Mengunggah screenshot App Store dengan App Store Connect API
appScreenshotSet untuk locale dan perangkat yang tepat, reservasi appScreenshot (Apple memberimu URL chunk yang sudah ditandatangani), PUT byte-nya, lalu PATCH reservasi tadi dengan uploaded: true dan MD5 filenya. Otentikasi memakai JWT berumur 20 menit yang ditandatangani dengan kunci .p8 milikmu. Semuanya tidak sulit; semuanya cukup ribet. Berikut urutan sebenarnya — dan jalan pintas kalau kamu tidak ingin membangunnya sendiri.Dokumentasi Apple untuk ini akurat tapi hampir tak terbaca — alurnya tersebar di belasan halaman referensi tanpa satu pun contoh lengkap yang utuh. Post ini adalah panduan tunggal, berurutan, lengkap dengan endpoint dan nama field yang tepat. Ditulis untuk siapa pun yang sedang memutuskan antara membangun integrasi sendiri atau memakai tool yang sudah punya semuanya.
Model objek yang kamu unggah ke dalamnya
Screenshot tidak menempel langsung ke app-mu. Mereka tergantung di rantai objek, dan kamu harus menelusurinya dari atas ke bawah:
- appStoreVersion — versi spesifik yang sedang kamu edit (harus dalam status editable).
- appStoreVersionLocalization — satu per locale App Store (en-US, de-DE, ja, dan seterusnya).
- appScreenshotSet — satu per tipe tampilan di dalam sebuah localization (iPhone 6.7", iPad 13", dll).
- appScreenshot — gambar individual, sampai 10 per set.
Jadi listing yang terlokalisasi penuh dalam 50 bahasa di dua ukuran iPhone dan satu ukuran iPad adalah 50 × 3 set, masing-masing menampung sampai 10 screenshot. Perkalian itulah alasan utama orang mengotomatisasi ini alih-alih klik satu-satu di web UI.
Langkah 0 — JWT berumur 20 menit
Setiap request kecuali unggah byte itu sendiri butuh header Authorization: Bearer berisi JSON Web Token yang kamu tandatangani sendiri. Kamu butuh tiga hal dari App Store Connect: issuer ID, key ID, dan file private key .p8 yang kamu unduh sekali saat membuat key (Apple tidak pernah menampilkannya lagi).
Token ditandatangani dengan ES256 — ECDSA pada kurva P-256 dengan SHA-256 — memakai key .p8 tadi. Header membawa kid; payload membawa issuer sebagai iss, audience sebagai string literal appstoreconnect-v1, dan exp tidak lebih dari 20 menit setelah iat. Apple menolak apa pun dengan masa berlaku lebih lama, jadi kamu perlu sering meregenerasi — buat token baru per batch alih-alih mencoba menahannya tetap terbuka.
Tandatangani dengan library JWT apa pun yang mendukung ES256 (jsonwebtoken, PyJWT, atau apa pun yang dipakai stack-mu), lewatkan isi .p8 sebagai key, dan taruh hasilnya di header Authorization pada setiap panggilan di bawah.
Langkah 1 — buat screenshot set
Sebuah set terikat pada satu localization dan satu tipe tampilan. Kamu POST ke /v1/appScreenshotSets dengan screenshotDisplayType di attributes dan relationship yang menunjuk ke appStoreVersionLocalization yang ingin kamu isi.
Tipe tampilan umum: APP_IPHONE_67 (6.7", 1290 × 2796), ukuran iPhone besar saat ini, dan APP_IPAD_PRO_3GEN_129 (12.9", 2048 × 2732). Satu hal berguna yang sekarang dilakukan Apple: screenshot untuk ukuran iPhone terbesar dipakai ulang ke kelas iPhone yang lebih kecil, dan ukuran iPad terbesar ke iPad yang lebih kecil — jadi dalam praktiknya kamu sering hanya perlu satu set iPhone dan satu set iPad per locale, bukan satu per perangkat fisik. Respons memberimu id set yang kamu bawa ke panggilan berikutnya. Kalau set sudah ada untuk locale/tipe itu, pakai ulang saja, jangan buat duplikat.
Langkah 2 — reservasi screenshot
Kamu tidak mengunggah file dalam satu kali kirim. Pertama kamu reservasi: beri tahu Apple nama file dan ukuran byte pastinya, dan Apple mengembalikan rencana unggah. POST ke /v1/appScreenshots dengan attribute fileName dan fileSize, plus relationship ke set dari langkah 1.
Responsnya bagian yang menarik. Di dalam attributes screenshot baru itu kamu dapat uploadOperations — array yang menjelaskan persis cara mengirim byte-nya. Untuk file kecil hanya satu operasi; untuk file besar Apple membaginya jadi beberapa. Setiap entri memberimu method (PUT), url yang sudah ditandatangani, offset dan length byte yang harus dikirim, serta requestHeaders yang harus disertakan.
Langkah 3 — PUT byte-nya
Untuk setiap operasi, baca potongan file-mu dari offset sepanjang length byte, lalu PUT ke url yang diberikan dengan tepat requestHeaders yang disediakan Apple. URL-URL ini sudah ditandatangani, jadi kamu tidak mengirim JWT di sini — menambahkan header Authorization justru bisa merusak request yang sudah ditandatangani. Beberapa operasi bisa berjalan paralel, tapi Apple membatasi laju unggahan agresif, jadi bungkus dengan retry-with-backoff alih-alih menembakkan semuanya sekaligus.
Langkah 4 — commit dengan uploaded: true dan MD5
Mengunggah byte tidak berarti apa-apa sampai kamu memberi tahu Apple bahwa reservasi sudah selesai. PATCH screenshotnya kembali dengan uploaded: true dan sourceFileChecksum — MD5 dari seluruh file sebagai string hex huruf kecil. Ini pengecekan integritas Apple: kalau checksum tidak cocok dengan yang diterima, pemrosesan gagal.
Setelah PATCH, asetnya masuk pemrosesan di sisi Apple. Poll assetDeliveryState milik screenshot itu sampai mencapai status selesai — dan baca errors-nya kalau gagal, karena di situlah masalah dimensi salah dan alpha channel muncul. PUT dan PATCH bisa sama-sama berhasil dan screenshotnya tetap bisa ditolak beberapa menit kemudian saat pemrosesan. Jangan asumsikan status 2xx pada commit berarti selesai; pantau delivery state-nya.
Langkah 5 — atur urutan tampilan
Screenshot kembali dalam urutan apa pun saat dibuat, yang jarang jadi urutan yang kamu inginkan. Urutan set adalah relationship terpisah. PATCH /v1/appScreenshotSets/{id}/relationships/appScreenshots dengan array ID screenshot — urutan array itulah urutan tampilan di store.
Batasan yang benar-benar diberlakukan Apple
- Hanya PNG atau JPEG. Tidak ada HEIC, tidak ada WebP. Kalau renderer-mu menghasilkan format lain, konversi dulu.
- Tanpa alpha channel. Ratakan transparansi ke background solid dan ekspor RGB. Alpha channel yang tak sengaja tertinggal adalah salah satu penolakan diam-diam paling umum saat pemrosesan.
- Dimensi tepat per tipe tampilan. Gambar harus cocok persis dengan ukuran piksel tipe tampilannya — tidak boleh meleset sedikit pun, tidak boleh upscale. File 1290 × 2796 masuk ke set
APP_IPHONE_67dan tidak ke tempat lain. - Maksimal 10 per set. Sepuluh screenshot maksimum per localization per tipe tampilan.
- Hanya versi editable. Kamu hanya bisa mengubah set pada versi yang berstatus editable; versi yang sudah dalam review terkunci.
Kenapa ini lebih ribet dari kelihatannya
Setiap panggilan individual sederhana. Biayanya ada di semua yang mengelilinginya: menandatangani dan merotasi token berumur 20 menit, menghitung MD5, memotong file agar sesuai uploadOperations, menangani retry unggahan parsial, poll delivery state, memetakan locale-mu ke kode locale Apple, dan melakukan semuanya 150-plus kali untuk listing yang terlokalisasi dengan benar. Membuatnya andal butuh satu akhir pekan penuh untuk otentikasi, unggah bertahap, dan penanganan error — lalu kamu harus merawatnya setiap kali Apple menambah tipe tampilan baru.
Kalau kamu ingin urutan ini tanpa menulisnya sendiri, Fastlane's deliver membungkus API yang sama ini dan menjadi jalur open-source standar. Ini menyelesaikan bagian unggah; tidak mendesain screenshot atau menulis caption-nya.
…atau lewati semuanya
API ini hanya memindahkan gambar yang sudah jadi. Masih ada yang harus mendesain carousel-nya, menulis caption-nya, dan menerjemahkannya per locale — dan itulah bagian yang sebenarnya makan waktu. Mokbi mengerjakan itu hari ini: mendesain screenshot-nya, menulis draf copy listing, dan menerjemahkan semuanya ke 50 bahasa, lalu mengekspor setiap gambar dengan dimensi persis per tipe tampilan yang dituntut API ini — PNG, RGB, tanpa alpha, ukuran yang tepat — sehingga unggahan tidak terpental di tahap delivery-state.
Lalu ia menerbitkannya. Untuk App Store, Mokbi menjalankan urutan reserve-and-commit yang persis sama ini di balik layar — mengunggah screenshot dan metadata-mu serta menyiapkan versinya siap kamu submit, jadi kamu tidak perlu menyentuh JWT atau PUT bertahap. Apple tetap mewajibkan Submit final dan review-nya; segalanya sebelum itu sudah ditangani untukmu. Untuk Google Play, ia langsung mendorongnya ke store. Bagaimanapun juga kamu dapat hasil API-nya tanpa menulis kodenya, lengkap dengan desain, copy, dan terjemahan 50 bahasa yang sudah selesai.