· Developers · 6 min de leitura

Enviando capturas de tela da App Store com a App Store Connect API

Enviando capturas de tela da App Store com a App Store Connect API
TL;DR. Enviar uma captura de tela pela App Store Connect API é uma sequência de quatro passos por imagem: criar um appScreenshotSet para o locale e dispositivo certos, reservar um appScreenshot (a Apple devolve URLs de blocos pré-assinadas), fazer o PUT dos bytes e, então, dar PATCH na reserva com uploaded: true e o MD5 do arquivo. A autenticação é um JWT de 20 minutos assinado com sua chave .p8. Nada disso é difícil; tudo é trabalhoso. Aqui está a sequência real — e o atalho para quem não quer construir isso do zero.

A documentação da Apple sobre isso é precisa e quase ilegível — o fluxo está espalhado em uma dezena de páginas de referência, sem um único exemplo completo. Este post é o passo a passo, em ordem, com os endpoints e nomes de campos exatos. É escrito para quem está decidindo entre construir a integração ou usar uma ferramenta que já faz isso.

O modelo de objetos em que você está enviando

As capturas de tela não se anexam diretamente ao seu app. Elas dependem de uma cadeia de objetos, e você precisa percorrê-la de cima para baixo:

  • appStoreVersion — a versão específica que você está editando (precisa estar em um estado editável).
  • appStoreVersionLocalization — um por locale da App Store (en-US, de-DE, ja, e assim por diante).
  • appScreenshotSet — um por tipo de exibição dentro de uma localização (iPhone de 6.7", iPad de 13", etc.).
  • appScreenshot — a imagem individual, até 10 por conjunto.

Ou seja, uma listagem totalmente localizada em 50 idiomas, com dois tamanhos de iPhone e um de iPad, é 50 × 3 conjuntos, cada um com até 10 capturas de tela. Essa multiplicação é a razão principal para automatizar isso em vez de clicar manualmente na interface web.

Passo 0 — o JWT de 20 minutos

Toda requisição, exceto os próprios uploads de bytes, precisa de um cabeçalho Authorization: Bearer carregando um JSON Web Token que você mesmo assina. Você precisa de três coisas da App Store Connect: seu issuer ID, um key ID e o arquivo de chave privada .p8 que você baixa uma única vez ao criar a chave (a Apple nunca a mostra de novo).

O token é assinado com ES256 — ECDSA na curva P-256 com SHA-256 — usando essa chave .p8. O cabeçalho carrega o kid; o payload carrega o emissor como iss, a audiência como a string literal appstoreconnect-v1, e um exp no máximo 20 minutos depois do iat. A Apple rejeita qualquer coisa com validade maior, então você regenera com frequência — gere um token novo por lote em vez de tentar manter um aberto.

Assine isso com qualquer biblioteca JWT compatível com ES256 (jsonwebtoken, PyJWT, o que sua stack usar), passe o conteúdo do .p8 como a chave e coloque o resultado no cabeçalho Authorization em cada chamada abaixo.

Passo 1 — criar o conjunto de capturas de tela

Um conjunto é vinculado a uma localização e um tipo de exibição. Você faz POST em /v1/appScreenshotSets com o screenshotDisplayType nos atributos e um relacionamento apontando para o appStoreVersionLocalization que você quer preencher.

Tipos de exibição comuns: APP_IPHONE_67 (6.7", 1290 × 2796), o tamanho atual de iPhone grande, e APP_IPAD_PRO_3GEN_129 (12.9", 2048 × 2732). Uma coisa útil que a Apple faz hoje: as capturas de tela do maior tamanho de iPhone são reaproveitadas nas classes menores de iPhone, e as do maior iPad, nos iPads menores — então, na prática, você geralmente só precisa de um conjunto de iPhone e um de iPad por locale, não um por dispositivo físico. A resposta traz o id do conjunto, que você carrega para a próxima chamada. Se já existir um conjunto para aquele locale/tipo, reaproveite-o em vez de criar um duplicado.

Passo 2 — reservar a captura de tela

Você não envia o arquivo de uma vez. Primeiro você o reserva: informa à Apple o nome do arquivo e o tamanho exato em bytes, e ela devolve um plano de upload. Faça POST em /v1/appScreenshots com os atributos fileName e fileSize e um relacionamento com o conjunto do passo 1.

A resposta é a parte interessante. Dentro dos atributos da nova captura de tela, você recebe uploadOperations — um array descrevendo exatamente como enviar os bytes. Para um arquivo pequeno, é uma única operação; para um grande, a Apple divide em várias. Cada entrada traz um method (PUT), uma url pré-assinada, o offset e o length em bytes a enviar, e os requestHeaders a anexar.

