Android Developer Console API

The Android Developer Console API is a RESTful service that lets verified developers automate Android developer verification workflows in the Android Developer Console, including retrieving developer accounts, checking key eligibility requirements, registering Android package names, registering app signing keys, and verifying key ownership.

Overview, use cases, and implementation context

Key use cases and features

  • Automated CI/CD package name registration: Register dozens or hundreds of Android package names programmatically (CreateAndroidPackage).
  • Pre-flight historical key policy inspection: Programmatically inspect whether Google has previously observed a package name in the ecosystem and whether registering a specific signing certificate requires key ownership verification (GetAndroidPackageRegistrationPolicy).
  • Automated app signing key registration and ownership verification: Register public signing certificate SHA-256 fingerprints (CreateAndroidPackageKey), retrieve unique verification challenge tokens (verificationToken), and automate proof of private key possession using single-request or resumable signed APK uploads (VerifyAndroidPackageKeyOwnership).
  • Programmatic justification submission: Submit ownership justifications (JustifyAndroidPackageKeyRegistration).
  • Status monitoring: Monitor registration status across developer accounts, package names, and app signing keys (GetDeveloperAccount, ListDeveloperAccounts, GetAndroidPackage, ListAndroidPackages, GetAndroidPackageKey, ListAndroidPackageKeys).

End-to-end implementation workflow

  1. Verify developer identity once in the UI: Complete developer identity verification (INDIVIDUAL or ORGANIZATION) in the Android Developer Console so verificationState is VERIFIED.
  2. Enable the API and authenticate: Enable androiddeveloperconsole.googleapis.com in your Google Cloud project and obtain a user-delegated OAuth 2.0 Bearer access token with scope https://www.googleapis.com/auth/androiddeveloperconsole.
  3. Discover your developer account resource name: Call GET /v1/developerAccounts (ListDeveloperAccounts) to retrieve developerAccounts/{developer_account} and verify verificationState is VERIFIED.
  4. Check registration policy for the package name: Call GET /v1/developerAccounts/{id}/androidPackages/{pkg}/registrationPolicy (GetAndroidPackageRegistrationPolicy) to inspect keySelectionStrategy (SELECT_KEY_FROM_LIST or USE_ANY_KEY) and any known historical signing keys (knownKeys).
  5. Create the Android package resource: Call POST /v1/developerAccounts/{id}/androidPackages?androidPackageId={pkg} (CreateAndroidPackage) with body {"name": ""} (creates resource in DRAFT state).
  6. Register your app signing key fingerprint: Call POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys (CreateAndroidPackageKey) with JSON body {"certificateFingerprintSha256": "..."}. Inspect the returned state:
    • DRAFT: Proof of private key ownership is required, and the response includes a unique verificationToken for Step 7.
    • IN_REVIEW: Proof of ownership and justification are skipped automatically (for example, when registering a new package name that has never been seen on Android, or when you have already verified ownership of this signing key for another package name in the same DeveloperAccount). Skip Step 7 and the justification call in Step 8, and proceed directly to polling GetAndroidPackage and GetAndroidPackageKey.
  7. Build and upload the verification APK (if state is DRAFT): Embed the returned verificationToken string into assets/adi-registration.properties inside a minimal APK matching packageName, sign it with your private app signing key, and upload it using POST /upload/v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:verify (VerifyAndroidPackageKeyOwnership).
  8. Submit justification (if required) and poll registration status: If the key is in OWNERSHIP_VERIFIED state and registrationJustificationRequired is true, call POST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:justifyAndroidPackageKeyRegistration (JustifyAndroidPackageKeyRegistration). Poll GetAndroidPackage and GetAndroidPackageKey until state reaches REGISTERED.

Local CLI commands for preparing key fingerprints and verification APKs

  • Extract SHA-256 certificate fingerprint from a keystore (keytool):

    keytool -list -v -keystore release-key.jks -alias my-key-alias
  • Verify SHA-256 signing certificate digest on a built APK (apksigner):

    apksigner verify --print-certs app-release.apk
  • Inspect APK package name and embedded token file before upload (aapt2 and unzip):

    aapt2 dump badging app-release.apk | head -n 1
    unzip -p app-release.apk assets/adi-registration.properties

Android Developer Console UI and API capabilities

