Asc api app store submit
Skill bokuwalily/claude-code-skills/skills/asc-api-app-store-submit
75 battle-tested Claude Code skills from shipping 20+ apps solo — macOS, Next.js, Vercel, iOS/Expo, Cloudflare, Phaser, local AI media & more
npx -y skills add bokuwalily/claude-code-skills --skill asc-api-app-store-submitAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
iOSアプリをApp Store Connectへ「審査提出・状態確認・著作権/価格/メタの編集」する時。Appleログインや2FA無しで、保管済みのASC APIキー(JWT認証)を使って無人で操作する。eas submit後に審査まで通したい時、提出が止まった時、提出状態を確認したい時に発火。
SKILL.md
17.5 KB, as published. Nobody here has run it
Procedure
App Store Connectには「人がWeb画面で操作」と「ASC APIキー(JWT)でプログラム操作」の2経路がある。後者は 2FA不要・無人 で、ビルド/メタ/価格/審査提出まで叩ける。鍵がこのMacに保管済み=Claudeが自分で審査提出できる。
認証情報(このMacに保管済み・アカウント横断)
~/.appstoreconnect/keys.json… key_id / issuer_id / key_path / team を持つ(ここを読む。値をハードコードしない)~/.appstoreconnect/private_keys/AuthKey_*.p8… 唯一の秘密(chmod 600・dir 700・gitリポ外)- 1本でアカウント内の全アプリに有効(shukatsu/konomi/postwing/dayleaf 等)
再利用ヘルパー ~/.appstoreconnect/asc.py
python3 ~/.appstoreconnect/asc.py apps # 全アプリ(id/bundleId/名前)
python3 ~/.appstoreconnect/asc.py status <app_id> # version state/copyright/review/build
python3 ~/.appstoreconnect/asc.py set-copyright <app_id> "2026 Lily"
python3 ~/.appstoreconnect/asc.py submit <app_id> # 編集中バージョンを審査提出
python3 ~/.appstoreconnect/asc.py add-tester <app_id> # TestFlightテスター追加(既定=本人iCloud)
keys.jsonを読んでJWTを生成し直叩きする。statusで appStoreState と reviewSubmission.state を確認できる。
フルパイプライン(新規/更新アプリを審査まで)
- ビルド:
eas build --local -p ios --profile production(無料署名。credentials.json+リポのAppStore profile。skill [expo-free-local-ios-testflight]) - バイナリ上传:
eas submit -p ios --path build/<app>.ipa --non-interactive(EASサーバ保管のASCキーで2FA無し) - メタ/スクショ:
fastlane deliver(Deliverfile・fastlane/metadata+fastlane/screenshots)。スクショは 1320x2868(6.9") 必須・6.5"も入れると無難 - 価格: 未設定だと提出が止まる → Apple公式API
POST /v1/appPriceSchedules(USA/USD/free等)。fastlaneの旧price_tier経路は壊れてて使えない - 公開フィールドの本人性: copyright等は本名でなく「Lily」に(公開ポリシー)。
asc.py set-copyright - 審査提出:
asc.py submit <app_id>かfastlane deliver submit_build - TestFlightテスター追加(新規アプリは既定で必須):
asc.py add-tester <app_id>。既定で本人 iCloud[email protected]を内部グループ(Beta審査不要=本人が即インストール可)へ追加。内部グループが無ければPOST /v1/betaGroups(isInternalGroup:trueはAPIで設定可)で自動作成。今まで手動で全アプリに入れていた手間を自動化。冪等(filter[apps]で既存検出してskip)。別のテスターはadd-tester <id> <email>。- ⚠️唯一通る経路 =
POST /v1/betaTesters(attributes.email +relationships.betaGroupsで内部グループ指定)。POST /v1/betaGroups/{gid}/relationships/betaTestersに既存テスターidを直リンクすると 409 STATE_ERROR "Tester(s) cannot be assigned"(グローバルなbetaTester記録は外部用の名寄せで内部グループに付かない)。外部グループはビルドのBeta審査承認が無いとテスター追加不可で即時用途に使えない。createパスはemailで内部適格な記録に名寄せして付く。既に所属なら createパスも 409 を返す→filter[apps]で実在を再確認して成否を判定する。
- ⚠️唯一通る経路 =
Pitfalls
- 本名漏れ: App Storeのcopyright欄は公開。
fastlane/metadata/copyright.txtがデフォルト本名になりがち → 「2026 Lily」に。提出済みでもWAITING_FOR_REVIEW中はAPIでPATCH可(In Reviewでロック)。 - PII:
fastlane/Deliverfileに Apple ID メールが入る →.gitignore必須(リポ外)。.p8も当然gitignore。 - 価格未設定で提出停止: fastlane price_tierは死んでる。公式API
appPriceSchedules直叩きで解決。 - JWT: ES256・
iss=issuer_id・aud="appstoreconnect-v1"・exp 20分以内。cryptographyでECDSA署名→r||s(各32byte)にrawエンコード(DERのままはNG)。 - キーの場所: Downloads等の揮発場所に置かない。
~/.appstoreconnect/(700)に集約済。新しい鍵を貰ったら keys.json を更新するだけ。 - eas submit のキーはEASサーバ保管(別ID)。
asc.pyのキー(ローカル)とは別物だが両方同アカウント。 - ITMS-90111 (beta macOSビルドが真因・2026-06-26 ねむログ/Konomiで確定): 提出が
ITMS-90111「Unsupported SDK or Xcode version - use latest RC」で却下され version が直後にINVALID_BINARY転落する時、エラー文言はミスリードで真因は beta macOS でビルドした事。アーカイブのBuildMachineOSBuildにbeta値(例26A5368g=macOS27beta)が埋まり、Apple検証が拒否。最新安定版Xcodeでも落ちる(=ツールチェーンが原因に見えるが違う)。ニュース/フォーラムが無い=Apple全体障害でなく自分の環境を疑え。回避: アーカイブの.app/Info.plist(と全PlugIns/*.appex/Info.plist)のBuildMachineOSBuildを安定版macOSビルド番号(例25F80=macOS26.5.1、都度確認)にPlistBuddy -c "Set"で書換え→xcodebuild -exportArchive(再署名がパッチ済plistに乗る)→ IPAで値とcodesign --verify --deep --strictを検証→ altool upload。提出後 3-4分 WAITING_FOR_REVIEW 維持=成功(失敗は1-2分でINVALID_BINARY)。詳細=memoryreference_itms90111_beta_macos。なお Expo/RN は Xcode beta でnode_modules/*/.DerivedDataが汚染され安定版でもビルド不能になる→該当.DerivedDataを rm して再ビルド。 - 価格(無料)スケジュールPOSTの正解形(2026-06-22 つづけで確定):
POST /v1/appPriceSchedules、data.relationships={app, baseTerritory(territories/USA・必須), manualPrices→[{type:"appPrices",id:"${p}"}]}、included=[{type:"appPrices",id:"${p}","attributes":{},relationships:{appPricePoint:{data:{type:"appPricePoints",id:<free>}}}}]。⚠️includedのappPriceに"attributes":{}(空オブジェクト)が無い/startDate:nullだと422 invalid value at data.included。manualPricesにappPricePoints型を直入れすると409。価格ポイント=/v1/apps/{id}/appPricePoints?filter[territory]=USAでcustomerPrice=="0.0"(そのトークンidの直GETは404でも提出には有効)。
Verification
python3 ~/.appstoreconnect/asc.py status <app_id>でappStoreState=WAITING_FOR_REVIEWと狙いの copyright を確認- PATCH/submitは戻りHTTP<400かつ再GETで反映を確認(推測で「提出済み」と言わない)
- 実績: 2026-06-19 konomi(6780963389) build13 を本パイプラインで審査提出・copyrightを本名→「2026 Lily」にPATCH(200)・
WAITING_FOR_REVIEWをAPIで裏取り済 - 実績: 2026-06-21 5本(就活/PostWing/Konomi/30H/Dayleaf)を最新UIスクショ+掲載文込みで一括審査提出。下記の罠を全部踏んで突破。
5本同時提出で踏んだ罠 (2026-06-21・再発防止)
- 審査待ちの差し替え: WAITING_FOR_REVIEW のまま新ビルドは載せられない。先に
asc.py reject <id>(保留submission取消)→make-versionで新版→attach→submit。- ⚠️**
attach-build <app_id> <ARG>の ARG は build番号でなく marketing version("1.0.0")**(2026-06-22 Akari build4で確定)。内部の_build_for_versionは preReleaseVersion.version(=CFBundleShortVersionString)でマッチし、同 marketing の最新VALID buildを選ぶ。build番号(4)を渡すとno VALID build for version 4で永遠に空振り。正しい差し替え全手順:reject <id>→attach-build <id> 1.0.0→submit <id>→statusで attached build番号と WAITING_FOR_REVIEW を裏取り。 - 同 version で build番号だけ上げる更新(build3→4)は
make-version不要(既存編集中versionにattachするだけ)。CURRENT_PROJECT_VERSION を project.yml で上げxcodegen generate(pbxprojに焼く)→archive→export→altool→VALID待ち→上記差し替え。
- ⚠️**
- 公開中(READY_FOR_SALE)の更新: ASCの現行versionより上の番号必須。configが古い値でもASC側が先行している(例: 就活configは1.0.5だがASC公開は1.2)→必ず
asc.py statusで現行を見てから上の番号に。 - Expo prebuildのバージョン焼き込み: app.config の version bump 前 に
expo prebuildするとios/に旧版が焼かれ、altoolがCFBundleShortVersionString must be higher / train closed (90062/90186)で蹴る。直し=/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString X" ios/<App>/Info.plist+CFBundleVersionも。bumpは prebuild より前に。 - dual-cert+capability署名(EAS無料クラウド枠切れ時):
eas build --localは EAS管理プロファイルがローカル鍵の無いcertを指してprofile doesn't include signing certificateで死ぬ。回避=ネイティブ流の fastlane ローカル署名。Expoの prebuiltios/<App>.xcworkspace(scheme=app/PostWing等) に対し最小Fastfile:get_certificates(development:false)+get_provisioning_profile(force:true)+build_app(... xcargs: "... PROVISIONING_PROFILE_SPECIFIER='#{lane_context[SharedValues::SIGH_NAME]}'")。xcargs に PROVISIONING_PROFILE_SPECIFIER を入れ忘れると archive でrequires a provisioning profile with Push/Sign In with Appleになる(Bundle IDにcapabilityはあるのにprofile未指定で自動署名が外す)。 - fastlane deliver の api_key:
--api_key_pathの JSON はkey(=.p8本体テキスト) が必須。key_filepathだけだとmissing field(s): key。一時JSONを{"key_id","issuer_id","key":<p8文字列>,"in_house":false}で作る(600・使い終わったら消す)。 - deliver スクショ:
sync_screenshots:trueはFASTLANE_ENABLE_BETA_DELIVER_SYNC_SCREENSHOTS要求で止まる→overwrite_screenshots:trueのみ(syncは付けない)。初版は release_notes がスキップされる(whatsNew 409=初回は不要)。更新版はasc.py whatsnew可。 - altool 空パス:
-f "$IPA"の変数が空だとFile does not exist at path: .で ExitFailure 31。必ず絶対パスで渡す。fastlane build_appの出力は プロジェクト直下<scheme>.ipa。 - 提出409 (localization invalid): 追加ロケール(ko/en-US)に サポートURL or スクショが無い と
appStoreVersionLocalizations ... not in valid state。直し=各ロケールに supportUrl をPATCH+スクショを全ロケールへ配置して deliver。スクショ assetDeliveryState は全COMPLETEを確認してから submit(アップロード途中で submit すると appScreenshots invalid)。 - 検証:
GET /v1/builds?filter[app]=<id>&fields[builds]=version,processingStateでVALIDを待ってから attach。
追補: 新規ネイティブiOSアプリを“箱作成〜審査提出”まで無人で出す (2026-06-22 Auralyで全実証)
新規アプリは APIキーだけでは作れない/落とし穴が多い。実証済みの順序:
- 箱(App record)作成:
POST /v1/appsはAPIキーで 403 (CREATE不可)。正解=fastlane produce。Fastfileでapp_store_connect_api_key(asc_key) →produce(app_identifier:, app_name:, language:"Japanese", sku:, team_id:, skip_devcenter:true)。Appfileにapple_idを置く。spaceshipセッションが無効でも APIキーにフォールバックしてパスワード/2FA無しで作成できる。 - 署名/archive/altoolアップロード/VALID待ちは本文どおり。
- スクショは deliver、ただしスクショ単独で:
fastlane deliver --skip_binary_upload true --skip_metadata true --skip_screenshots false。⚠️metadataを同時にやるとreview_attachment_fileで クラッシュ(No data)。- 🛑deliver後・submit前に必ず
python3 ~/.appstoreconnect/asc.py dedup <app_id> --applyを実行する(必須・任意ではない)。overwrite_screenshots:true(syncなし)はリトライ時に既存を消さず追記するため、deliverが2回走ると各スクショが連続2枚に二重化する(同 checksum+fileName)。ストアで「同じ写真が2枚ずつ並ぶ」醜い表示になる。dedupは同一 checksum+fileName の2枚目以降をDELETE /v1/appScreenshots/{id}で間引く(編集中versionのみ可)。--apply無しはdry-run。2026-06-22に6アプリ(つづけ/就活トラッカー/PostWing/Dayleaf/30H/Konomi)で全滅し一括修正した再発防止。 - 公開中(READY_FOR_SALE)アプリの修正は新version作成→継承スクショをdedup→新ビルド添付→submit。⚠️公開中versionは
DELETEが 409(STATE_ERROR)。審査中(WAITING_FOR_REVIEW)はasc.py rejectで DEVELOPER_REJECTED にしてから dedup→submit。
- 🛑deliver後・submit前に必ず
- メタ/著作権/ビルド添付/価格/年齢/審査連絡先は
asc.pyのcall()をimportして直叩き:- localization PATCH、version PATCH(copyright + relationships.build)。
- 無料価格:
GET /v1/apps/{id}/appPricePoints?filter[territory]=USAで customerPrice "0.0" の point →POST /v1/appPriceSchedules(included appPrice id${price-0}が free point を指す)。 - 年齢4+:
PATCH /v1/ageRatingDeclarations/{id}。⚠️型混在。enum"NONE"= violence*/sexual*/contests/gunsOrOtherWeapons/alcohol/gamblingSimulated/horror/mature/medical/profanity。BOOLEAN(false)= advertising/messagingAndChat/gambling/lootBox/unrestrictedWebAccess/healthOrWellnessTopics/parentalControls/userGeneratedContent/ageAssurance。kidsAgeBand=null。 - 審査連絡先:
POST /v1/appStoreReviewDetails。contactPhone必須(+国番号形式 例+81 90 7170 0135)。demoAccountRequired:false。 PATCH /v1/apps/{id}contentRightsDeclaration:"DOES_NOT_USE_THIRD_PARTY_CONTENT"。
- App Privacy(必須): ⚠️
appDataUsages系エンドポイントは このAPIキーで全404(アプリrelationshipsにも無い)。正解=fastlane upload_app_privacy_details_to_app_storeをレーン内でasc_keyの後に呼ぶ(api_key引数は無いがlane contextのトークンをspaceshipが拾う)。json=[{"data_protections":["DATA_NOT_COLLECTED"]}]。 - iPad要件: device family
"1,2"だと提出時にSCREENSHOT_REQUIRED.APP_IPAD_PRO_3GEN_129。iPhoneアプリはTARGETED_DEVICE_FAMILY:"1"にして回避→build番号上げて再ビルド/再アップロード。 - 提出:
asc.py submit <id>。409時はmeta.associatedErrorsに不足項目が全列挙される(screenshot/reviewDetail/appDataUsages 等)→それを全部潰してから再提出。 - アプリ名衝突: ja主言語名は作成時に空きなら通るが、en-USローカライズ追加で同名が他アプリと衝突しうる→ v1は ja単独掲載で出し、en-USは承認後に別名で追加。
追補2 (2026-06-22 Hibiで確定・produce 500と提出必須項目)
fastlane produceが「Server error got 500」で死ぬ最大要因 = bundleIdが事前に存在しない。skip_devcenter:trueを付けると produce は App ID(devcenter)作成をスキップし bundleId 既存前提で app record だけ作る→bundleId が無いと名前と無関係に 500(名前を変えても直らず名前衝突と誤診しやすい)。→ 必ず先にsetup_signing.py(POST /v1/bundleIds で bundleId 作成)を実行してから produce。順序: setup_signing → produce → archive → upload。- submit が 409 になる隠れ必須2点(
meta.associatedErrorsはtruncateされるので直接dumpして全文読む):- primaryCategory 未設定 =
appInfosの relationship(Deliverfileのprimary_categoryだけでは付かない)。PATCH /v1/appInfos/{appInfoId}でrelationships.primaryCategory.data={type:"appCategories",id:"LIFESTYLE"}(+secondaryCategory)。appInfoId=GET /v1/apps/{id}/appInfos。 - APP_PRICING_REQUIRED = 新規アプリにASCが自動生成する空のappPriceScheduleは無効。
POST /v1/appPriceSchedulesで USA free point を明示作成し直す(included appPrice に"attributes":{}必須・既存あっても再POSTで201上書き)。
- primaryCategory 未設定 =
- 年齢宣言の必須属性(欠けると REQUIRED 409 が連鎖): ENUM"NONE"= violence*/sexual*/profanity*/mature*/horror*/medical*/alcohol*/gamblingSimulated/contests/gunsOrOtherWeapons。BOOL(false)= gambling/unrestrictedWebAccess/advertising/messagingAndChat/lootBox/healthOrWellnessTopics/parentalControls/userGeneratedContent/ageAssurance。kidsAgeBand=null。
seventeenPlusは存在しない(入れると UNKNOWN 409)。 - deliver スクショ二重UP: deliver は1回目「missing on App Store Connect」→自動リトライで各fileNameが2枚に重複(6枚=3種×2)。submit前に重複削除必須=
DELETE /v1/appScreenshots/{id}(各fileNameの2枚目以降)。WAITING_FOR_REVIEW中は409で削除不可→asc.py reject <id>(version→DEVELOPER_REJECTED)→各setをfileNameでグルーピングし1枚残して削除→asc.py submitで再提出。