Glossaire

Comment initializeUpload de LinkedIn transforme un fichier en URN d'image

Taras Shynkarenko
Taras Shynkarenko
Mis à jour : 8 min de lecture
Comment initializeUpload de LinkedIn transforme un fichier en URN d'imageComment initializeUpload de LinkedIn transforme un fichier en URN d'image

TL;DR, Réponse Rapide

8 min de lecture

Publier une image sur LinkedIn demande trois appels. POST /rest/images?action=initializeUpload enregistre l'envoi et renvoie une uploadUrl, un horodatage uploadUrlExpiresAt et un URN d'image de la forme urn:li:image:{id}. Vous envoyez ensuite le fichier vers cette URL, ce que la page Assets documente comme un PUT portant un jeton OAuth, et vous référencez l'URN sous content.media.id sur POST /rest/posts. Chaque étape a son propre tableau d'erreurs, et LinkedIn ne documente aucune voie de reprise après un envoi raté, hormis tout recommencer.

Que fait l'appel initializeUpload de LinkedIn ?

Un appel initializeUpload de LinkedIn enregistre un envoi d'image avant qu'un seul octet ne bouge, et rend l'URL vers laquelle envoyer le fichier plus l'URN que le post référencera. La description de LinkedIn tient en trois phrases : « Use the initializeUpload action to register the upload. When you initialize, you declare the upcoming upload. Use the upload URL to upload the image. »

L'appel est une action de l'Images API, passée en paramètre de requête :

POST https://api.linkedin.com/rest/images?action=initializeUpload
Authorization: Bearer {INSERT_TOKEN}
Linkedin-Version: 202608
X-Restli-Protocol-Version: 2.0.0

{
  "initializeUploadRequest": {
    "owner": "urn:li:organization:5583111"
  }
}

Un seul champ obligatoire, initializeUploadRequest.owner, décrit comme l'« URN of the entity that owns this asset. Can be a person(urn:li:person:123), or organization(urn:li:organization:123) URN. » Cela vaut la peine de le lire face au schéma de l'image lui-même, où le champ owner de premier niveau accepte aussi un URN sponsoredAccount. La requête d'initialisation ne liste que person et organization.

Le second champ, facultatif, enregistre en même temps l'asset dans la médiathèque d'un compte publicitaire :

{
  "initializeUploadRequest": {
    "owner": "urn:li:organization:2414183",
    "mediaLibraryMetadata": {
      "associatedAccount": "urn:li:sponsoredAccount:123456789",
      "assetName": "My media library asset"
    }
  }
}

mediaLibraryMetadata.mediaLibraryStatus « defaults to ACTIVE on creation », donc un asset de médiathèque est actif dès la fin de son traitement.

Une note que la documentation place dans un encadré, parce qu'elle casse une habitude héritée de l'ancienne Assets API : « SYNCHRONOUS_UPLOAD is not supported in Images API. » Il n'y a pas de raccourci en un seul appel. Les trois étapes sont toute la surface.

Que renvoie initializeUpload ?

Un 200 avec trois valeurs, enveloppées dans value :

{
   "value": {
       "uploadUrlExpiresAt": 1650567510704,
       "uploadUrl": "https://www.linkedin.com/dms-uploads/C4E10AQFoyyAjHPMQuQ/uploaded-image/0?ca=vector_ads&cn=uploads&sync=0&v=beta&ut=08zHQjMjAOLqc1",
       "image": "urn:li:image:C4E10AQFoyyAjHPMQuQ"
   }
}

La valeur image est l'URN, et c'est la pièce à conserver. Tout ce qui suit désigne l'image par cette chaîne : le corps du post, le GET qui vérifie le statut de traitement, la liste de la médiathèque. Remarquez que l'identifiant contenu dans l'URN est le même que celui contenu dans le chemin de l'URL d'envoi, ce qui rend les deux faciles à rapprocher dans les logs.

uploadUrlExpiresAt est en millisecondes depuis l'epoch. LinkedIn ne publie pas la durée de la fenêtre, donc la bonne chose à faire est de lire l'horodatage plutôt que de supposer une durée. Une file qui initialise un lot d'envois plusieurs heures avant d'expédier les fichiers dépend d'un chiffre que personne n'a documenté.

