Age Verification

Start an age check

The machine to machine surface. Creates an age verification check and returns the url of its hosted verification page, to send the person to, plus a check id to poll. Rate limited (default 60/min per key). No name, date of birth, document or photo from the credential is stored: the check keeps the boolean age result with your reference. Omit the body to check age_over_18. Pass an Idempotency-Key header to make create retries safe: a repeated key returns the original check.

Creating a check does not bill. A check is charged for when a wallet has presented an attestation and we have verified it, so an abandoned, declined, timed out or unverifiable check costs nothing, and a test mode check never bills at all. What this route does check is the plan's hard ceiling, which exists to bound a runaway integration. A metered plan stops at ten times its included volume, so passing the volume itself is ordinary business, charged nothing per unit; an unmetered plan stops at the bound it reports as both limits.

post/v1/age-checks

Request

  • Base URL: https://api.tessio.eu
  • URL: https://api.tessio.eu/v1/age-checks
  • Auth: HTTP bearer

Headers

Idempotency-Keystring

Unique per project; a retry with the same key returns the original check (nothing is created or metered again). Kept for 24 hours, after which a retry carrying it creates and meters a new check.

Request body

minAgeinteger

Age threshold to verify. 18 is the only value guaranteed to work: the EU age verification attestation makes age_over_18 mandatory at issuance and leaves every other age_over_NN optional, so which further thresholds a holder can answer depends on who issued their credential. Any threshold from 1 to 99 is accepted (the ISO 18013-5 claim is age_over_NN, two digits); one the credential does not carry returns a check with status "failed" and a null meetsMinAge, rather than a guess. The sandbox only ever demonstrates 18.

referencestring

Your correlation id, stored as you send it and returned with the check. Keep it opaque: do not put a name or other personal detail in it. Control characters are refused, including tab, carriage return and newline: the CSV export prints this column, and a newline in it would split one record into two. Printable characters are all accepted, so an id beginning with =, +, - or @ is fine; the export guards those itself.

credential'proof-of-age' | 'pid-mdoc' | 'pid-sdjwt' | 'pid-de-sdjwt' | 'photo-id'

Which credential the person is asked to present. Omit it for this deployment's default, which is what every check asked for before this field existed. A deployment offers its default plus any credentials it is configured to offer: naming one it does not offer is refused with credential_not_offered, and a name not in this list with unknown_credential. The names are proof-of-age (the EU age verification attestation), pid-mdoc and pid-sdjwt (the EU PID in its two encodings), pid-de-sdjwt (the German PID) and photo-id (the ISO Photo ID). Each check records what it asked for and is judged by that alone.

Response

Check created (poll the returned id)

idstring uuid
urlstring uri

The hosted verification page for this check: send the person here. Not a wallet deeplink. The page picks a transport for the browser and device in front of it, so a new transport reaches every integration without any of them changing.

status'pending'
expiresAtstring date-time
mode'test' | 'live'

The mode of the project that created this check, fixed when the project was created. test is a sandbox: the check completes on its own after a couple of seconds and its result is simulated, so meetsMinAge proves nothing about anyone. live means only a wallet presentation completes the check. Read this before acting on meetsMinAge.

Changes

No recorded changes to this operation across all 1 revision of this API.