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
- Verify developer identity once in the UI: Complete developer identity
verification (
INDIVIDUALorORGANIZATION) in the Android Developer Console soverificationStateisVERIFIED. - Enable the API and authenticate: Enable
androiddeveloperconsole.googleapis.comin your Google Cloud project and obtain a user-delegated OAuth 2.0 Bearer access token with scopehttps://www.googleapis.com/auth/androiddeveloperconsole. - Discover your developer account resource name: Call
GET /v1/developerAccounts(ListDeveloperAccounts) to retrievedeveloperAccounts/{developer_account}and verifyverificationStateisVERIFIED. - Check registration policy for the package name: Call
GET /v1/developerAccounts/{id}/androidPackages/{pkg}/registrationPolicy(GetAndroidPackageRegistrationPolicy) to inspectkeySelectionStrategy(SELECT_KEY_FROM_LISTorUSE_ANY_KEY) and any known historical signing keys (knownKeys). - Create the Android package resource: Call
POST /v1/developerAccounts/{id}/androidPackages?androidPackageId={pkg}(CreateAndroidPackage) with body{"name": ""}(creates resource inDRAFTstate). - 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 uniqueverificationTokenfor 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 sameDeveloperAccount). Skip Step 7 and the justification call in Step 8, and proceed directly to pollingGetAndroidPackageandGetAndroidPackageKey.
- Build and upload the verification APK (if state is
DRAFT): Embed the returnedverificationTokenstring intoassets/adi-registration.propertiesinside a minimal APK matchingpackageName, sign it with your private app signing key, and upload it usingPOST /upload/v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:verify(VerifyAndroidPackageKeyOwnership). - Submit justification (if required) and poll registration status: If the
key is in
OWNERSHIP_VERIFIEDstate andregistrationJustificationRequiredistrue, callPOST /v1/developerAccounts/{id}/androidPackages/{pkg}/keys/{sha256}:justifyAndroidPackageKeyRegistration(JustifyAndroidPackageKeyRegistration). PollGetAndroidPackageandGetAndroidPackageKeyuntilstatereachesREGISTERED.
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-aliasVerify SHA-256 signing certificate digest on a built APK (
apksigner):apksigner verify --print-certs app-release.apkInspect APK package name and embedded token file before upload (
aapt2andunzip):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
- Register package names with the Android Developer Console API
- Check app registration status with the Android Developer ID Status API
- Register on Android Developer Console
- Register on Google Play Console