Going to production
Nine checks, computed live from your records, and three of them surprise people.
The nine checks
The checklist is computed from live records every time you read it. It is the same checklist regardless of how you integrate — a web redirect, a server-to-server client and a drop-in component are all held to it identically.
One of them is conditional. When a conditional check does not apply it reports applicable: false, passes automatically and never blocks.
Every code, its label as the API exports it, and what makes it pass
| Code | Label | How to pass |
|---|---|---|
| production_record | Production environment set up | Set up Production. It creates a separate record with its own client id. |
| verified_publisher | Verified publisher / Verified developer identity | The publisher the production application names is verified — a verified publisher profile, or, with none named, your own verified UnifyID identity. |
| app_name | Application name | A non-empty name on the production record. It is the name people see on the consent screen. |
| homepage_url | Homepage | An https homepage URL on the production record. |
| privacy_policy_url | Privacy policy | An https link to the privacy policy people can read before they agree. |
| terms_url | Terms of service | An https link to the terms that apply to the application. |
| https_redirect | Secure redirect URIs | At least one https redirect URI on the production record. |
| restricted_scope_justifications | Restricted scope justifications | Conditional. Only when restricted scopes are requested: at least 20 characters explaining each one. |
| sandbox_sign_in | Recent Sandbox sign-in | A successful sign-in to the sandbox environment in the last 30 days. |
The three that surprise people
Reading the checklist
The application's Go live screen (/applications/<applicationId>/production) reads the checklist every time you open it and shows each failing check with the path that fixes it. It is one session-bound route:
GET /v1/developer/applications/{applicationId}/production/checklistWhat comes back under data
passed- True only when every applicable check passes.
checks[]- Each one has
code,label,passed,applicable,detail,configurePathandevidence. restrictedScopes- The restricted scopes on the production record — the ones that need justifications.
projectId, sandboxApplicationId, productionApplicationId, checkedAt- Identifiers and the moment the checklist was computed.
Submitting for review
The same Go live screen submits: it runs the checklist against your records and sends the request when every applicable check passes. What it sends is POST /v1/developer/applications/{applicationId}/production/review, with an optional body of restrictedScopeJustifications — an object of scope code to text — and notes; PUT …/production/review saves the same body as a draft without submitting. Withdraw an open submission with POST …/production/review/withdraw. All of these are session-bound developer routes.
GET …/production is the review's state: not_set_up before a production record exists, then draft, in_review, approved, changes_requested, rejected or withdrawn.
What this does not do
- Passing the checklist is not approval. It is what lets you ask. A submission is reviewed by staff, and
verified_publishermeans someone verified the publisher, not the application. - Restricted scopes need production first, which is circular on purpose. A restricted scope such as
date_of_birthis refused at authorize until the application is production-active — so you cannot exercise it end-to-end in the sandbox, and the justification is how you make the case. - A justification under 20 characters fails silently as "missing". The check does not distinguish a short answer from no answer.
Verified against API commit 234dba22 on 2026-10-18. The routes, scopes, checklist, events and limits on these pages are read from that export, not typed.