TL;DR, Respuesta Rápida
9 min de lecturaPublicar una imagen en LinkedIn cuesta tres llamadas. POST /rest/images?action=initializeUpload registra la subida y devuelve un uploadUrl, una marca de tiempo uploadUrlExpiresAt y un URN de imagen con la forma urn:li:image:{id}. Luego envías el archivo a esa URL, algo que la página de Assets documenta como un PUT con un token OAuth, y referencias el URN como content.media.id en POST /rest/posts. Cada paso tiene su propia tabla de errores, y LinkedIn no documenta ninguna vía de reintento para una subida fallida más allá de empezar de nuevo.
¿Qué hace la llamada initializeUpload de LinkedIn?
Una llamada initializeUpload de LinkedIn registra la subida de una imagen antes de que se mueva un solo byte, y devuelve la URL a la que enviar el archivo más el URN al que apuntará el post. La descripción del propio LinkedIn son tres frases: "Use the initializeUpload action to register the upload. When you initialize, you declare the upcoming upload. Use the upload URL to upload the image."
La llamada es una acción de la Images API, pasada como parámetro de consulta:
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 campo obligatorio, initializeUploadRequest.owner, descrito como el "URN of the entity that owns this asset. Can be a person(urn:li:person:123), or organization(urn:li:organization:123) URN." Merece la pena leerlo frente al propio esquema de imagen, donde el campo owner de primer nivel también acepta un URN sponsoredAccount. La petición de inicialización solo lista persona y organización.
El segundo campo opcional registra el recurso en la biblioteca de medios de una cuenta publicitaria al mismo tiempo:
{
"initializeUploadRequest": {
"owner": "urn:li:organization:2414183",
"mediaLibraryMetadata": {
"associatedAccount": "urn:li:sponsoredAccount:123456789",
"assetName": "My media library asset"
}
}
}
mediaLibraryMetadata.mediaLibraryStatus "defaults to ACTIVE on creation," así que un recurso de biblioteca está activo en cuanto termina de procesarse.
Una nota que la documentación mete en un recuadro, porque rompe un patrón que la gente arrastra de la vieja Assets API: "SYNCHRONOUS_UPLOAD is not supported in Images API." No hay atajo de una sola llamada. Los tres pasos son toda la superficie.
¿Qué devuelve initializeUpload?
Un 200 con tres valores, envueltos en 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"
}
}
El valor image es el URN, y es la pieza que hay que guardar. Todo lo que viene después se refiere a la imagen por esa cadena: el cuerpo del post, el GET que comprueba el estado de procesamiento, el listado de la biblioteca de medios. Fíjate en que el identificador dentro del URN es el mismo que hay dentro de la ruta de la URL de subida, lo que hace fácil correlacionar las dos en los logs.
uploadUrlExpiresAt son milisegundos desde el epoch. LinkedIn no publica cuánto dura la ventana, así que lo correcto es leer la marca de tiempo en lugar de suponer una duración. Una cola que inicializa un lote de subidas horas antes de enviar los archivos depende de un número que nadie ha documentado.
El URN de imagen también tiene una forma que conviene validar por tu lado, ya que la Images API rechaza los malformados con un error propio. urn:li:image: seguido del identificador, y nada más. La Images API acepta "Images with less than 36,152,320 pixels" en "JPG, GIF, and PNG formats," con "GIF format supports up to 250 frames."

¿Cómo subes los bytes de la imagen?
A la uploadUrl, con el archivo como cuerpo y el mismo token bearer adjunto. La página de Assets a la que la Images API remite para este paso es explícita sobre el método: "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"
Una subida correcta responde HTTP/2 201 con content-length: 0. Sin cuerpo, sin JSON, nada que parsear. Lo único que averiguas es el código de estado.
LinkedIn se contradice en el verbo, y conviene saberlo antes de depurar un 405. La guía de consumo Share on LinkedIn, que cubre el flujo antiguo de /v2/assets, dice que envíes "a POST request to the uploadUrl with your image or video included as a binary file," y luego lo demuestra con curl -i --upload-file, que es un PUT. La página de Assets dice PUT en la prosa y enseña el mismo comando. El comando es la parte fiable de las dos páginas.
Después de la subida, GET https://api.linkedin.com/rest/images/urn:li:image:C4E10AQFn10iWtKexVA devuelve el recurso con un campo status. Los valores documentados son 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") y PROCESSING_FAILED, que el esquema atribuye a "client error such as file size too large, unsupported file format, internal error."
AdaptlyPost
Prueba gratis de 7 días
Analíticas multiplataforma
Bandeja Social
Asistente con IA
Una trampa de permisos en ese GET: la Images API requiere rw_ads, w_member_social, w_organization_social o w_power_creators, y LinkedIn señala 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." Una integración con alcance de miembro puede subir y no puede consultar.
¿Cómo referencias el URN de imagen en un post?
Como content.media.id en la Posts API, junto al texto alternativo:
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." El URN del post vuelve en una cabecera, no en el cuerpo, y tiene el aspecto de urn:li:share:6844785523593134080 o urn:li:ugcPost:68447855235931240. Las integraciones que solo leen cuerpos de respuesta pierden el ID del post por completo.
El altText de ese objeto de medios lleva su propio techo documentado, cubierto en el desglose de dónde escribe LinkedIn su límite de texto alternativo. Para un post de varias imágenes, los mismos URN van a un array images, con un mínimo de 2 y un máximo de 20.