L'URN d'image a aussi une forme qu'il vaut mieux valider de votre côté, puisque l'Images API rejette les URN malformés avec une erreur dédiée. urn:li:image: suivi de l'identifiant, et rien d'autre. L'Images API accepte les « Images with less than 36,152,320 pixels » aux formats « JPG, GIF, and PNG formats », le « GIF format supports up to 250 frames. »

Un écran de téléphone affichant un envoi de fichier en cours, l'étape où les octets de l'image sont envoyés vers l'URL issue d'initializeUpload.

Comment envoyer les octets de l'image ?

Vers l'uploadUrl, avec le fichier en corps de requête et le même jeton bearer attaché. La page Assets vers laquelle l'Images API renvoie pour cette étape est explicite sur la méthode : « Use the uploadUrl from the previous step to upload the image. Use a PUT method to upload the image. The upload call requires a valid OAuth token in the 'Authorization' header. This is different than the upload video call which doesn't accept an OAuth token. »

curl -i --upload-file ~/Desktop/Myimage.jpg \
  -H 'Authorization: Bearer Redacted' \
  "https://www.linkedin.com/dms-uploads/C5622AQHdBDflPp0pEg/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&sync=1&v=beta&ut=1lrKqjt4fYuqw1"

Un envoi réussi répond HTTP/2 201 avec content-length: 0. Pas de corps, pas de JSON, rien à analyser. La seule chose que vous apprenez est le code de statut.

LinkedIn se contredit sur le verbe, et mieux vaut le savoir avant de déboguer un 405. Le guide grand public Share on LinkedIn, qui couvre l'ancien flux /v2/assets, dit d'« send a POST request to the uploadUrl with your image or video included as a binary file », puis le démontre avec curl -i --upload-file, qui est un PUT. La page Assets dit PUT en prose et montre la même commande. La commande est la partie fiable des deux pages.