Task Android Developer Console Web UI (android.google.com/developerconsole) Android Developer Console API
Developer identity verification (KYC/KYB) and fee payment Supported (required one-time prerequisite) Not supported using the API (read-only status check using GetDeveloperAccount and ListDeveloperAccounts)
View linked developer accounts Account switcher in console header GET /v1/developerAccounts (ListDeveloperAccounts)
Inspect historical signing keys and policy for a package name Displayed during "Register package name" wizard GET /v1/.../registrationPolicy (GetAndroidPackageRegistrationPolicy)
Register a new Android package name Package names > Register package name POST /v1/{parent}/androidPackages?androidPackageId=... (CreateAndroidPackage)
View or list registered and draft package names Package names dashboard table GET /v1/{name} (GetAndroidPackage), GET /v1/{parent}/androidPackages (ListAndroidPackages)
Add an app signing key and generate challenge token Package detail > Add signing key POST /v1/{parent}/keys (CreateAndroidPackageKey)
Prove private key ownership (adi-registration.properties) Upload signed snippet APK in console UI POST /upload/v1/{name}:verify (VerifyAndroidPackageKeyOwnership)
Submit justification when key requires manual review Text prompt during key registration workflow POST /v1/{name}:justifyAndroidPackageKeyRegistration (JustifyAndroidPackageKeyRegistration)

Service configuration and authentication

All API requests must use HTTPS and include an Authorization: Bearer ACCESS_TOKEN header obtained using the OAuth 2.0 Web Server flow for a Google Account that has completed developer identity verification in the Android Developer Console.

Property Value
Base REST endpoint https://androiddeveloperconsole.googleapis.com
Media upload endpoint https://androiddeveloperconsole.googleapis.com/upload
API version v1
Required OAuth 2.0 scope https://www.googleapis.com/auth/androiddeveloperconsole
Default quota limit 2,000 requests per day per Google Cloud project per method

API resources and endpoints

The Android Developer Console API organizes resources in the following hierarchy:

  • DeveloperAccount (developerAccounts/{developer_account})
    • AndroidPackage (developerAccounts/{developer_account}/androidPackages/{android_package})
      • AndroidPackageRegistrationPolicy (developerAccounts/{developer_account}/androidPackages/{android_package}/registrationPolicy)
      • AndroidPackageKey (developerAccounts/{developer_account}/androidPackages/{android_package}/keys/{key})

Resource: DeveloperAccount

Represents an account in the Android Developer Console associated with a developer identity.

Field Type Description
name string Identifier. Resource name in the format developerAccounts/{developer_account}.
displayName string Output only. Human-readable name associated with the developer account (individual name or organization name).
verificationState enum (VerificationState) Output only. Current developer identity verification status of the account.

Enum: DeveloperAccount.VerificationState

Value Description
VERIFIED Developer identity verification is complete. The account can register package names and app signing keys.
NOT_VERIFIED Developer identity verification hasn't been completed in the Android Developer Console.

Methods: DeveloperAccount

