Docs
Verification

DCQL Queries

Digital Credentials Query Language, for specifying exactly which credentials and claims you need

DCQL (Digital Credentials Query Language) is the query format used in OID4VP v1. It lets you specify which credentials, claims, and trust constraints the wallet must satisfy.

Basic structure

{
  "credentials": [
    {
      "id": "unique_id",
      "format": "mso_mdoc",
      "meta": { "doctype_value": "..." },
      "claims": [
        { "path": ["namespace", "attribute"] }
      ]
    }
  ]
}

Credential query

Each credential entry describes one type of credential you'll accept:

FieldTypeRequiredDescription
idstringYesUnique identifier for this credential query
format"mso_mdoc" | "dc+sd-jwt"YesCredential format
metaobjectNoFormat-specific metadata
claimsarrayNoSpecific claims to request
trusted_authoritiesarrayNoTrust constraints (see Trusted Authorities)

mDoc metadata

For mso_mdoc format:

{
  "meta": {
    "doctype_value": "eu.europa.ec.eudi.pid.1"
  }
}

SD-JWT metadata

For dc+sd-jwt format:

{
  "meta": {
    "vct_values": ["eu.europa.ec.eudi.pid.1"]
  }
}

Claims

Claims specify which attributes to request. The path format differs by credential format.

mDoc claims

For mDoc credentials, the path is [namespace, attribute]:

{
  "claims": [
    { "path": ["eu.europa.ec.eudi.pid.1", "family_name"] },
    { "path": ["eu.europa.ec.eudi.pid.1", "given_name"] },
    { "path": ["eu.europa.ec.eudi.pid.1", "age_over_18"] }
  ]
}

SD-JWT claims

For SD-JWT credentials, the path is [attribute]:

{
  "claims": [
    { "path": ["family_name"] },
    { "path": ["given_name"] },
    { "path": ["age_over_18"] }
  ]
}

Claim options

FieldTypeDescription
pathstring[]Attribute path
valuesany[]Acceptable values (the claim must match one)
intent_to_retainbooleanSignal that you intend to store this claim

Value constraints

Request only credentials where age_over_18 is true:

{
  "path": ["eu.europa.ec.eudi.pid.1", "age_over_18"],
  "values": [true]
}

Credential sets

When you accept multiple credential types, use credential_sets to define the logic:

{
  "credentials": [
    { "id": "pid_mdoc", "format": "mso_mdoc", "meta": { "doctype_value": "eu.europa.ec.eudi.pid.1" } },
    { "id": "pid_sdjwt", "format": "dc+sd-jwt", "meta": { "vct_values": ["eu.europa.ec.eudi.pid.1"] } }
  ],
  "credential_sets": [
    {
      "options": [["pid_mdoc"], ["pid_sdjwt"]],
      "required": true
    }
  ]
}

This tells the wallet: "I need a PID: either mDoc or SD-JWT format is fine."

Complete example

{
  "credentials": [
    {
      "id": "pid",
      "format": "mso_mdoc",
      "meta": { "doctype_value": "eu.europa.ec.eudi.pid.1" },
      "claims": [
        { "path": ["eu.europa.ec.eudi.pid.1", "family_name"] },
        { "path": ["eu.europa.ec.eudi.pid.1", "given_name"] },
        { "path": ["eu.europa.ec.eudi.pid.1", "birth_date"] },
        {
          "path": ["eu.europa.ec.eudi.pid.1", "age_over_18"],
          "values": [true],
          "intent_to_retain": false
        }
      ],
      "trusted_authorities": [
        { "type": "aki", "values": ["MIGfMA0GCSqGSIb3DQEBAQUAA4GN"] }
      ]
    }
  ]
}