Skip to Content
Working with the codebaseAge rating & content rights

Age rating and content rights

The two review declarations that are single answers rather than a generated set, both read from declarations.config.json.

Both are in Apple’s public API, so the App Store Connect key is enough for them. Both are also statements you stand behind, so pushing them is gated the same way the privacy declarations are.

declarations.config.json
{ "humanConfirmed": false, "contentRights": null, "ageRating": { "all-none": true, "user-generated-content": false, "messaging-and-chat": false, "social-media": false } }

Prerequisites

  • Store credentials: the App Store Connect key, and asc installed
  • An App Store Connect app record, so there is something to declare against

Answer content rights yourself

contentRights ships as null and the script will not fill it in. There is no safe default, because both answers assert something.

AnswerWhat you are saying
DOES_NOT_USE_THIRD_PARTY_CONTENTNothing in the app is licensed from someone else
USES_THIRD_PARTY_CONTENTThere is third-party content, and you hold the rights to it

The second answer is a claim, not a disclaimer. Picking it because it sounds like the cautious option asserts a licence you may not have.

Whoever owns the app decides this, once. Write the answer into declarations.config.json and it stays there for every later release.

The age-rating answers that ship

The default is all-none, every question answered NONE or false, with three answers written out as false. Apple defines all three by what happens between users, in its age rating definitions :

AnswerApple’s definitionSet it to true when
user-generated-content“the broad distribution of content created by users”Users can publish content that other users see
messaging-and-chat“Users can directly communicate with one another”Users can message each other
social-media“Redistribution, amplification, or interaction with user-generated content through a social feed or similar discovery method that visibly spreads content to many users”The app has a feed, or something like one, that spreads user content. App Store Connect accepts it only with user-generated-content also true

One user talking to a model is none of these. The app as shipped has no feed, no public profiles and no messages between users, so chat, create and scan leave all three false. Answering true to be safe is also a misdeclaration: it declares capabilities the app does not have, and it raises the rating in regions that rate them.

Apple has required the social media answer on every new app and update since September 2026 , which is why it is written out and not left to all-none. Its flag needs asc 3.1.0 or newer. Run brew upgrade asc if asc age-rating edit --help does not list --social-media.

There is no question about AI or chatbots. What the AI features affect is the content questions that all-none answers NONE: profanity, mature themes, violence and the rest. Those cover what the models return as well as what you wrote, so raise the ones your models and prompts can produce.

asc age-rating edit --help lists every question. In the ageRating block, "all-none": true is a bare switch. Every other key takes its answer, true, false or a level such as "INFREQUENT_OR_MILD", and is sent as --key value, so adding "gambling": true sends --gambling true and an explicit false overrides what all-none set. null leaves a question unanswered.

Push both

Read the answers

node .claude/skills/submit/scripts/declarations.mjs

It prints the age-rating flags it would send and the content-rights answer, or the two options if it is still unanswered. Nothing is sent. Under the flags it adds a note when social-media is unanswered, when an answer is one App Store Connect would refuse, and for each of the three between-users answers set to true, with what that answer claims. While chat, create or scan still ship, it also notes that all-none covers what the models return.

Confirm

Answer contentRights, then set the flag:

declarations.config.json
"humanConfirmed": true

--push fails on an unanswered contentRights before it even looks at the flag, because only you can say whether the app uses third-party content.

Push

node .claude/skills/submit/scripts/declarations.mjs --push --dry-run # see the asc commands node .claude/skills/submit/scripts/declarations.mjs --push

Verify

asc age-rating view --app "$ASC_APP_ID" --output table

Age-rating completeness is also one of the conditions asc validate aggregates before a submission, so a missing answer shows up there too.

Re-push on a later release only if the answers changed.

Google’s content rating is a Play Console job

Google’s equivalent is the IARC questionnaire, and it is not in the API. Neither are target audience, ads, the news and financial-app flags, or the account-deletion link. play.config.json’s playConsoleOnly block records those answers so they are decided once in the repo rather than improvised at the last minute, and the submit preflight lists whichever are still unanswered. Entering them is Play Console → Policy → App content.

play.config.json
"playConsoleOnly": { "humanConfirmed": false, "targetAudience": null, "containsAds": null, "isNewsApp": null, "contentRatingSubmitted": null, "accountDeletionUrl": null }

Answer the questionnaire by the same reading as Apple’s. IARC’s interaction question is about users exchanging content with each other, and one user talking to a model is not that.

Last updated on