Method HTTP request Description
GetDeveloperAccount GET /v1/{name=developerAccounts/*} Retrieves metadata and verification state for a single DeveloperAccount.
ListDeveloperAccounts GET /v1/developerAccounts Lists all DeveloperAccount objects accessible to the authenticated Google Account (unpaginated).

Resource: AndroidPackage

Represents an Android package name registered or being registered under a DeveloperAccount.

Field Type Description
name string Identifier. Resource name in the format developerAccounts/{developer_account}/androidPackages/{android_package}, where {android_package} is the Android package name (for example, com.example.myapp).
packageName string Output only. The Android package name (for example, com.example.myapp).
state enum (AndroidPackage.State) Output only. Current registration lifecycle state of the package name.
registeredAppStore boolean Output only. Indicates whether this package name is currently active as a registered app store.

Enum: AndroidPackage.State

Value Description
DRAFT The package name resource has been created, and app signing key registration or ownership verification is still in progress.
IN_REVIEW The package name registration and any required key justification have been submitted and are under review by Google. A package transitions from DRAFT to IN_REVIEW either immediately upon CreateAndroidPackageKey (when key ownership verification is skipped, including when the key was already verified for another package name in the same DeveloperAccount) or after completing VerifyAndroidPackageKeyOwnership and, if required, JustifyAndroidPackageKeyRegistration.
REGISTERED The package name is actively registered to this developer account for Android developer verification.
PENDING_TRANSFER The package name is awaiting completion of an ownership transfer to another developer account.

Resource: AndroidPackageRegistrationPolicy

Singleton resource returned by GetAndroidPackageRegistrationPolicy that describes historical public signing keys detected for a package name and whether registering the package name with a given signing key requires a written justification.

Field Type Description
name string Identifier. Resource name in the format developerAccounts/{developer_account}/androidPackages/{android_package}/registrationPolicy.
knownKeys[] object (KnownKey) List of historical app signing keys previously observed distributing apps with this package name, sorted lexicographically by certificateFingerprintSha256.
knownKeys[].certificateFingerprintSha256 string Output only. Normalized 64-character lowercase hexadecimal SHA-256 fingerprint of the historical signing certificate (without colons).
knownKeys[].justificationRequirement enum (JustificationRequirement) Output only. Indicates whether registering this key requires calling JustifyAndroidPackageKeyRegistration (REQUIRED or NOT_REQUIRED). If the signing key was previously verified on another package name under the same DeveloperAccount, both VerifyAndroidPackageKeyOwnership and JustifyAndroidPackageKeyRegistration are skipped even when justificationRequirement is REQUIRED.
keySelectionStrategy enum (KeySelectionStrategy) Output only. Key selection policy for registering this package name: SELECT_KEY_FROM_LIST (must register a key from knownKeys) or USE_ANY_KEY (any valid app signing key owned by the developer can be registered).

Enum: KnownKey.JustificationRequirement

Value Description
REQUIRED Registering this known key requires submitting a written justification using JustifyAndroidPackageKeyRegistration after completing VerifyAndroidPackageKeyOwnership (unless the key was previously verified on another package name under the same DeveloperAccount, in which case both VerifyAndroidPackageKeyOwnership and JustifyAndroidPackageKeyRegistration are skipped).
NOT_REQUIRED Registering this known key does not require a justification. The key transitions directly to IN_REVIEW after VerifyAndroidPackageKeyOwnership (or immediately upon CreateAndroidPackageKey if the key was previously verified on another package name under the same DeveloperAccount).

Enum: AndroidPackageRegistrationPolicy.KeySelectionStrategy

Value Description
SELECT_KEY_FROM_LIST The caller must register one of the historical keys listed in knownKeys.
USE_ANY_KEY In addition to any keys in knownKeys, the caller can register any valid app signing key not previously observed in the Android ecosystem.

Methods: AndroidPackage

Method HTTP request Description
GetAndroidPackageRegistrationPolicy GET /v1/{name=developerAccounts/*/androidPackages/*/registrationPolicy} Retrieves the key selection strategy and known historical signing keys for a package name.
CreateAndroidPackage POST /v1/{parent=developerAccounts/*}/androidPackages?androidPackageId={package_name} Creates a new AndroidPackage resource in DRAFT state to start registering a package name.
GetAndroidPackage GET /v1/{name=developerAccounts/*/androidPackages/*} Retrieves details and current registration state for an existing AndroidPackage.
ListAndroidPackages GET /v1/{parent=developerAccounts/*}/androidPackages Lists AndroidPackage objects under a DeveloperAccount (pageSize max 1000, pageToken).

Resource: AndroidPackageKey

Represents a public app signing certificate fingerprint associated with an AndroidPackage and tracks ownership verification and registration review state.

Field Type Description
name string Identifier. Server-assigned resource name in the format developerAccounts/{developer_account}/androidPackages/{android_package}/keys/{key}, where {key} is a normalized 64-character lowercase hexadecimal SHA-256 fingerprint without colons. Must be omitted or empty when calling CreateAndroidPackageKey.
certificateFingerprintSha256 string Required. Immutable. SHA-256 hash of the app signing certificate. On input in CreateAndroidPackageKey, accepts either plain 64-character hex (60e860e8...) or colon-separated hex (60:E8:60:E8:...). On output, always normalized to 64-character lowercase hexadecimal without colons.
state enum (AndroidPackageKey.State) Output only. Current verification and registration lifecycle state of the key.
verificationToken string Output only. Unique challenge token generated by Google. Used only when state is DRAFT (can be ignored when CreateAndroidPackageKey transitions the key directly to IN_REVIEW). When the state is DRAFT, embed this string inside assets/adi-registration.properties in a signed APK to complete VerifyAndroidPackageKeyOwnership.
registrationJustificationRequired boolean Output only. If true and the key is in OWNERSHIP_VERIFIED state, you must submit a written justification using JustifyAndroidPackageKeyRegistration before registration proceeds to IN_REVIEW. If CreateAndroidPackageKey transitions the key directly to IN_REVIEW (because the key was previously verified on another package name in the same DeveloperAccount), justification is skipped.

Enum: AndroidPackageKey.State

Value Description
DRAFT The key resource has been created, and proof of private key possession using signed APK upload (VerifyAndroidPackageKeyOwnership) is still required because ownership of this key has not yet been verified on any package name under this DeveloperAccount.
OWNERSHIP_VERIFIED Private key ownership has been verified using a signed APK upload. If registrationJustificationRequired is true, a justification is still required before review begins.
IN_REVIEW The key registration is under review by Google. A key transitions here either immediately upon CreateAndroidPackageKey when proof of ownership is not required (for example, on a new package name that has never been seen on Android, or when the key was previously verified on another package name under the same DeveloperAccount, which also skips JustifyAndroidPackageKeyRegistration), directly after VerifyAndroidPackageKeyOwnership (if registrationJustificationRequired is false), or after JustifyAndroidPackageKeyRegistration (if registrationJustificationRequired is true).
REGISTERED The app signing key is actively registered to this package name for Android developer verification.
PENDING_TRANSFER The app signing key registration is awaiting completion of a transfer.

Methods: AndroidPackageKey

Method HTTP request Description
CreateAndroidPackageKey POST /v1/{parent=developerAccounts/*/androidPackages/*}/keys Registers a new app signing certificate SHA-256 fingerprint under an AndroidPackage. Returns the key in DRAFT state (when proof of ownership using VerifyAndroidPackageKeyOwnership is required) or directly in IN_REVIEW state (when ownership verification is skipped, such as for a new package name that has never been seen on Android or a key already verified on another package name in the same DeveloperAccount).
GetAndroidPackageKey GET /v1/{name=developerAccounts/*/androidPackages/*/keys/*} Retrieves status, fingerprint, and verification metadata of a specific AndroidPackageKey.
ListAndroidPackageKeys GET /v1/{parent=developerAccounts/*/androidPackages/*}/keys Lists all AndroidPackageKey objects registered under an AndroidPackage (pageSize max 1000, pageToken).
VerifyAndroidPackageKeyOwnership POST /upload/v1/{name=developerAccounts/*/androidPackages/*/keys/*}:verify Uploads a signed minimal APK containing verificationToken in assets/adi-registration.properties to verify private key ownership and submit ready keys for review.
JustifyAndroidPackageKeyRegistration POST /v1/{name=developerAccounts/*/androidPackages/*/keys/*}:justifyAndroidPackageKeyRegistration Submits additional justification context when registrationJustificationRequired is true and submits verified keys for review.

Error handling

When an API request fails, the Android Developer Console API returns an HTTP 4xx or 5xx status code and a standard google.rpc.Status JSON error body:

{
  "error": {
    "code": 400,
    "message": "Invalid certificate fingerprint SHA256 format.",
    "status": "INVALID_ARGUMENT",
    "details": []
  }
}

HTTP status codes and common resolutions

HTTP code gRPC status Common causes Resolution
400 Bad Request INVALID_ARGUMENT Missing or invalid Java-style androidPackageId; invalid certificateFingerprintSha256 format; non-empty name field on CreateAndroidPackage or CreateAndroidPackageKey; uploaded APK is unsigned, corrupted, missing assets/adi-registration.properties, missing matching verificationToken, or signed with a mismatched certificate. Validate request formats against the resource schemas, omit or empty name on create calls, and verify your APK signature and embedded token using apksigner verify --print-certs and unzip -p app-release.apk assets/adi-registration.properties before uploading.
400 Bad Request FAILED_PRECONDITION DeveloperAccount has verificationState: NOT_VERIFIED; key selection violates AndroidPackageRegistrationPolicy (SELECT_KEY_FROM_LIST); calling VerifyAndroidPackageKeyOwnership or JustifyAndroidPackageKeyRegistration in an ineligible state. Complete developer identity verification in the Android Developer Console, check GetAndroidPackageRegistrationPolicy first, and inspect the resource's current state.
401 Unauthorized UNAUTHENTICATED Missing, expired, or invalid OAuth 2.0 Bearer access token, or attempt to authenticate using an API key or service account. Obtain a fresh user-delegated OAuth 2.0 Bearer access token with scope https://www.googleapis.com/auth/androiddeveloperconsole.
403 Forbidden PERMISSION_DENIED Authenticated user lacks permission on the target DeveloperAccount or AndroidPackage, or the Android Developer Console API isn't enabled on the Google Cloud project. Verify account membership using ListDeveloperAccounts and ensure androiddeveloperconsole.googleapis.com is enabled in Google Cloud Console.
404 Not Found NOT_FOUND Specified DeveloperAccount, AndroidPackage, or AndroidPackageKey resource path doesn't exist. Confirm resource paths using ListDeveloperAccounts, ListAndroidPackages, or ListAndroidPackageKeys. Ensure {key} IDs use lowercase hex without colons.
409 Conflict ALREADY_EXISTS Package name or SHA-256 certificate fingerprint is already registered under this or another developer account. Inspect existing registrations using GetAndroidPackage or GetAndroidPackageKey, or check historical ownership using GetAndroidPackageRegistrationPolicy.
429 Too Many Requests RESOURCE_EXHAUSTED Exceeded per-method quota of 2,000 requests per day per Google Cloud project. Implement exponential backoff with jitter and avoid high-frequency polling loops.
500 / 503 INTERNAL / UNAVAILABLE Transient backend error or temporary service unavailability. Retry idempotent requests with truncated exponential backoff.

HTTP request and response examples

Replace placeholder values such as ACCESS_TOKEN, 1234567890, com.example.myapp, and 60e860e8... with your own values.

1. GetDeveloperAccount

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890"

Response:

{
  "name": "developerAccounts/1234567890",
  "displayName": "Example Developer",
  "verificationState": "VERIFIED"
}

2. ListDeveloperAccounts

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts"

Response:

{
  "developerAccounts": [
    {
      "name": "developerAccounts/1234567890",
      "displayName": "Example Developer",
      "verificationState": "VERIFIED"
    }
  ]
}

3. GetAndroidPackageRegistrationPolicy

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/registrationPolicy"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/registrationPolicy",
  "knownKeys": [
    {
      "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
      "justificationRequirement": "NOT_REQUIRED"
    }
  ],
  "keySelectionStrategy": "SELECT_KEY_FROM_LIST"
}

4. CreateAndroidPackage

curl -X POST \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"name": ""}' \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages?androidPackageId=com.example.myapp"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp",
  "packageName": "com.example.myapp",
  "state": "DRAFT",
  "registeredAppStore": false
}

5. GetAndroidPackage

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp",
  "packageName": "com.example.myapp",
  "state": "REGISTERED",
  "registeredAppStore": false
}

6. ListAndroidPackages

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages?pageSize=100"

Response:

{
  "androidPackages": [
    {
      "name": "developerAccounts/1234567890/androidPackages/com.example.myapp",
      "packageName": "com.example.myapp",
      "state": "REGISTERED",
      "registeredAppStore": false
    }
  ],
  "nextPageToken": ""
}

7. CreateAndroidPackageKey

curl -X POST \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
    "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123"
  }' \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "state": "DRAFT",
  "verificationToken": "token_xyz987654321"
}

8. GetAndroidPackageKey

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "state": "REGISTERED"
}

9. ListAndroidPackageKeys

curl -X GET \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys?pageSize=100"

Response:

{
  "androidPackageKeys": [
    {
      "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
      "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
      "state": "REGISTERED"
    }
  ],
  "nextPageToken": ""
}

10. VerifyAndroidPackageKeyOwnership

Option A: Single-request media upload

curl -X POST \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @app-release.apk \
  "https://androiddeveloperconsole.googleapis.com/upload/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123:verify?uploadType=media"

Option B: Resumable upload protocol (recommended for large APKs or CI/CD)

Step 1: Start the resumable upload session and extract the returned X-Goog-Upload-URL header:

curl -i -X POST \
  "https://androiddeveloperconsole.googleapis.com/upload/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123:verify" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: FILE_SIZE_IN_BYTES" \
  -H "X-Goog-Upload-Header-Content-Type: application/vnd.android.package-archive" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123"
  }'

Step 2: Upload the signed APK binary to UPLOAD_SESSION_URI and finalize the session:

curl -X PUT \
  "UPLOAD_SESSION_URI" \
  -H "Content-Length: FILE_SIZE_IN_BYTES" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@app-release.apk"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "state": "IN_REVIEW"
}

11. JustifyAndroidPackageKeyRegistration

curl -X POST \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
    "justification": "We previously distributed com.example.myapp directly from https://downloads.example.com and are migrating to our rotated production key."
  }' \
  "https://androiddeveloperconsole.googleapis.com/v1/developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123:justifyAndroidPackageKeyRegistration"

Response:

{
  "name": "developerAccounts/1234567890/androidPackages/com.example.myapp/keys/60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "certificateFingerprintSha256": "60e860e8d77251234567890abcdef1234567890abcdef1234567890abcdef123",
  "state": "IN_REVIEW",
  "registrationJustificationRequired": true
}

Additional resources