DEV Community

Kun Shen
Kun Shen

Posted on

Build a Read-Only Android Package Registration Gate

An Android registration gate should answer two different questions in sequence: “Is this package name registered to any verified developer?” and “Is this package name registered with the public certificate that signed this release?” Combining those questions into one vague green check hides the exact failure a developer needs to fix.

The Android Developer ID Status API is suitable for this job because it is a read-only status service. It does not register a package or mutate keys. The official documentation describes a package-only request and an optional certificateFingerprint query parameter for the certificate-aware request.

Level 1: package-only signal

The package-only call tests whether the application ID is registered. It is useful early in a build, when the final signed artifact may not exist yet.

curl -sS \
  -H "X-Goog-Api-Key: $ANDROID_STATUS_API_KEY" \
  "https://androiddeveloperidstatus.googleapis.com/v1/packages/com.example.app/packageRegistrationStatus:check"
Enter fullscreen mode Exit fullscreen mode

A valid response state is REGISTERED or NOT_REGISTERED. The result does not tell you whether your next release certificate matches. It also does not prove that your organization owns the package. It reports registration state for the supplied identifier.

Level 2: artifact-aware signal

After signing the release artifact, extract the signing certificate's public SHA-256 fingerprint and make the certificate-aware check.

curl -sS \
  -H "X-Goog-Api-Key: $ANDROID_STATUS_API_KEY" \
  "https://androiddeveloperidstatus.googleapis.com/v1/packages/com.example.app/packageRegistrationStatus:check?certificateFingerprint=PUBLIC_SHA256_HEX"
Enter fullscreen mode Exit fullscreen mode

That check can return:

  • REGISTERED: the package-and-fingerprint pair is registered.
  • REGISTERED_WITH_ANOTHER_CERTIFICATE_FINGERPRINT: the package is registered, but not with the fingerprint supplied in this request.
  • NOT_REGISTERED: the supplied lookup is not registered according to the service response.

The distinction is the reason to retain both levels. A package-only green result and an artifact-aware mismatch should produce a signing investigation, not a generic “registration passed” message.

For a compact state and remediation map, see this package-registration status workflow. Treat it as an operational explanation; the API response and official consoles are the source of truth.

Fail the right thing

Status, authentication, quota, and service availability are separate dimensions. The official API guide uses standard Google Cloud error objects and recommends building logic around the canonical status field rather than parsing English error text.

A reasonable gate policy is:

Condition Release-gate action
REGISTERED for final package and certificate Pass the registration check
NOT_REGISTERED Block protected-channel promotion and assign registration work
Different certificate Block and start signing-identity diagnosis
INVALID_ARGUMENT Fail the job configuration without retry
PERMISSION_DENIED Fail configuration; verify API enablement and credential scope
RESOURCE_EXHAUSTED Mark the check inconclusive; retry later with backoff
INTERNAL or UNAVAILABLE Retry with bounded exponential backoff

Do not translate every non-200 response into NOT_REGISTERED. That produces false negatives precisely when quota or networking is unhealthy.

Keep the API key on the server side

The API supports key credentials, but that does not make a key safe to embed in a browser bundle, APK, build log, or public workflow file. Store it in the CI platform's secret store, send it only from a trusted runner, and mask derived command output that might echo headers.

Restrict the key to the required API where Google Cloud supports that restriction. Rotate it if it appears in logs. Also budget calls: the official page currently publishes a default limit of 1,000 CheckPackageRegistrationStatus requests per project per day. Cache a result only for a deliberately short period, because registration state can change.

Log decisions, not credentials

A useful audit record contains the final package name, a normalized public fingerprint, response state, HTTP status, canonical error status when present, timestamp, workflow run, and source commit. It must not contain the API key, a private signing key, keystore password, or whole APK.

This turns the gate into reproducible evidence. When a later build changes state, the team can compare the exact artifact identity and status response instead of debating which screenshot was current.

Primary reference: Check app registration status with the Android Developer ID Status API, last updated by Android Developers on July 30, 2026 when checked for this article.

Disclosure: I work on PkgReady, an independent implementation aid. It is not affiliated with or endorsed by Google or Android. This article was prepared with AI assistance and manually checked against the linked primary source on August 15, 2026.

Top comments (0)