· Développeurs · 6 min de lecture

Envoyer des captures d'écran App Store avec l'API App Store Connect

Envoyer des captures d'écran App Store avec l'API App Store Connect
TL;DR. Envoyer une capture d'écran via l'API App Store Connect est une séquence en quatre étapes par image : créer un appScreenshotSet pour la bonne locale et le bon appareil, réserver un appScreenshot (Apple te fournit des URL de morceaux pré-signées), envoyer les octets en PUT, puis faire un PATCH de la réservation avec uploaded: true et le MD5 du fichier. L'authentification est un JWT valable 20 minutes, signé avec ta clé .p8. Rien n'est difficile en soi ; tout est fastidieux. Voici la vraie séquence — et le raccourci si tu préfères ne pas la construire.

La documentation d'Apple sur le sujet est précise et presque illisible — le flux est éparpillé sur une dizaine de pages de référence, sans aucun exemple complet. Cet article est le tutoriel unique, dans l'ordre, avec les endpoints et noms de champs exacts. Il s'adresse à quiconque hésite entre construire l'intégration ou utiliser un outil qui l'a déjà fait.

Le modèle d'objets dans lequel tu envoies

Les captures d'écran ne se rattachent pas directement à ton app. Elles pendent au bout d'une chaîne d'objets, qu'il faut parcourir de haut en bas :

  • appStoreVersion — la version précise que tu modifies (doit être dans un état modifiable).
  • appStoreVersionLocalization — une par locale App Store (en-US, de-DE, ja, etc.).
  • appScreenshotSet — une par type d'affichage à l'intérieur d'une localisation (iPhone 6,7", iPad 13", etc.).
  • appScreenshot — l'image individuelle, jusqu'à 10 par set.

Une fiche entièrement localisée en 50 langues, sur deux tailles d'iPhone et une taille d'iPad, représente donc 50 × 3 sets, chacun pouvant contenir jusqu'à 10 captures. Cette multiplication est la vraie raison pour laquelle on automatise ce processus plutôt que de cliquer dans l'interface web.

Étape 0 — le JWT de 20 minutes

Chaque requête, hormis les envois d'octets eux-mêmes, nécessite un en-tête Authorization: Bearer portant un JSON Web Token que tu signes toi-même. Il te faut trois éléments d'App Store Connect : ton issuer ID, un key ID, et le fichier de clé privée .p8 que tu télécharges une seule fois à la création de la clé (Apple ne le remontre jamais).

Le token est signé en ES256 — ECDSA sur la courbe P-256 avec SHA-256 — à l'aide de cette clé .p8. L'en-tête porte le kid ; le payload porte l'émetteur en iss, l'audience sous forme de la chaîne littérale appstoreconnect-v1, et un exp qui ne dépasse pas 20 minutes après iat. Apple rejette tout jeton avec une durée de vie plus longue, d'où l'intérêt de régénérer souvent — crée un jeton neuf par lot plutôt que d'essayer d'en garder un ouvert.

Signe-le avec n'importe quelle bibliothèque JWT compatible ES256 (jsonwebtoken, PyJWT, ou l'équivalent de ta stack), passe le contenu du .p8 comme clé, et place le résultat dans l'en-tête Authorization de chaque appel ci-dessous.

Étape 1 — créer le set de captures d'écran

Un set est rattaché à une localisation et un type d'affichage précis. Tu fais un POST vers /v1/appScreenshotSets avec le screenshotDisplayType dans les attributs et une relation pointant vers l'appStoreVersionLocalization à remplir.