¿Qué errores aparecen en cada paso?
Tres pasos, tres tablas de errores separadas, y no se solapan.
| Paso | Estado | Código | Qué significa |
|---|---|---|---|
initializeUpload | 400 | INVALID_URN_TYPE | "{field} value {value} must be a {urnType} URN" |
initializeUpload | 400 | INVALID_URN_ID | "This URN ID is invalid" |
initializeUpload | 403 | ninguno publicado | "Accessing this image resource is forbidden. Please check your permissions for this resource" |
initializeUpload | 400 | VERSION_MISSING | Se omitió la cabecera de versión en la petición |
PUT de subida | 401 | UNAUTHORIZED | "The OAuth token is missing, invalid, or expired" |
PUT de subida | 413 | REQUEST_ENTITY_TOO_LARGE | "The uploaded file exceeds the allowed size limit" |
PUT de subida | 415 | UNSUPPORTED_MEDIA_TYPE | "The uploaded file format is not supported" |
PUT de subida | 422 | UNPROCESSABLE_ENTITY | "The server understands the request but can't process it" |
POST /rest/posts | 400 | INVALID_URN_TYPE | "Verify the URN type used for fields such as author or content.media.id" |
POST /rest/posts | 400 | MISSING_FIELD | Falta author, visibility, distribution o lifecycleState |
POST /rest/posts | 403 | ACCESS_DENIED | Scope concedido pero el miembro no tiene el rol en la página de empresa |
POST /rest/posts | 429 | TOO_MANY_REQUESTS | "The API rate limit has been exceeded" |
El 403 de la inicialización es el que hay que leer con cuidado, porque LinkedIn lo publica como cuerpo en bruto y no como código, y porque su causa suele ser un rol de página más que un scope. Las comprobaciones de permisos documentadas son por rol: "For images with company URN owners, the caller must have ADMIN or DSC permissions for the company page," y "For images with member URN owners, the caller must match the image owner."
Una cabecera de versión ausente hace fallar la llamada de inicialización antes de evaluar nada de eso, con 400 VERSION_MISSING y el mensaje "A version must be present. Please specify a version by adding the Linkedin-Version header." Las reglas de esa cabecera, incluido qué devuelve un valor retirado, conviene leerlas junto a este flujo en la pieza sobre la cabecera de versión que necesita cada llamada /rest/.
¿Qué deja LinkedIn sin documentar aquí?
Tres cosas, y cada una es una decisión que tienes que tomar sin cita que la respalde.
Cuánto dura la URL de subida. Recibes uploadUrlExpiresAt en la respuesta y ninguna duración declarada en toda la página, así que un programador que agrupe subidas tiene que tratar la marca de tiempo como el contrato.
Si hay que esperar a AVAILABLE antes de crear el post. Los valores de estado están documentados, el GET que los devuelve está documentado, y la relación entre ambos y la llamada POST /rest/posts no lo está. El patrón seguro es consultar hasta AVAILABLE, y es un patrón, no una regla.
Qué hacer con PROCESSING_FAILED. El esquema nombra las causas y ahí se para. No hay endpoint de reintento documentado, lo que en la práctica significa inicializar una subida nueva y conseguir un URN nuevo. Los equipos que hacen esto a volumen con un programador de publicaciones de LinkedIn acaban construyendo ese reintento por su cuenta, igual que hacen con otras APIs de publicación con flujos de medios en tres pasos.
Preguntas frecuentes
¿Qué es el endpoint initializeUpload de LinkedIn?
POST https://api.linkedin.com/rest/images?action=initializeUpload. Es una acción de la Images API que registra una subida y devuelve un uploadUrl, una marca de tiempo uploadUrlExpiresAt y un URN image, antes de enviar ningún dato del archivo.
¿Qué aspecto tiene el URN de imagen de initializeUpload?
urn:li:image:{id}, por ejemplo urn:li:image:C4E10AQFoyyAjHPMQuQ. El mismo identificador aparece dentro de la ruta de la URL de subida devuelta, y el URN es lo que pasas como content.media.id al crear el post.
¿Qué método HTTP sube la imagen a LinkedIn?
PUT. La página de Assets afirma "Use a PUT method to upload the image" y exige "a valid OAuth token in the 'Authorization' header," y una subida correcta devuelve 201 con el cuerpo vacío. La prosa de la guía de consumo dice POST, pero su propio ejemplo de curl usa --upload-file, que envía un PUT.
AdaptlyPost
Prueba gratis de 7 días
Analíticas multiplataforma
Bandeja Social
Asistente con IA
¿Hay que esperar a que la imagen termine de procesarse antes de publicar?
LinkedIn no documenta ninguna espera obligatoria. Documenta un campo status en la imagen con los valores WAITING_UPLOAD, PROCESSING, AVAILABLE y PROCESSING_FAILED, y consultar GET /rest/images/{urn} hasta AVAILABLE es la lectura segura de eso.
¿Por qué initializeUpload devuelve 403?
El cuerpo documentado es "Accessing this image resource is forbidden. Please check your permissions for this resource" con "status": 403. Las comprobaciones de permisos son por rol: un propietario con URN de empresa requiere permisos ADMIN o DSC en la página, y un propietario con URN de miembro tiene que coincidir con quien llama.
¿Puede un token con solo w_member_social usar la Images API?
Para escrituras, sí. LinkedIn afirma 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," así que ese token puede inicializar y subir pero no puede consultar el estado de la imagen en el endpoint versionado.
¿Qué formatos y tamaños de imagen acepta la Images API de LinkedIn?
La Images API acepta archivos JPG, GIF y PNG con un límite de 36.152.320 píxeles. Los GIF pueden llegar hasta 250 fotogramas. Estos límites se aplican a cualquier imagen del flujo de tres pasos, no a un paso en concreto.
¿La Images API de LinkedIn admite subida síncrona?
No la admite. LinkedIn lo deja en un aviso: "SYNCHRONOUS_UPLOAD is not supported in Images API." Las tres llamadas, initializeUpload, el PUT y POST /rest/posts, son todo el flujo, sin el atajo de un solo paso que algunos arrastran de la antigua Assets API.
¿Qué scopes de OAuth permiten usar la Images API de LinkedIn?
rw_ads, w_member_social, w_organization_social o w_power_creators. Cualquiera de los cuatro cubre initializeUpload y el PUT de subida, pero w_member_social por sí solo no puede leer el estado de la imagen con un GET, porque LinkedIn documenta ese scope como solo de escritura.
¿Cuántas imágenes puede llevar un post de LinkedIn?
Un post de una sola imagen referencia una URN mediante content.media.id. Un post de varias imágenes usa en su lugar un array images, que LinkedIn exige con un mínimo de 2 y un máximo de 20 URNs.
Ponlo en práctica con AdaptlyPost
¿Te resultó útil este artículo?
¡Cuéntanos qué te parece!
Vernos más en Google
Un clic marca AdaptlyPost como fuente preferida y nuestros artículos aparecen más arriba en tus Noticias destacadas, el modo IA y los resúmenes con IA.
Antes de irte...
AdaptlyPost
Programa tu contenido en todas las plataformas
Gestiona todas tus cuentas de redes sociales en un solo lugar con AdaptlyPost.
Analíticas multiplataforma
Bandeja Social
Asistente con IA
Términos relacionados del glosario


