Glossário

Como o initializeUpload do LinkedIn transforma um arquivo em URN de imagem

Taras Shynkarenko
Taras Shynkarenko
Atualizado: 8 min de leitura
Como o initializeUpload do LinkedIn transforma um arquivo em URN de imagemComo o initializeUpload do LinkedIn transforma um arquivo em URN de imagem

TL;DR, Resposta Rápida

8 min de leitura

Postar uma imagem no LinkedIn leva três chamadas. O POST /rest/images?action=initializeUpload registra o upload e devolve uma uploadUrl, um timestamp uploadUrlExpiresAt e uma URN de imagem na forma urn:li:image:{id}. Você então manda o arquivo para essa URL, o que a página Assets documenta como um PUT carregando um token OAuth, e referencia a URN como content.media.id no POST /rest/posts. Cada passo tem sua própria tabela de erros, e o LinkedIn não documenta caminho de retry para um upload que falhou além de começar de novo.

O que a chamada initializeUpload do LinkedIn faz?

Uma chamada initializeUpload do LinkedIn registra um upload de imagem antes de um único byte se mover, e devolve a URL para onde mandar o arquivo mais a URN que o post vai referenciar. A descrição do próprio LinkedIn são três 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."

A chamada é uma ação na Images API, passada 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"
  }
}

Um campo obrigatório, initializeUploadRequest.owner, descrito como a "URN of the entity that owns this asset. Can be a person(urn:li:person:123), or organization(urn:li:organization:123) URN." Vale ler isso contra o próprio schema da imagem, em que o campo owner de topo também aceita uma URN de sponsoredAccount. A requisição de inicialização lista apenas pessoa e organização.

O segundo campo, opcional, registra o ativo na biblioteca de mídia de uma conta de anúncios ao mesmo tempo:

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

O mediaLibraryMetadata.mediaLibraryStatus "defaults to ACTIVE on creation," então um ativo de biblioteca fica no ar no instante em que termina o processamento.

Uma nota que a documentação põe num destaque, porque quebra um padrão que as pessoas trazem da antiga Assets API: "SYNCHRONOUS_UPLOAD is not supported in Images API." Não existe atalho de chamada única. Os três passos são a superfície inteira.

O que o initializeUpload devolve?

Um 200 com três valores, embrulhados em 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"
   }
}

O valor de image é a URN, e é a peça a guardar. Tudo a jusante se refere à imagem por essa string: o corpo do post, o GET que checa o status de processamento, a listagem da biblioteca de mídia. Repare que o identificador dentro da URN é o mesmo identificador dentro do caminho da URL de upload, o que torna os dois fáceis de correlacionar nos logs.

O uploadUrlExpiresAt está em milissegundos desde a época. O LinkedIn não publica quanto dura a janela, então a coisa certa a fazer é ler o timestamp em vez de assumir uma duração. Uma fila que inicializa um lote de uploads horas antes de mandar os arquivos está dependendo de um número que ninguém documentou.

A URN de imagem também tem um formato que vale validar do seu lado, já que a Images API rejeita as malformadas com um erro dedicado. urn:li:image: seguido do identificador, e nada mais. A Images API aceita "Images with less than 36,152,320 pixels" em "JPG, GIF, and PNG formats," com "GIF format supports up to 250 frames."

Uma tela de celular mostrando um envio de arquivo em andamento, a etapa em que os bytes da imagem vão para a URL do initializeUpload.

Como você sobe os bytes da imagem?

Para a uploadUrl, com o arquivo no corpo e o mesmo bearer token anexado. A página Assets para onde a Images API aponta nesse passo é explícita sobre o 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"

Um upload bem-sucedido responde HTTP/2 201 com content-length: 0. Sem corpo, sem JSON, nada a analisar. A única coisa que você aprende é o código de status.

O LinkedIn se contradiz sobre o verbo, e vale saber disso antes de depurar um 405. O guia consumidor Share on LinkedIn, que cobre o fluxo antigo /v2/assets, diz para "send a POST request to the uploadUrl with your image or video included as a binary file," e depois demonstra com curl -i --upload-file, que é um PUT. A página Assets diz PUT no texto e mostra o mesmo comando. O comando é a parte confiável das duas páginas.

