For most of the last decade, the age question lived entirely inside your application. You asked for a birthday, uploaded a document, ran a selfie check, or — most of the time — trusted a checkbox. In 2026 that changed at the platform layer. Both app stores now hand you an age signal directly from the operating system, gated by jurisdiction, and they did it on a rolling, state-by-state schedule that is easy to misread as “the stores solved age verification for us.”
They did not. What Google and Apple shipped is genuinely useful and worth integrating. But it is a signal — a coverage-limited, assurance-opaque input — not a system of record. If you treat the store response as your compliance answer, you will discover the gap at the worst possible time: when a regulator asks you to demonstrate effectiveness, when a user lands in a jurisdiction the store doesn’t cover, or when the only artefact you kept is a boolean someone else computed.
This piece is the hands-on counterpart to our earlier strategic overview of device-level age verification. Here we get concrete: what the Play Age Signals API and Apple’s Declared Age Range API actually return as of mid-2026, where the response is empty, and the integration pattern that uses them correctly — as a fast path into your own age layer, not a replacement for it.
What Actually Shipped in 2026
The rollout was driven by law, not product strategy, which is why it arrived piecemeal. Google’s Play Age Signals API (still beta) started returning real data for users in Brazil on March 17, 2026 under the Digital ECA, then for Texas users who created their accounts after May 28, 2026 to support Texas SB 2420, with Utah and Louisiana sequenced behind them. Apple updated its Declared Age Range API for beta testing on February 24, 2026, simultaneously beginning to block 18+ app downloads in Australia, Brazil, and Singapore, and switched on developer-facing age categories for new Utah accounts on May 6 and Louisiana accounts on July 1, 2026.
Two things matter about that pattern. First, both APIs only return age data where a law in that user’s region compels the platform to provide it. Outside those jurisdictions — and for any user who opts not to share their age — the API returns null. Second, the schedule is ongoing: every new state law adds another region to the matrix, on its own date, sometimes with its own age bands. You are not integrating a feature once; you are subscribing to a moving compliance surface. This is the same per-jurisdiction fragmentation that makes the US age-verification patchwork so expensive to track manually.
What Play Age Signals Actually Returns
Strip away the framing and the Play Age Signals API is a client-side call that returns four fields: a userStatus, an age range (ageLower/ageUpper), a mostRecentApprovalDate for supervised accounts, and an installID. The field that carries the weight is userStatus, and its possible values are more revealing than most integration guides admit:
VERIFIED— Google verified the user’s age “using a commercially reasonable method such as a government-issued ID, credit card, or facial age estimation.” Note what this collapses: three methods with wildly different assurance levels, reported to you as one flat value. You cannot see which method was used, and you cannot tune the threshold.DECLARED— the age was declared by the user or their parent. This is self-declaration with a coat of paint.SUPERVISED,SUPERVISED_APPROVAL_PENDING,SUPERVISED_APPROVAL_DENIED— the user has a parent-managed Google account (Family Link), with a parental-approval state attached.UNKNOWN— the user is in an applicable jurisdiction but Play has no age for them; you’re told to send them to the Play Store to resolve it.null— the user is not in a covered jurisdiction, or has chosen not to share their age with apps. You cannot distinguish these two cases from the response.
The default age bands are 0-12, 13-15, 16-17, and 18+. You can override them with up to three custom minimum ages in the Play Console — but they must be at least two years apart and you can change them only once per year, which is a meaningful constraint if your thresholds shift with regulation. A minimal Kotlin integration looks like this:
val ageSignalsManager =
AgeSignalsManagerFactory.create(applicationContext)
ageSignalsManager
.checkAgeSignals(AgeSignalsRequest.builder().build())
.addOnSuccessListener { result ->
when (result.userStatus()) {
AgeSignalsVerificationStatus.SUPERVISED_APPROVAL_DENIED ->
blockAccess()
AgeSignalsVerificationStatus.VERIFIED ->
gateOn(result.ageLower(), result.ageUpper())
else ->
// DECLARED, UNKNOWN, null, SUPERVISED_APPROVAL_PENDING...
fallThroughToYourOwnAgeLayer()
}
}
That else branch is the whole point of this article. In Brazil today, userStatus can only ever be DECLARED, UNKNOWN, or null — VERIFIED is not even on the table. Across every market, a large share of real sessions land in the else. A few more details engineers should plan for: the API is supported only on Android 6.0+ via Google Play, returns APP_NOT_OWNED if your app wasn’t installed through Play (sideloaded and alternative-store installs get nothing), caches an updated age band only 2–8 weeks after a user’s birthday, and should be paired with the Play Integrity API because a client-side signal is otherwise trivially spoofable. The terms also restrict you to using the signal for age-appropriate experiences and compliance — not advertising, profiling, or analytics.
Apple’s Mirror: Declared Age Range
Apple’s Declared Age Range API solves the same problem with the same shape. It returns an age range rather than a date of birth, plus — usefully — a signal about the method of age assurance and whether regulatory requirements apply to the user. As Biometric Update reported, Apple positioned it explicitly for national and state-level age-assurance laws, with the same jurisdiction-gated rollout: Australia, Brazil, and Singapore from February 24, Utah from May 6, Louisiana from July 1.
The strategic reality is that you now have two platform age APIs with different field names, different enums, different jurisdiction schedules, and different parental-control models — and neither covers the web, desktop, consoles, smart TVs, or any context outside its own store. If your product touches more than one surface, the store signals are not a solution; they are two of N inputs you have to normalize.
The Four Limits That Make a Store Signal Not a Strategy
Here is the part that doesn’t make it into the integration tutorials.
1. Coverage is full of holes — by design. The APIs return data only where the platform is legally compelled to, only for store-distributed apps, only on supported OS versions, and only when the user agrees to share. Every other session — a different jurisdiction, an opted-out user, a sideloaded install, your web app, your Roku app — comes back null or UNKNOWN. You cannot run a compliance program on a control that is silent for a large, unpredictable fraction of your users. You will need a fallback path regardless, which means you are building your own age layer anyway; the only question is whether it’s a coherent system or a pile of else branches.
2. The assurance is opaque and uncontrollable. A VERIFIED from Google can mean a facial-age estimate, a credit-card check, or a scanned passport — methods that differ by an order of magnitude in reliability, and one of which (a credit card) is not proof of age at all. You can’t see which fired, can’t set the confidence bar, and can’t apply a buffer zone near your threshold. And DECLARED is self-declaration — which UK regulators, in the joint ICO/Ofcom position, have stated outright is not “highly effective.” Accepting DECLARED as a pass is accepting a method a regulator has already rejected.
3. A signal is not evidence. This is the failure mode we covered in the second-fine analysis: regulators increasingly punish the inability to demonstrate age assurance separately from the absence of it. When Ofcom or a state attorney general asks you to show your working — which method, what it concluded, how it performs at the threshold, what happens to users who fail — “the Play Store returned VERIFIED” is not an answer you own. You kept the outcome and threw away the proof, and the proof lived on someone else’s infrastructure to begin with.
4. You inherit a maintenance matrix, not a control. Two APIs, divergent enums, per-state activation dates, once-a-year custom-band changes, version pinning, integrity attestation, error-and-retry handling, and a null-disambiguation problem you can’t actually solve. Each new state law is another cell in the grid. None of that work produces a single, auditable record of your age decision — it produces glue code around two black boxes.
The Pattern That Actually Works
Use the store signals for exactly what they’re good at, and no more: a fast, free, low-friction first input that lets a large share of already-known users through without re-verifying. Then fall through to an age layer you own for everything the store can’t answer. Concretely:
| Store response | What it really means | Correct handling |
|---|---|---|
VERIFIED + clear age band |
Strong-ish, method unknown | Accept as fast path; log that the decision came from the store, not from you |
DECLARED |
Self-declaration | Treat as unverified near a real threshold; step up |
SUPERVISED states |
Parental control present | Honour the parental state; verify the account holder for adult thresholds |
UNKNOWN / null |
No coverage or opted out | Run your own age check — this is most of the long tail |
| Near your threshold | Band edge, any status | Step up to stronger evidence |
The decision and its evidence have to live in your system, not the store’s. That means: a method you can name and tune, a buffer zone around the threshold so users near the line get stronger checks while the clear majority pass cheaply, an exportable record of what was verified and when, and a result that’s portable across every surface the store APIs don’t reach. Do this and the store signal becomes a conversion optimization — it reduces friction for known-adult users — rather than a compliance dependency you can’t defend.
How Xident Fits
Xident is the age layer you own underneath the store signals — built so that the else branch is a coherent system instead of a liability. We sit behind your app on every surface (iOS, Android, web, desktop, console), normalize whatever the platform hands you, and make the actual age decision ourselves so it’s the same defensible result whether the user came in VERIFIED, DECLARED, or null.
For the long tail the stores can’t cover, most users clear the threshold with privacy-preserving facial age estimation that returns an age band, not an identity, and runs on the device so no face image touches your servers. Only users near the line get escalated to a document or NFC check, so friction lands where it’s actuarially warranted instead of taxing everyone. We classify across bands (+12, +15, +18, +21, +25) rather than a single binary, so one integration serves a 13+ access rule and an 18+ content gate. Critically, we retain the decision — an auditable, exportable record of method, result, and timestamp — which is the evidence an Ofcom information request or a state AG actually asks for, and which a store enum can never give you. And because the output is a reusable, bound credential, a user verifies once and proves it anywhere, so adding a real fallback doesn’t crater conversion the way a hard wall would.
If you’re scoping how to combine platform age signals with a verification layer you control, our vendor security checklist lays out the questions that separate a check you can defend from one that just clears a demo.
The Honest Take
The store APIs are a real improvement. For a known, in-jurisdiction, store-distributed user who shares their age, getting a VERIFIED band for free is a better experience than a document upload, and you should take it. The mistake is reading “the OS gives me an age signal now” as “I no longer need an age-verification capability.” The opposite is true: the store signal is silent for too many users, opaque about its own method, and useless as evidence — which means the moment you integrate it seriously, you also have to build the layer that answers for everyone and everything it doesn’t cover.
Treat Google and Apple’s age signals as the fast path, not the foundation. Own the decision, keep the evidence, and make it portable across every surface a store API will never see. That’s the difference between an age signal and an age strategy.
If you operate a platform that needs an age layer that works with the store signals and beyond them, start here.