Après l'envoi, GET https://api.linkedin.com/rest/images/urn:li:image:C4E10AQFn10iWtKexVA renvoie l'asset avec un champ status. Les valeurs documentées sont WAITING_UPLOAD (« Waiting for client to upload source file or uploading process to be completed »), PROCESSING, AVAILABLE (« All of the recipe's required artifacts are ready. The asset is available to be served ») et PROCESSING_FAILED, que le schéma attribue à un « client error such as file size too large, unsupported file format, internal error. »

AdaptlyPost
AdaptlyPost

Essai gratuit de 7 jours

Analyses multiplateforme

Boîte sociale

Assistant IA

Un piège de permission sur ce GET : l'Images API exige rw_ads, w_member_social, w_organization_social ou w_power_creators, et LinkedIn note que « w_member_social permission are write-only and tokens with only w_member_social permissions would be unable to perform a GET call for rest/images. » Une intégration à portée membre peut envoyer et ne peut pas sonder.

Comment référencer l'URN d'image dans un post ?

Sous content.media.id sur la Posts API, à côté du texte alternatif :

POST https://api.linkedin.com/rest/posts

{
  "author": "urn:li:organization:5515715",
  "commentary": "test strings!",
  "visibility": "PUBLIC",
  "distribution": {
    "feedDistribution": "MAIN_FEED",
    "targetEntities": [],
    "thirdPartyDistributionChannels": []
  },
  "content": {
    "media": {
      "altText": "testing for alt tags",
      "id": "urn:li:image:C5610AQFj6TdYowm17w"
    }
  },
  "lifecycleState": "PUBLISHED",
  "isReshareDisabledByAuthor": false
}

« A successful response returns a 201 Created HTTP status code and the ID in the x-restli-id response header. » L'URN du post revient dans un en-tête, pas dans le corps, et il ressemble à urn:li:share:6844785523593134080 ou urn:li:ugcPost:68447855235931240. Les intégrations qui ne lisent que les corps de réponse perdent l'identifiant du post entièrement.

L'altText sur cet objet media porte son propre plafond documenté, traité dans l'analyse de l'endroit où LinkedIn écrit sa limite de texte alternatif. Pour un post multi-images, les mêmes URN vont dans un tableau images à la place, avec un minimum de 2 et un maximum de 20.

Une personne lisant un message d'erreur sur l'écran d'un ordinateur portable, à l'image du débogage qui suit un appel d'envoi ou de publication échoué.

Quelles erreurs apparaissent à chaque étape ?

Trois étapes, trois tableaux d'erreurs séparés, et ils ne se recoupent pas.

ÉtapeStatutCodeCe que cela veut dire
initializeUpload400INVALID_URN_TYPE« {field} value {value} must be a {urnType} URN »
initializeUpload400INVALID_URN_ID« This URN ID is invalid »
initializeUpload403aucun publié« Accessing this image resource is forbidden. Please check your permissions for this resource »
initializeUpload400VERSION_MISSINGL'en-tête de version a été omis de la requête
PUT d'envoi401UNAUTHORIZED« The OAuth token is missing, invalid, or expired »
PUT d'envoi413REQUEST_ENTITY_TOO_LARGE« The uploaded file exceeds the allowed size limit »
PUT d'envoi415UNSUPPORTED_MEDIA_TYPE« The uploaded file format is not supported »
PUT d'envoi422UNPROCESSABLE_ENTITY« The server understands the request but can't process it »
POST /rest/posts400INVALID_URN_TYPE« Verify the URN type used for fields such as author or content.media.id »
POST /rest/posts400MISSING_FIELDauthor, visibility, distribution ou lifecycleState absent
POST /rest/posts403ACCESS_DENIEDScope accordé mais le membre n'a pas le rôle sur la page entreprise
POST /rest/posts429TOO_MANY_REQUESTS« The API rate limit has been exceeded »

Le 403 sur l'initialisation est celui à lire attentivement, parce que LinkedIn le publie sous forme de corps brut plutôt que de code, et parce que sa cause est le plus souvent un rôle de page plutôt qu'un scope. Les vérifications de permission documentées sont fondées sur les rôles : « For images with company URN owners, the caller must have ADMIN or DSC permissions for the company page », et « For images with member URN owners, the caller must match the image owner. »

Un en-tête de version manquant fait échouer l'appel d'initialisation avant que rien de tout cela ne soit évalué, avec 400 VERSION_MISSING et le message « A version must be present. Please specify a version by adding the Linkedin-Version header. » Les règles de cet en-tête, y compris ce que renvoie une valeur retirée du service, méritent d'être lues à côté de ce flux dans l'article sur l'en-tête de version que chaque appel /rest/ exige.

Qu'est-ce que LinkedIn laisse sans documentation ici ?

Trois choses, et chacune est une décision que vous devez prendre sans citation.

Combien de temps l'URL d'envoi dure. Vous obtenez uploadUrlExpiresAt dans la réponse et aucune durée annoncée nulle part sur la page, donc un planificateur qui envoie des lots doit traiter l'horodatage comme le contrat.

S'il faut attendre AVAILABLE avant de créer le post. Les valeurs de statut sont documentées, le GET qui les renvoie est documenté, et la relation entre les deux et l'appel POST /rest/posts ne l'est pas. Le schéma prudent est de sonder jusqu'à AVAILABLE, et c'est un usage plutôt qu'une règle.

Quoi faire de PROCESSING_FAILED. Le schéma nomme les causes et s'arrête là. Aucun endpoint de reprise n'est documenté, ce qui en pratique veut dire initialiser un nouvel envoi et obtenir un nouvel URN. Les équipes qui font tourner cela à volume par un planificateur de posts LinkedIn finissent par construire cette reprise elles-mêmes, comme elles le font pour d'autres API de publication à flux média en trois étapes.

Trois décisions non documentées
1
Durée de vie de l'URL d'upload. Aucune durée n'est publiée, donc uploadUrlExpiresAt reste la seule garantie.
2
Attendre AVAILABLE. Interroger le statut jusqu'à ce qu'il change est une pratique, pas une règle documentée.
3
PROCESSING_FAILED. Aucun endpoint de nouvelle tentative n'existe, la solution consiste donc en un nouvel appel initializeUpload et une nouvelle URN.
Chacune de ces trois décisions se prend sans citation de la documentation LinkedIn.

Questions fréquentes

Quel est l'endpoint initializeUpload de LinkedIn ?

POST https://api.linkedin.com/rest/images?action=initializeUpload. C'est une action de l'Images API qui enregistre un envoi et renvoie une uploadUrl, un horodatage uploadUrlExpiresAt et un URN image, avant qu'aucune donnée de fichier ne soit envoyée.

À quoi ressemble l'URN d'image renvoyé par initializeUpload ?

urn:li:image:{id}, par exemple urn:li:image:C4E10AQFoyyAjHPMQuQ. Le même identifiant apparaît dans le chemin de l'URL d'envoi renvoyée, et l'URN est ce que vous passez sous content.media.id quand vous créez le post.

Quelle méthode HTTP envoie l'image à LinkedIn ?

PUT. La page Assets indique « Use a PUT method to upload the image » et exige « a valid OAuth token in the 'Authorization' header », et un envoi réussi renvoie 201 avec un corps vide. La prose du guide grand public dit POST, mais son propre exemple curl utilise --upload-file, qui envoie un PUT.

AdaptlyPost
AdaptlyPost

Essai gratuit de 7 jours

Analyses multiplateforme

Boîte sociale

Assistant IA

Faut-il attendre la fin du traitement de l'image avant de publier ?

LinkedIn ne documente aucune attente obligatoire. Il documente un champ status sur l'image avec les valeurs WAITING_UPLOAD, PROCESSING, AVAILABLE et PROCESSING_FAILED, et sonder GET /rest/images/{urn} jusqu'à AVAILABLE est la lecture prudente de tout cela.

Pourquoi initializeUpload renvoie-t-il 403 ?

Le corps documenté est « Accessing this image resource is forbidden. Please check your permissions for this resource » avec "status": 403. Les vérifications de permission sont fondées sur les rôles : un propriétaire à URN d'entreprise exige les permissions ADMIN ou DSC sur la page, et un propriétaire à URN de membre doit correspondre à l'appelant.

Un jeton limité à w_member_social peut-il utiliser l'Images API ?

Pour les écritures, oui. LinkedIn indique que « w_member_social permission are write-only and tokens with only w_member_social permissions would be unable to perform a GET call for rest/images », donc un tel jeton peut initialiser et envoyer, mais pas sonder le statut de l'image sur l'endpoint versionné.

Quels formats et tailles d'image accepte l'Images API de LinkedIn ?

L'Images API accepte les fichiers JPG, GIF et PNG, plafonnés à 36 152 320 pixels. Les GIF peuvent aller jusqu'à 250 images. Ces limites s'appliquent à toute image du flux en trois étapes, pas à une seule étape en particulier.

L'Images API de LinkedIn prend-elle en charge l'upload synchrone ?

Elle ne le fait pas. LinkedIn le précise dans un encadré : "SYNCHRONOUS_UPLOAD is not supported in Images API." Les trois appels, initializeUpload, le PUT et POST /rest/posts, forment tout le flux, sans le raccourci en une étape que certains gardent de l'ancienne Assets API.

Quels scopes OAuth donnent accès à l'Images API de LinkedIn ?

rw_ads, w_member_social, w_organization_social ou w_power_creators. Chacun des quatre couvre initializeUpload et le PUT d'upload, mais w_member_social seul ne permet pas de lire le statut de l'image avec un GET, puisque LinkedIn documente ce scope comme réservé à l'écriture.

Combien d'images un post LinkedIn peut-il contenir ?

Un post à une seule image référence une URN via content.media.id. Un post à plusieurs images utilise à la place un tableau images, que LinkedIn impose avec un minimum de 2 et un maximum de 20 URN.

Cet article vous a-t-il été utile ?

Dites-nous ce que vous en pensez !

Nous voir plus souvent sur Google

Un clic définit AdaptlyPost comme source préférée. Nos articles remontent alors dans vos À la une, en mode IA et dans les aperçus IA.

Avant de partir...

AdaptlyPost

AdaptlyPost

Planifiez vos contenus sur toutes les plateformes

Gérez tous vos comptes de réseaux sociaux en un seul endroit avec AdaptlyPost.

Analyses multiplateforme

Boîte sociale

Assistant IA

Termes connexes du glossaire

Articles Connexes