Depois do upload, GET https://api.linkedin.com/rest/images/urn:li:image:C4E10AQFn10iWtKexVA devolve o ativo com um campo status. Os valores documentados são 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") e PROCESSING_FAILED, que o schema atribui a "client error such as file size too large, unsupported file format, internal error."

AdaptlyPost
AdaptlyPost

Teste grátis de 7 dias

Análises multiplataforma

Caixa Social

Assistente com IA

Uma armadilha de permissão nesse GET: a Images API exige rw_ads, w_member_social, w_organization_social ou w_power_creators, e o LinkedIn nota 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." Uma integração com escopo de membro consegue subir e não consegue consultar.

Como referenciar a URN de imagem em um post?

Como content.media.id na Posts API, ao lado do alt text:

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." A URN do post volta num cabeçalho, não no corpo, e se parece com urn:li:share:6844785523593134080 ou urn:li:ugcPost:68447855235931240. Integrações que só leem corpos de resposta perdem o ID do post inteiro.

O altText nesse objeto de mídia carrega seu próprio teto documentado, coberto no detalhamento sobre onde o LinkedIn escreve o seu limite de alt text. Para um post com múltiplas imagens as mesmas URNs vão para um array images, com mínimo de 2 e máximo de 20.

Uma pessoa lendo uma mensagem de erro na tela de um laptop, refletindo a depuração que segue uma chamada de upload ou post malsucedida.

Que erros aparecem em cada passo?

Três passos, três tabelas de erro separadas, e elas não se sobrepõem.

PassoStatusCódigoO que significa
initializeUpload400INVALID_URN_TYPE"{field} value {value} must be a {urnType} URN"
initializeUpload400INVALID_URN_ID"This URN ID is invalid"
initializeUpload403nenhum publicado"Accessing this image resource is forbidden. Please check your permissions for this resource"
initializeUpload400VERSION_MISSINGO cabeçalho de versão ficou de fora da requisição
Upload PUT401UNAUTHORIZED"The OAuth token is missing, invalid, or expired"
Upload PUT413REQUEST_ENTITY_TOO_LARGE"The uploaded file exceeds the allowed size limit"
Upload PUT415UNSUPPORTED_MEDIA_TYPE"The uploaded file format is not supported"
Upload PUT422UNPROCESSABLE_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 ausente
POST /rest/posts403ACCESS_DENIEDEscopo concedido, mas o membro não tem o papel na página da empresa
POST /rest/posts429TOO_MANY_REQUESTS"The API rate limit has been exceeded"

O 403 na inicialização é o que precisa ser lido com cuidado, porque o LinkedIn o publica como corpo cru em vez de código, e porque sua causa costuma ser um papel na página e não um escopo. As checagens de permissão documentadas são baseadas em papel: "For images with company URN owners, the caller must have ADMIN or DSC permissions for the company page," e "For images with member URN owners, the caller must match the image owner."

Um cabeçalho de versão ausente faz a chamada de inicialização falhar antes de qualquer uma dessas avaliações, com 400 VERSION_MISSING e a mensagem "A version must be present. Please specify a version by adding the Linkedin-Version header." As regras desse cabeçalho, incluindo o que um valor descontinuado devolve, valem ser lidas junto deste fluxo no texto sobre o cabeçalho de versão que toda chamada /rest/ exige.

O que o LinkedIn deixa sem documentar aqui?

Três coisas, e cada uma é uma decisão que você toma sem citação.

Quanto tempo a URL de upload dura. Você recebe o uploadUrlExpiresAt na resposta e nenhuma duração declarada em lugar algum da página, então um agendador que faz uploads em lote tem que tratar o timestamp como o contrato.

Se você precisa esperar o AVAILABLE antes de criar o post. Os valores de status são documentados, o GET que os devolve é documentado, e a relação entre os dois e a chamada POST /rest/posts não é. O padrão seguro é consultar até AVAILABLE, e isso é um padrão, não uma regra.

O que fazer com o PROCESSING_FAILED. O schema nomeia as causas e para por aí. Nenhum endpoint de retry é documentado, o que na prática significa inicializar um upload novo e receber uma URN nova. Times que rodam isso em volume por um agendador de posts do LinkedIn acabam construindo esse retry por conta própria, do mesmo jeito que fazem para outras APIs de publicação com fluxos de mídia em três passos.