Passo 3 — fazer o PUT dos bytes

Para cada operação, leia o trecho do seu arquivo a partir do offset por length bytes, e faça PUT para a url fornecida com exatamente os requestHeaders que a Apple enviou. Essas URLs são pré-assinadas, então você não envia seu JWT aqui — adicionar o cabeçalho Authorization pode até quebrar a requisição assinada. Várias operações podem rodar em paralelo, mas a Apple limita uploads agressivos, então envolva-as em uma lógica de retry com backoff em vez de disparar tudo de uma vez.

Passo 4 — confirmar com uploaded: true e o MD5

Enviar os bytes não faz nada até você avisar à Apple que a reserva está completa. Faça PATCH na captura de tela com uploaded: true e um sourceFileChecksum — o MD5 do arquivo inteiro como uma string hexadecimal em minúsculas. Essa é a verificação de integridade da Apple: se o checksum não bater com o que chegou, o processamento falha.

Depois do PATCH, o recurso entra em processamento do lado da Apple. Faça polling do assetDeliveryState da captura de tela até ele chegar a um estado concluído — e leia os errors se falhar, porque é ali que problemas de dimensão errada e canal alfa aparecem. O PUT e o PATCH podem ambos ter sucesso e a captura de tela ainda ser rejeitada minutos depois, durante o processamento. Não assuma que um 2xx no commit significa que terminou; acompanhe o estado de entrega.

Passo 5 — definir a ordem de exibição

As capturas de tela voltam na ordem em que foram criadas, o que raramente é a ordem que você quer exibir. A ordem do conjunto é um relacionamento separado. Faça PATCH em /v1/appScreenshotSets/{id}/relationships/appScreenshots com um array de IDs de capturas de tela — a ordem do array é a ordem de exibição na loja.

As restrições que a Apple realmente aplica

  • Apenas PNG ou JPEG. Nada de HEIC, nada de WebP. Se o seu renderizador gerar outra coisa, converta antes.
  • Sem canal alfa. Achate a transparência para um fundo sólido e exporte em RGB. Um canal alfa perdido é uma das rejeições silenciosas mais comuns no processamento.
  • Dimensões exatas por tipo de exibição. A imagem precisa bater precisamente com o tamanho em pixels do tipo de exibição — nada de aproximação, nada de upscaling. Um arquivo de 1290 × 2796 vai em um conjunto APP_IPHONE_67 e em nenhum outro.
  • Até 10 por conjunto. Dez capturas de tela no máximo por localização, por tipo de exibição.
  • Somente versão editável. Você só pode alterar conjuntos em uma versão que esteja em estado editável; uma versão já em revisão fica bloqueada.

Por que isso dá mais trabalho do que parece

Cada chamada individual é simples. O custo está em tudo ao redor: assinar e renovar um token de 20 minutos, calcular MD5s, fatiar arquivos para bater com as uploadOperations, lidar com retentativas de upload parcial, fazer polling do estado de entrega, mapear seus locales para os códigos de locale da Apple, e fazer tudo isso mais de 150 vezes para uma listagem devidamente localizada. Deixar isso confiável é um fim de semana de autenticação, uploads em blocos e tratamento de erros — e depois é seu para manter toda vez que a Apple adiciona um tipo de exibição.

Se você quer a sequência sem escrevê-la, o deliver do Fastlane encapsula essa mesma API e é o caminho open-source padrão. Ele resolve o upload; não desenha as capturas de tela nem escreve as legendas.

…ou pule tudo isso

A API só movimenta imagens prontas. Alguém ainda precisa desenhar o carrossel, escrever as legendas e traduzi-las por locale — que é a parte que realmente consome tempo. O Mokbi faz isso hoje: desenha as capturas de tela, redige o texto da listagem e traduz tudo para 50 idiomas, depois exporta cada imagem exatamente nas dimensões por tipo de exibição que essa API exige — PNG, RGB, sem alfa, tamanho certo — para que um upload não trave na etapa de estado de entrega.

Depois, ele publica. Para a App Store, o Mokbi executa exatamente essa sequência de reserve-and-commit por baixo dos panos — enviando suas capturas de tela e metadados e deixando a versão pronta para você enviar, sem você tocar em um JWT ou um PUT em blocos. A Apple ainda exige o envio final e sua revisão; tudo até esse ponto é resolvido para você. Para o Google Play, ele publica direto na loja. De qualquer forma, você obtém o resultado da API sem escrever o código, com o design, o texto e a tradução em 50 idiomas já prontos.

O que ler a seguir

Abrir o editor →