The Play Integrity API answers one narrow, practical question for your backend: is this request coming from the copy of my app that Google Play shipped, on a device that is what it claims to be? Your server asks Google for an integrity verdict, receives a signed payload, and decides — on the server, never on the client — how far to trust the interaction. It is the standard way to slow down tampered builds, scripted clients, emulators and sideloaded copies before they reach your game economy, your subscription entitlements or your ad revenue.
This guide follows the order you will actually work in: enable the API, link a Cloud project, choose between a standard and a classic request, warm up the token provider, request and decrypt a token, read the verdict fields, handle quota and error codes, and roll enforcement out without locking out paying users. One rule runs through all of it — the API hands you signals for your own decisions, and the only durable way to pass an integrity check is to ship a genuine app through the official channel.
1. What the API attests, and what it does not
Three verdict families come back by default, and each one answers a different question.
- appIntegrity — did this come from your unmodified binary? The
appRecognitionVerdictreturnsPLAY_RECOGNIZEDwhen the package and certificate match what Google Play distributes,UNRECOGNIZED_VERSIONwhen the certificate or package name does not match Play records, andUNEVALUATEDwhen a prerequisite was missed. - deviceIntegrity — is the device genuine? By default the
deviceRecognitionVerdictcan containMEETS_DEVICE_INTEGRITY: a genuine, certified Android device, with hardware-backed proof on Android 13 and higher that the bootloader is locked and the loaded software is genuine. A device that meets no label at all simply gets the field omitted. - accountDetails — does the user hold an entitlement? The
appLicensingVerdictreturnsLICENSED(installed or updated from Google Play),UNLICENSED, orUNEVALUATED.
Two points of discipline matter more than the field list. First, Google states plainly that the API works best alongside other signals, as part of an overall anti-abuse strategy and not as your sole mechanism — a verdict is one input, and treating it as the only gate produces both false positives and easy bypasses. Second, these are risk signals, not judgments about your users: a hobbyist on a rooted device is not a criminal, and the response should be proportionate to what is actually at stake on that screen.
2. Step 1 — enable the API and link a Cloud project
Every app or SDK that calls the API needs a Google Cloud project, because that is where usage is monitored and quota is managed.
- In the Google Cloud Console, create a new project or choose an existing one you want to use.
- Go to APIs and services → Enable APIs and services, search for Play Integrity API, and click Enable.
- Then link that project to your app. In the Play Console, open your app, go to Protected with Play, find Play Integrity API and choose Get started.
Linking is the step that unlocks everything else. A project that is enabled in Cloud but not linked in the Play Console — or in the Play SDK Console for SDKs — is not eligible for the additional configuration options or for a quota increase. The linking flow will enable the API for you if you skipped the console step, so either order works; skipping the link does not.
Decryption needs a credential your app must never carry. Create a service account inside the linked Cloud project and call the decode endpoint from your server with the playintegrity scope. The client asks for tokens; only the server opens them.
3. Step 2 — choose a standard or a classic request
There are two request styles, and picking the right one first saves a rewrite later.
- Standard requests are the default choice for apps on Google Play. They run on Android 5.0 (API level 21) and higher, and they are built from two calls: prepare the integrity token provider ahead of time, then request a token when you actually need one.
- Classic requests exist for the cases standard requests do not cover — most notably apps distributed exclusively outside Google Play, and SDKs. Structurally a classic request is a single call that takes a
nonceyou generate, and apps that are not distributed on Play must also pass their Cloud project number withsetCloudProjectNumber(). Apps on Play are linked through the console and do not set it in the request.
If your app is on Google Play, standard is the answer. Reach for classic when distribution genuinely happens outside Play, or when a specific integration constrains you.
4. Step 3 — warm up the provider, then request the token
A standard request is deliberately split in two so that the slow part never lands on the user's critical path.
Prepare, or warm up, the integrity token provider. Call this well before you need a verdict — typically at app launch, which works well because the call is asynchronous and does not affect startup time. Warming up lets Google Play cache partial attestation information on the device so the later request is fast; re-preparing is also a lighter way to make the next verdict more current. The provider itself can expire if it is held too long, which surfaces as INTEGRITY_TOKEN_PROVIDER_INVALID; handle that by requesting a fresh provider rather than retrying the stale one.
Request an integrity token on demand. When the app makes a server call you want to vouch for, request a token and send it to your backend. Attach a request hash: compute a digest — SHA-256 of the stable parameters, for example — and pass it in, because the API echoes that value back inside the signed response. Without it, a token is bound to the device but not to the specific request, which is exactly the gap a proxy needs to reuse it for something else.
Classic requests use a nonce you supply instead. It is passed to Google as-is, so never put personal or sensitive data in it, and it must be valid Base64 of an accepted length — otherwise you collect NONCE_TOO_SHORT, NONCE_TOO_LONG or NONCE_IS_NOT_BASE64 instead of a verdict.
5. Step 4 — decrypt and verify on your server
The token that reaches your backend is encrypted and useless until Google decrypts it. Using your service account credentials and the playintegrity scope, your server calls:
POST https://playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken
{ "integrity_token": "INTEGRITY_TOKEN" }
What comes back is a plain-text JSON payload. Before you look at a single verdict, validate the request details, because the payload is only meaningful if it really is the answer to your request:
requestPackageNamemust equal your package name;requestHashmust equal the hash you sent;timestampMillismust be recent — compare it with a freshness window (an allowed window of milliseconds) and reject anything older, since a stale token is a replay candidate.
Google Play also applies automatic replay protection, preventing an integrity token from being reused many times. Treat that as a safety net rather than a substitute for your own freshness check, and decode the token server-side at the moment of the action instead of caching one for a day.
6. Reading the payload without over-blocking
The payload is JSON containing requestDetails, appIntegrity, deviceIntegrity, accountDetails and — once you opt in — environmentDetails. Field order is not guaranteed, so always read by key. A workable decision ladder looks like this.
- Confirm the app first:
PLAY_RECOGNIZEDmeans the binary and certificate are the ones Play distributes. - Then look at the device:
MEETS_DEVICE_INTEGRITYis the default bar. The additional labels —MEETS_BASIC_INTEGRITY,MEETS_STRONG_INTEGRITYandMEETS_VIRTUAL_INTEGRITY— are opt-in and belong to a tiered strategy, not to a first release. - Use
accountDetailswhere entitlements matter:UNLICENSEDmeans the account has no Play entitlement, though on some older devices an entitlement can persist after uninstall, so read it as a signal rather than a fact. - If you enabled
environmentDetails, theappAccessRiskVerdicttells you whether apps able to capture the screen or draw overlays are present — itsappsDetectedlist uses values such asKNOWN_INSTALLED,UNKNOWN_INSTALLEDandUNKNOWN_CAPTURING— and the Play Protect verdict summarises the device's Play Protect state.
Two non-obvious cases deserve design attention. Emulators that pass system integrity checks and meet core Android compatibility requirements can receive a device label of their own, so "emulator" does not automatically mean "attacker". And a device that meets no label omits the field entirely, which means code that assumes the key is always present crashes instead of failing closed.
7. Quota, error codes, and failing safely
By default your app can make up to 10,000 requests per day across all installs. That ceiling arrives faster than teams expect after a launch, so watch usage in the linked Cloud project and request an increase while the trend line still leaves you room. Exceeding it surfaces as TOO_MANY_REQUESTS (error code -8), which you absorb with exponential backoff rather than by blocking users.
Error handling is where integrations usually go wrong. Treat these as transient and retry with backoff: NETWORK_ERROR (-3), TOO_MANY_REQUESTS (-8), GOOGLE_SERVER_UNAVAILABLE (-12) and CLIENT_TRANSIENT_ERROR (-18). Others are environmental — no Play Store, no Play services, an outdated Play services version, a missing Play account, a Cloud project number the API rejects. Google's guidance for those is to treat the outcome as if the client had failed the checks, while you still keep the interaction usable where you reasonably can.
Handle errors as a policy question, not just a code path. Blocking everyone whose device looks unusual turns an anti-abuse signal into a retention problem; silently ignoring every failure is the opposite mistake. Decide per surface — a leaderboard can be permissive, a wallet top-up can be strict — and write the decision down so the next engineer inherits the reasoning.
Google also ships remediation dialogs: app-triggered, Google-guided flows that help a legitimate user repair the underlying problem, such as installing the official build from Play or restoring connectivity, instead of leaving them at a dead end. And if you need to spot repeat abuse from the same hardware after enforcement, the device recall feature (beta) is built for that.
8. Rolling it out without breaking your users
Telemetry before enforcement. Log verdicts and their distribution for a few weeks before you gate anything, so you know the real proportion of UNEVALUATED and UNLICENSED results in your own install base rather than someone else's blog post. Then enforce in tiers: the default device label first, additional labels later, and one surface at a time. Keep the client able to distinguish "retry" from "no", and make sure the app degrades gracefully when the API is simply unavailable — a user on a flaky network should not lose access to content they already paid for.
9. Where KappS fits in
KappS helps developers keep accounts and releases in a state that stands up to platform scrutiny — preparing and submitting compliant material, never defeating checks. In practice that means:
- Release hygiene. Signed with Play App Signing, uploaded through the official channel, version codes and certificates consistent with the records Google Play recognises — the conditions under which
PLAY_RECOGNIZEDis even possible. - Account readiness. Developer verification, payment profile and tax records aligned with the legal identity behind the account, so a launch is not stalled by an unrelated review.
- Integration review. A second pair of eyes on how the client requests tokens, what the server branches on, and whether the enforcement tier matches the business risk.
We do not, and will not, offer integrity bypass, verdict spoofing, or tooling that hides a tampered build from Play. Those are precisely what this API exists to detect, they put the account at risk, and they are not a service we provide. The only durable way to pass an integrity check is to be the genuine article.
Sources (Google official documentation): Play Integrity API — Overview; Setup; Make a standard request; Make a classic request; About integrity verdicts; Use device recall; Handle error codes; Remediation dialogs (developer.android.com).