TL;DR. Yes, the App Store Connect API can update your keyword field, subtitle, description, and promotional text without you opening App Store Connect by hand. But name and subtitle live on the
appInfoLocalizationresource while keywords, description, promotional text, and What’s New live onappStoreVersionLocalization— a different resource with its own state rules. Try to PATCH keywords on a version that’s live or in review and you’ll get a 409STATE_ERROR. The API doesn’t bypass Apple’s release cycle, it just gives you a scriptable way to trigger the same actions you’d otherwise click through.
If you manage metadata for more than one app, or you localize into six-plus languages and re-type the same keyword field change into six locale tabs every release, the App Store Connect API removes the clicking. It does not remove the constraints. Knowing where those constraints actually live saves you a debugging session the first time a PATCH request fails for a reason that has nothing to do with your JSON.
Can I update my keyword field via the App Store Connect API?
Yes. The keywords attribute lives on the appStoreVersionLocalization resource, and you update it with a PATCH request to that resource’s endpoint, scoped to a locale. This works exactly like editing the keyword field by hand in App Store Connect’s Localizable Information section — same 100-character field, same tokenization rules, same “don’t repeat your title” guidance. The API doesn’t relax any of that; it’s a different door into the same room.
What trips people up isn’t the request body. It’s that this endpoint only accepts writes while the parent app store version is in an editable state.
Which resource holds which metadata field?
This is the part most integration guides skip, and it’s the reason a working PATCH request for one field can fail for another field on the same day.
appInfoLocalization holds fields that aren’t tied to a specific version:
namesubtitleprivacyPolicyUrl,privacyPolicyText,privacyChoicesUrl
appStoreVersionLocalization holds fields that are tied to a specific version:
keywordsdescriptionpromotionalTextwhatsNewmarketingUrl,supportUrl
The split looks like it should mean name and subtitle can be pushed live independent of a version submission, since Apple’s own resource model doesn’t nest them under a version. In practice it doesn’t work that way: both fields still only take effect once a version releases, the same as keywords. If you’re validating a subtitle change and you’re used to reading version status for “Ready for Sale” before you trust a metric, that habit still applies here — the API changes how you write the field, not when Apple actually ships it. That’s the same release-vs-approval gap covered in the App Store Connect release options guide.
Why does my PATCH request fail with a 409 STATE_ERROR?
Because appStoreVersionLocalization fields can only be edited while the parent version is in an editable state — PREPARE_FOR_SUBMISSION, DEVELOPER_REJECTED, REJECTED, or METADATA_REJECTED. Once a version moves into WAITING_FOR_REVIEW, IN_REVIEW, PENDING_DEVELOPER_RELEASE, or READY_FOR_SALE, the same PATCH request that worked yesterday returns a 409 with "code": "STATE_ERROR" and a message that the attribute can’t be edited right now.
This is the API enforcing the exact rule you already know from the manual UI: once you’ve submitted, the keyword field is locked until either the review resolves or you pull the version back with a developer rejection. The fix isn’t a different request shape — it’s checking the version’s state with a GET before you attempt the write, and only submitting the update when the state is one of the editable ones above. If you’re scripting this as part of a release pipeline, that state check belongs before the PATCH, not in a retry loop after it fails.
How does authentication actually work?
Every request needs a JSON Web Token signed with ES256, generated from a private key you create in App Store Connect. Team keys come from Users and Access → Integrations → Team Keys, and generating one requires the Admin role on the account — a narrower requirement than the Account Holder/Admin/App Manager/Marketing group that can edit the keyword field by hand. Individual keys, generated from your own user profile, inherit your own account role and app assignments instead of account-wide access.
Two practical consequences:
- Team keys see every app on the account, with no way to scope one to a single app. If you manage metadata for one app only, an individual key tied to your own App Manager or Marketing role is the tighter-scoped option.
- The private key downloads exactly once. Apple doesn’t store a re-downloadable copy. Lose it and you revoke the key and generate a new one — you can’t recover or rename an existing key’s access level either way.
- Apple recommends short token lifetimes for standard requests (the App Store Connect API caps normal request tokens at roughly 20 minutes), not the maximum allowed for the narrow set of read-only reporting scopes. Generate a token per run of your script rather than hardcoding one with a long expiry.
Is this actually worth building for an indie team?
If you manage one app in one or two locales and change your keyword field every few weeks, no — the manual UI is faster than writing and maintaining an API integration. The API starts paying for itself once you’re managing metadata across multiple locales on a schedule, or across more than one app, where the same field change has to be repeated identically many times and a copy-paste mistake in locale five is easy to miss.
The realistic first use case isn’t full automation — it’s a script that reads your current keyword field, description, and subtitle across every locale for a version, so you can diff a proposed change against what’s actually live before you touch anything by hand. Read access has none of the state-lock problems above, since GET requests work regardless of version state, so it’s the lower-risk place to start.
Before you build against this API
- Confirm which resource your target field lives on before you write the request —
appInfoLocalizationfor name/subtitle,appStoreVersionLocalizationfor keywords/description/promotional text/What’s New. - GET the version’s state before every PATCH to
appStoreVersionLocalization. Only write when it’sPREPARE_FOR_SUBMISSION,DEVELOPER_REJECTED,REJECTED, orMETADATA_REJECTED. - Decide team key versus individual key based on scope, not convenience — a team key you only needed for one app is a standing account-wide credential you didn’t need to create.
- Remember the API changes how you edit metadata, not when it goes live. Release timing still follows the same release-vs-approval rule as manual edits, and role requirements still follow who’s allowed to touch the keyword field at all.