Dónde está escrito realmente el límite de caracteres del texto alternativo de LinkedIn
Hay un solo número: el límite de caracteres del texto alternativo de LinkedIn es 4.086 en el campo altText de la API, y la app no publica ninguno.


Qué devuelve el endpoint content_publishing_limit de Instagram
El endpoint content_publishing_limit de Instagram devuelve quota_usage más un bloque config con quota_total 50 y quota_duration 86400 segundos.


Por qué un token de acceso de LinkedIn caduca a los 60 días
Cada token de acceso de LinkedIn dura 60 días y expires_in devuelve 5184000. Reglas del refresh token, qué lo mata antes y en qué difieren los 60 días de Meta.
Artículos Relacionados


Solo LinkedIn publica una definición de dwell time en redes sociales
LinkedIn es la única red con una definición publicada de dwell time en redes sociales: se mide desde que al menos la mitad de un update es visible.


Meta fija en 1.000 el límite de caracteres de alt_text en la API de Instagram
Meta fija el límite de caracteres de alt_text en la API de Instagram en 1.000 y lo restringe a imágenes fijas. Reels y stories no admiten texto alternativo.


Por qué el límite de caracteres de la descripción de TikTok se mide en runas UTF-16
El límite de caracteres de la descripción de TikTok es de 2200 runas UTF-16 en video y 90 en un título de foto. Un emoji puede costar once runas.