Types d'affichage courants : APP_IPHONE_67 (6,7", 1290 × 2796), la taille d'iPhone grand format actuelle, et APP_IPAD_PRO_3GEN_129 (12,9", 2048 × 2732). Une chose pratique désormais faite par Apple : les captures pour la plus grande taille d'iPhone sont réutilisées pour les classes d'iPhone plus petites, et celles de la plus grande taille d'iPad pour les iPad plus petits — dans la pratique, tu n'as souvent besoin que d'un set iPhone et d'un set iPad par locale, pas d'un par appareil physique. La réponse te donne un id de set à reporter dans l'appel suivant. Si un set existe déjà pour cette locale/ce type, réutilise-le plutôt que d'en créer un doublon.

Étape 2 — réserver la capture d'écran

Tu n'envoies pas le fichier en une seule fois. Tu le réserves d'abord : tu indiques à Apple le nom du fichier et sa taille exacte en octets, et il te renvoie un plan d'envoi. POST vers /v1/appScreenshots avec les attributs fileName et fileSize, et une relation vers le set de l'étape 1.

La réponse est la partie intéressante. Dans les attributs de la nouvelle capture, tu obtiens uploadOperations — un tableau décrivant précisément comment envoyer les octets. Pour un petit fichier, c'est une seule opération ; pour un gros, Apple le découpe en plusieurs. Chaque entrée fournit une method (PUT), une url pré-signée, l'offset et la length en octets à envoyer, et les requestHeaders à joindre.

Étape 3 — envoyer les octets en PUT

Pour chaque opération, lis la tranche de ton fichier à partir de offset sur length octets, et envoie-la en PUT vers l'url donnée avec exactement les requestHeaders fournis par Apple. Ces URL sont pré-signées, donc tu n'envoies pas ton JWT ici — ajouter l'en-tête Authorization peut en réalité casser la requête signée. Plusieurs opérations peuvent tourner en parallèle, mais Apple limite le débit des envois trop agressifs, donc encadre-les d'une logique de réessai avec attente progressive plutôt que de tout lancer d'un coup.

Étape 4 — commit avec uploaded: true et le MD5

Envoyer les octets ne fait rien tant que tu n'as pas dit à Apple que la réservation est terminée. Fais un PATCH sur la capture d'écran avec uploaded: true et un sourceFileChecksum — le MD5 du fichier entier, en chaîne hexadécimale minuscule. C'est le contrôle d'intégrité d'Apple : si la somme de contrôle ne correspond pas à ce qui est arrivé, le traitement échoue.

Après le PATCH, l'asset entre en traitement côté Apple. Interroge l'assetDeliveryState de la capture jusqu'à ce qu'il atteigne un état finalisé — et lis ses errors en cas d'échec, car c'est là que remontent les problèmes de dimensions incorrectes et de canal alpha. Le PUT et le PATCH peuvent tous deux réussir, et la capture peut malgré tout être rejetée quelques minutes plus tard pendant le traitement. Ne suppose pas qu'un 2xx sur le commit signifie que c'est terminé ; surveille l'état de livraison.

Étape 5 — définir l'ordre d'affichage

Les captures d'écran reviennent dans l'ordre où elles ont été créées, ce qui est rarement l'ordre souhaité à l'affichage. L'ordre du set est une relation distincte. PATCH /v1/appScreenshotSets/{id}/relationships/appScreenshots avec un tableau d'ID de captures — l'ordre du tableau est l'ordre d'affichage sur le store.

Les contraintes qu'Apple applique réellement

  • PNG ou JPEG uniquement. Pas de HEIC, pas de WebP. Si ton moteur de rendu produit autre chose, convertis d'abord.
  • Pas de canal alpha. Aplatis la transparence sur un fond uni et exporte en RGB. Un canal alpha résiduel est l'un des rejets silencieux les plus fréquents au moment du traitement.
  • Dimensions exactes selon le type d'affichage. L'image doit correspondre précisément à la taille en pixels du type d'affichage — aucun écart, aucun agrandissement. Un fichier de 1290 × 2796 va dans un set APP_IPHONE_67 et nulle part ailleurs.
  • 10 maximum par set. Dix captures maximum par localisation et par type d'affichage.
  • Version modifiable uniquement. Tu ne peux modifier des sets que sur une version dans un état modifiable ; une version déjà en revue est verrouillée.

Pourquoi c'est plus de travail qu'il n'y paraît

Chaque appel pris isolément est simple. Le coût réside dans tout ce qui les entoure : signer et renouveler un jeton valable 20 minutes, calculer des MD5, découper les fichiers pour correspondre aux uploadOperations, gérer les réessais d'envois partiels, interroger l'état de livraison, faire correspondre tes locales aux codes de locale d'Apple, et répéter tout cela plus de 150 fois pour une fiche correctement localisée. La rendre fiable représente un week-end d'authentification, d'envois en morceaux et de gestion d'erreurs — et ensuite, c'est à toi de la maintenir à chaque nouveau type d'affichage ajouté par Apple.

Si tu veux la séquence sans l'écrire toi-même, le deliver de Fastlane enveloppe cette même API et reste la voie open-source standard. Il résout l'envoi ; il ne dessine pas les captures et n'écrit pas les textes.

…ou passe tout ça

L'API ne fait que déplacer des images finies. Il faut encore concevoir le carrousel, rédiger les textes, et les traduire par locale — c'est la partie qui prend réellement du temps. Mokbi le fait aujourd'hui : il conçoit les captures d'écran, rédige les textes de fiche, et traduit le tout en 50 langues, puis exporte chaque image aux dimensions exactes exigées par type d'affichage — PNG, RGB, sans alpha, à la bonne taille — pour qu'un envoi ne trébuche pas à l'étape de l'état de livraison.

Ensuite, il publie. Pour l'App Store, Mokbi exécute en coulisses cette même séquence reserve-and-commit — en envoyant tes captures d'écran et tes métadonnées et en préparant la version, prête à être soumise, sans que tu aies jamais à toucher un JWT ou un PUT en morceaux. Apple exige toujours la soumission finale et sa revue ; tout ce qui précède est pris en charge pour toi. Pour Google Play, il publie directement sur le store. Dans les deux cas, tu obtiens le résultat de l'API sans écrire le code, avec le design, les textes et la traduction en 50 langues déjà faits.

À lire ensuite

Ouvrir l'éditeur →