Três decisões sem documentação
1
Duração da URL de upload. Nenhuma duração é publicada, então uploadUrlExpiresAt é a única garantia.
2
Esperar por AVAILABLE. Consultar o status até ele mudar é um padrão, não uma regra documentada.
3
PROCESSING_FAILED. Não existe endpoint de nova tentativa, então a solução é uma nova chamada a initializeUpload e uma URN nova.
Cada uma dessas três decisões é tomada sem uma citação da documentação do LinkedIn.

Perguntas frequentes

O que é o endpoint initializeUpload do LinkedIn?

POST https://api.linkedin.com/rest/images?action=initializeUpload. É uma ação na Images API que registra um upload e devolve uma uploadUrl, um timestamp uploadUrlExpiresAt e uma URN image, antes de qualquer dado de arquivo ser enviado.

Com o que se parece a URN de imagem do initializeUpload?

urn:li:image:{id}, por exemplo urn:li:image:C4E10AQFoyyAjHPMQuQ. O mesmo identificador aparece dentro do caminho da URL de upload devolvida, e a URN é o que você passa como content.media.id ao criar o post.

Qual método HTTP sobe a imagem para o LinkedIn?

PUT. A página Assets afirma "Use a PUT method to upload the image" e exige "a valid OAuth token in the 'Authorization' header," e um upload bem-sucedido devolve 201 com corpo vazio. O texto do guia consumidor diz POST, mas o próprio exemplo em curl usa --upload-file, que envia um PUT.

AdaptlyPost
AdaptlyPost

Teste grátis de 7 dias

Análises multiplataforma

Caixa Social

Assistente com IA

É preciso esperar a imagem terminar o processamento antes de postar?

O LinkedIn não documenta uma espera obrigatória. Ele documenta um campo status na imagem com os valores WAITING_UPLOAD, PROCESSING, AVAILABLE e PROCESSING_FAILED, e consultar GET /rest/images/{urn} até AVAILABLE é a leitura segura disso.

Por que o initializeUpload devolve 403?

O corpo documentado é "Accessing this image resource is forbidden. Please check your permissions for this resource" com "status": 403. As checagens de permissão são baseadas em papel: um dono com URN de empresa exige permissões ADMIN ou DSC na página, e um dono com URN de membro tem que coincidir com quem chama.

Um token só com w_member_social pode usar a Images API?

Para escritas, sim. O 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," então um token desses consegue inicializar e subir, mas não consegue consultar o status da imagem no endpoint versionado.

Que formatos e tamanhos de imagem a Images API do LinkedIn aceita?

A Images API aceita arquivos JPG, GIF e PNG, com limite de 36.152.320 pixels. Os GIFs podem ter até 250 quadros. Esses limites valem para qualquer imagem do fluxo de três passos, não para um passo específico.

A Images API do LinkedIn aceita upload síncrono?

Ela não aceita. O LinkedIn deixa isso num aviso: "SYNCHRONOUS_UPLOAD is not supported in Images API." As três chamadas, initializeUpload, o PUT e POST /rest/posts, são todo o fluxo, sem o atalho de uma chamada só que alguns trazem da antiga Assets API.

Que escopos OAuth permitem usar a Images API do LinkedIn?

rw_ads, w_member_social, w_organization_social ou w_power_creators. Qualquer um dos quatro cobre initializeUpload e o PUT de upload, mas w_member_social sozinho não consegue ler o status da imagem com um GET, porque o LinkedIn documenta esse escopo como somente de escrita.

Quantas imagens um post do LinkedIn pode ter?

Um post de uma imagem referencia uma URN via content.media.id. Um post com várias imagens usa em vez disso um array images, que o LinkedIn exige com no mínimo 2 e no máximo 20 URNs.

Este artigo foi útil para você?

Conte-nos o que você achou!

Veja-nos mais no Google

Um clique marca a AdaptlyPost como fonte preferida e nossos artigos passam a aparecer mais acima nas suas Principais notícias, no modo IA e nas visões gerais com IA.

Antes de ir...

AdaptlyPost

AdaptlyPost

Agende seu conteúdo em todas as plataformas

Gerencie todas as suas contas de redes sociais em um só lugar com o AdaptlyPost.

Análises multiplataforma

Caixa Social

Assistente com IA

Termos relacionados do glossário

Artigos Relacionados