TL;DR. はい、App Store Connect API を使えば、App Store Connect を手で開かずにキーワードフィールド、サブタイトル、説明文、プロモーションテキストを更新できます。ただし、name と subtitle は
appInfoLocalizationリソースにあり、keywords、description、promotionalText、What’s New はappStoreVersionLocalizationという別のリソースにあります——それぞれ独自のステータスルールを持ちます。ライブ中または審査中のバージョンに対して keywords を PATCH しようとすると、409 のSTATE_ERRORが返ってきます。API は Apple のリリースサイクルを回避するものではなく、本来クリックして行う操作をスクリプトから実行できるようにするだけです。
複数のアプリのメタデータを管理していたり、6言語以上にローカライズしていて同じキーワードフィールドの変更をリリースのたびに6つのロケールタブへ入力し直しているなら、App Store Connect API はそのクリック作業を取り除いてくれます。ただし制約そのものはなくなりません。その制約が実際にどこにあるのかを知っておけば、JSON とはまったく関係のない理由で PATCH リクエストが失敗したときに、デバッグに時間を溶かさずに済みます。
キーワードフィールドは App Store Connect API で更新できますか?
はい。keywords 属性は appStoreVersionLocalization リソースにあり、ロケールを指定してそのリソースのエンドポイントへ PATCH リクエストを送ることで更新します。これは App Store Connect の「ローカライズ可能な情報」セクションで手動でキーワードフィールドを編集するのとまったく同じ動作です——同じ100文字のフィールド、同じトークン化ルール、「タイトルを繰り返さない」という同じガイダンスです。API はそのルールを何も緩和しません。同じ部屋への別の扉というだけです。
つまずくポイントはリクエストボディではありません。このエンドポイントは、親となる App Store のバージョンが編集可能なステータスにある間しか書き込みを受け付けない、という点です。
どのリソースがどのメタデータフィールドを保持していますか?
ここはほとんどの連携ガイドが説明を省く部分であり、ある日あるフィールドへの PATCH リクエストは成功するのに、同じ日に別のフィールドでは失敗する理由でもあります。
appInfoLocalization は特定のバージョンに紐づかないフィールドを保持します:
namesubtitleprivacyPolicyUrl、privacyPolicyText、privacyChoicesUrl
appStoreVersionLocalization は特定のバージョンに紐づくフィールドを保持します:
keywordsdescriptionpromotionalTextwhatsNewmarketingUrl、supportUrl
この分割を見ると、Apple 自身のリソースモデルが name と subtitle をバージョンの下にネストしていない以上、この2つはバージョン提出とは独立してライブに反映できそうに思えます。しかし実際にはそうなりません。どちらのフィールドも、keywords と同様、バージョンがリリースされて初めて反映されます。サブタイトルの変更を検証していて、指標を信頼する前にバージョンステータスが「販売準備完了」になっているかを確認する習慣があるなら、その習慣はここでもそのまま当てはまります——API が変えるのはフィールドの書き込み方法であって、Apple が実際にそれを出荷するタイミングではありません。これはApp Store Connect のリリースオプションガイドで扱った、リリースと承認の間にあるのと同じギャップです。
PATCH リクエストが 409 STATE_ERROR で失敗するのはなぜですか?
appStoreVersionLocalization のフィールドは、親バージョンが編集可能なステータス——PREPARE_FOR_SUBMISSION、DEVELOPER_REJECTED、REJECTED、METADATA_REJECTED——にある間しか編集できないためです。バージョンが WAITING_FOR_REVIEW、IN_REVIEW、PENDING_DEVELOPER_RELEASE、READY_FOR_SALE のいずれかに移ると、昨日まで動いていた同じ PATCH リクエストが、409 と "code": "STATE_ERROR"、そして今この属性は編集できないというメッセージを返すようになります。
これは、手動UIですでにご存知のルールを API がそのまま強制しているだけです。つまり、一度提出すると、審査が完了するか、開発者による却下でバージョンを引き戻すまで、キーワードフィールドはロックされます。解決策は別のリクエスト形式ではなく、書き込みを試みる前に GET でバージョンのステータスを確認し、上記の編集可能なステータスのいずれかであるときだけ更新を送信することです。これをリリースパイプラインの一部としてスクリプト化するなら、そのステータス確認は PATCH の失敗後のリトライループにではなく、PATCH の前に置くべきです。
認証は実際どのように機能しますか?
すべてのリクエストには、App Store Connect で作成した秘密鍵から生成し ES256 で署名した JSON Web Token が必要です。Team Keys は「ユーザとアクセス」→ Integrations → Team Keys から作成し、生成にはアカウントの Admin ロールが必要です——これはキーワードフィールドを手動で編集できるアカウント所有者/管理者/App管理者/マーケティングのグループよりも狭い要件です。自分のユーザープロファイルから生成する Individual Keys は、アカウント全体へのアクセス権ではなく、自分自身のアカウントロールとアプリの割り当てを引き継ぎます。
実務上、これには2つの意味があります:
- Team Keys はアカウント内のすべてのアプリが見えます。特定の1アプリに絞る方法はありません。管理するアプリが1つだけなら、自分の App管理者やマーケティングロールに紐づく Individual Key の方が範囲が狭く適しています。
- 秘密鍵はちょうど一度だけダウンロードできます。 Apple は再ダウンロード可能なコピーを保存しません。紛失した場合はそのキーを取り消して新しく生成するしかなく、既存キーのアクセスレベルを後から復元・変更することもできません。
- Apple は、読み取り専用のレポート用途に限られた一部のスコープに許される最大値ではなく、通常のリクエストには短いトークン有効期限を推奨しています(App Store Connect API は通常のリクエストトークンをおよそ20分に制限しています)。有効期限の長いトークンを一つハードコードするのではなく、スクリプトを実行するたびにトークンを生成しましょう。
インディーチームにとって、これを構築する価値は実際にありますか?
1つのアプリを1〜2ロケールで管理していて、キーワードフィールドを数週間に一度しか変えないなら、答えはノーです——API連携を書いて保守するより手動UIの方が速いです。API が元を取れるようになるのは、複数ロケールのメタデータをスケジュールに沿って管理している場合や、複数アプリを管理していて、同じフィールドの変更を何度も同じように繰り返す必要があり、5番目のロケールでのコピー&ペーストミスが見落とされやすい場合です。
現実的な最初のユースケースは完全自動化ではなく、あるバージョンについて全ロケールの現在のキーワードフィールド、説明文、サブタイトルを読み取るスクリプトです。それによって、手を動かす前に、提案する変更を実際にライブになっている内容と突き合わせて確認できます。GET リクエストはバージョンステータスに関係なく動作するため、読み取りアクセスには上記のステータスロックの問題が一切なく、始めるならリスクの低いところです。
この API を使って構築する前に
- リクエストを書く前に、対象フィールドがどのリソースにあるかを確認してください——name/subtitle は
appInfoLocalization、keywords/description/promotionalText/What’s New はappStoreVersionLocalizationです。 appStoreVersionLocalizationへの PATCH のたびに、事前に GET でバージョンのステータスを確認してください。書き込むのはPREPARE_FOR_SUBMISSION、DEVELOPER_REJECTED、REJECTED、METADATA_REJECTEDのいずれかのときだけです。- Team Key と Individual Key のどちらを使うかは、利便性ではなくスコープで決めてください——1つのアプリのためだけに必要だった Team Key は、本来不要だったアカウント全体の常設クレデンシャルになってしまいます。
- API が変えるのはメタデータの編集方法であって、それがいつライブになるかではないことを忘れないでください。リリースのタイミングは手動編集と同じリリースと承認のルールにそのまま従い、ロールの要件もそもそも誰がキーワードフィールドに触れられるかというルールにそのまま従います。