Docs · Concepts
Templates and DCQL
A template names what you are asking a wallet for. Two ship built in; anything else is a DCQL query you write once and reuse by name.
How a template resolves
template in POST /v1/verifications resolves in this
order:
- Built-ins —
age_over_18andbasic_identity. Built-ins always win: a tenant can never shadowage_over_18with a laxer query of its own, so the reserved keys mean one thing platform-wide. - Your own templates — created on the dashboard's
Templates page. The key must match
^[a-z0-9_]{1,64}$. - Neither matches →
422 unknown_template.
You can also skip templates entirely and send a query inline on the
create call. Exactly one of template and query is
required.
Built-in templates
| Key | Asks for |
|---|---|
age_over_18 | The age_over_18 attribute of the age-verification attestation eu.europa.ec.av.1, as an mdoc. |
basic_identity | Given name, family name and date of birth from the PID — requested in both mdoc and SD-JWT VC form, so a wallet holding either can satisfy it. |
{
"credentials": [
{
"id": "age_over_18_mdoc",
"format": "mso_mdoc",
"meta": { "doctype_value": "eu.europa.ec.av.1" },
"claims": [
{ "path": ["eu.europa.ec.av.1", "age_over_18"], "intent_to_retain": false }
]
}
]
}Writing your own query
A DCQL query lists the credentials you will accept and the claims you want
from each. credential_sets expresses alternatives — the query below is
satisfied by either the mdoc PID or the SD-JWT VC PID, which is how
basic_identity works:
{
"credentials": [
{
"id": "pid_mdoc",
"format": "mso_mdoc",
"meta": { "doctype_value": "eu.europa.ec.eudi.pid.1" },
"claims": [
{ "path": ["eu.europa.ec.eudi.pid.1", "given_name"], "intent_to_retain": false },
{ "path": ["eu.europa.ec.eudi.pid.1", "family_name"], "intent_to_retain": false },
{ "path": ["eu.europa.ec.eudi.pid.1", "birth_date"], "intent_to_retain": false }
]
},
{
"id": "pid_sdjwt",
"format": "dc+sd-jwt",
"meta": { "vct_values": ["urn:eudi:pid:1"] },
"claims": [
{ "path": ["given_name"] },
{ "path": ["family_name"] },
{ "path": ["birthdate"] }
]
}
],
"credential_sets": [{ "options": [["pid_mdoc"], ["pid_sdjwt"]] }]
}The query is validated when you save the template and again by the verification engine when a session is created, so an invalid query cannot reach a wallet however it got into the database.