Guide
How to measure an age check funnel
An age check funnel counts how far each check got: it was created, a wallet answered and an answer about age came out. The gaps between those steps show where people drop off, and the reason recorded for each refused attempt shows why. The pass rate, over the checks that have ended and against the period before, shows how the share of checks that passed has changed.
Updated
The steps every check passes
A check starts when your server creates it, and the person is then sent to a wallet to present a credential. Three counts follow it from there, and for a live check each is a subset of the one before.
A sandbox check answers without a wallet, so it reaches completed without a wallet ever answering. Read the funnel for live checks when you want to see real people and for test checks only to see your own integration.
- Created
- Every check your integration started in the period.
- A wallet answered
- A wallet sent a response and it was judged: refused, verified or held for a browser on the same device that never came back to collect it.
- Completed
- An answer about age came out: old enough or not old enough.
One more step for the EU Digital Identity Wallet
A request to the EU Digital Identity Wallet is signed and fetched by the wallet before it asks the person anything, so that path has a step the others lack: the request was fetched by a wallet. A check that was created and never fetched can mean the QR code was not scanned or the link was not opened.
A request to the EU age verification app reaches the wallet with everything already in it, through its link or the browser's Digital Credentials API, so nothing is fetched and the step does not exist there. If your checks only use the EU age verification app, this step stays at zero.
The EU Digital Identity Wallet is a separate path and it is still gated. That wallet checks who is asking before it releases anything, so it needs a relying party access certificate, which we applied for on 5 August 2026 and do not yet hold. Every relying party that wants to use that wallet has to register first and then identify itself to the wallet with such a certificate, incumbents included (Article 5b of Regulation (EU) 2024/1183 and Article 7 of Implementing Regulation (EU) 2025/848).
Where people drop off and what each gap can mean
Between created and a wallet answered, the person never got as far as a response. Either they had no wallet with a suitable credential or they left before answering. A check in this gap that runs out of time counts as no answer.
Between a wallet answered and completed, a wallet did respond but no answer about age has come out. It can be a refusal for one of the reasons below or a presentation that verified without the age claim in it. It can also be an answer held for a browser that never came back to redeem it. Checks still pending after a refused attempt sit here too and may yet complete.
The funnel shows where people stop. It counts checks rather than people, and a check carries no name or date of birth to count them by.
Why attempts are refused: the reasons
Each refused attempt is reported under one reason. The first two come from the wallet itself, and the rest are the check refusing what the wallet sent. A check can be refused more than once before it ends, so these are counts of attempts rather than checks. They can add up to more than the drop off they explain. When one attempt has several faults, the first reason in this list wins.
- No credential sent
- The wallet answered access_denied, which OpenID4VP 1.0 section 8.5 gives three meanings: it held no suitable credential, the person did not consent or it could not authenticate them. The wallet does not say which, so read it as any one of the three.
- Wallet error
- The wallet reported any other error and sent no credential.
- Credential revoked
- The credential has been revoked or suspended.
- Credential expired
- The credential has expired or is not valid yet. The person needs one that is valid today.
- Issuer not trusted
- The credential's issuer could not be confirmed as one the check trusts. A live check trusts the Commission's production list, so a test credential presented to it lands here unless an earlier reason in this list also applies.
- Did not verify
- The presentation itself failed verification: its signature, binding, disclosures, type or format.
- Other
- Anything else, such as a revocation status that could not be established.
The rates to compare
Rates are worked out over the checks that ended, so a check still pending moves none of them. The summary read returns each beside the period of equal length just before, and the console shows the change for as long as your plan still keeps that period.
Two kinds of check count in none of the three rates: one that ran out of time after a refused attempt and one that ran out with an answer still held for a browser. So the rates do not add up to the whole.
The time to result is measured from creation to completion, over completed checks only. On the same device it includes the browser coming back to collect the answer, so a slow return shows up there.
- Pass rate
- Checks old enough, divided by the checks that ended.
- Fail rate
- Checks not old enough, plus checks whose presentation verified but carried no readable answer about age, divided by the checks that ended.
- No answer rate
- Checks no wallet answered at all, divided by the checks that ended.
- Time to result
- The median and 95th percentile seconds from creation to completion.
What your plan keeps changes the numbers
Your plan keeps each check for a set time and its timeline for less. Every read returns the day from which each is whole, as retention.recordsFrom for checks and retention.eventsFrom for timelines. The console marks older days as partial.
Before the timeline day, the refusal counts, the wallet answered step and the request fetched step are partial. On those days a check whose answer was held for a browser counts as no answer. Before the check day the checks themselves are gone, so when the previous period reaches back past that day there is nothing to compare against. The console leaves the change out.
We know of no published completion rates for wallet age checks yet, so there is no benchmark to hold your pass rate against. Compare with your own previous period, while your plan still keeps it.
Where to read it
The console's Stats page draws these for live or test checks, for one project or a whole organisation. The same reads answer from code under /v1/stats: the summary on every plan, the funnel and the refusal reasons on Growth and up. On a plan without a read, the console shows what it would take to add it.
An AI assistant can read them too. The stats MCP server offers each read as a tool, get_summary, get_funnel and get_failure_breakdown among them. You can give it a key that reads stats and nothing else.
Frequently asked
What is an age check funnel?
It counts how far each age check got: created, a wallet answered and completed with an answer about age. The drop between two steps is where people stopped. It doesn't say who they were, because a check holds no name.
Why would an age check attempt be refused?
Two reasons come from the wallet: it sent no credential or reported an error. The rest are the check refusing what the wallet sent: the credential was revoked or expired or came from an issuer the check does not trust, or the presentation failed verification. Anything else is reported as other.
What is a good pass rate for a wallet age check?
We know of no published benchmark yet: wallet age checks are new and we haven't seen completion rates published for them. Compare your pass rate with your own previous period, over live checks that have ended.
Can an AI assistant read my age check funnel?
Yes, Tessio.Cloud has a read only MCP server that answers the same stats reads as the API. You can give it a key that reads stats and can't start or change a check.
Sources
Read the numbers yourself
Stats API and MCP
See your own funnel
The Stats page, the stats API and the MCP server all read the same numbers. Signup is open and a test project works as soon as you create one.