Skip to content

Creating Verification Queries

A verification query is a named, reusable statement of what you want a holder to present. You create one against the credential verification service, and every presentation you request names it by id.

Two names, one nesting

A verification query is ours: the object you create and address by verification_query_id. Inside it sits a DCQL queryDigital Credentials Query Language, the part of OID4VP that expresses which credentials and claims you are asking for. So the thing you create is a verification query; the thing you write inside it is a DCQL query.

Hold as many verification queries as you have distinct things to ask for. Each is created once and reused across sessions.

What is a DCQL query?

A DCQL query is a structured representation of the data the wallet should present to the verifier during the presentation protocol. In the example below it instructs the wallet to include studentId, dateOfBirth and enrollmentYear in a verifiable presentation:

DCQL query example:
{
  "credentials": [ // (1)!
    {
      "id": "studentCard", // (2)!
      "format": "jwt_vc_json-ld", // (3)!
      "meta": {}, // (4)!
      "claims": [ // (5)!
        {
          "id": "studentId", // (6)!
          "path": [ "credentialSubject", "studentId" ] // (7)!
        },
        {
          "id": "dateOfBirth",
          "path": [ "credentialSubject", "dateOfBirth" ]
        },
        {
          "id": "enrollmentYear",
          "path": [ "credentialSubject", "enrollmentYear" ]
        }
      ]
    }
  ]
}
  1. This is an array of credential queries. Each credential query specifies the type of information (claims) the wallet must present for this requested credential. A single DCQL query can contain multiple credential queries, and the wallet must present all of them in the presentation.
  2. A string that serves as an identifier for the credential query. This value is used when the wallet prepares the presentation, and therefore must not conflict with other IDs.
  3. The format of the requested credential.
  4. Optional. An object defining additional properties requested by the verifier that apply to the metadata and validity data of the credential. Only id and format are required on a credential query, so leave meta out entirely if you are not constraining anything.
  5. An array of Claim Queries specifying which claims the wallet must present.
  6. A string that serves as an identifier for the claim query. This is an optional field, but it can be useful for keeping track of claims and their values. If used, the value must not conflict with other IDs.
  7. An array of strings specifying a path to the requested claim value within a credential.

Writing the DCQL query

The overall structure of your own DCQL query must be updated and maintained. Therefore, use the example above as a guideline and starting point.

The main part of a DCQL query are the list of Claims Queries that specify the information to be requested from the wallet. Within each Claim Query object, you must define path and optionally an id (recommended). The path is an array of strings specifying a path to where the information is located within the credential.

{
    "id": "dateOfBirth",
    "path": ["credentialSubject", "dateOfBirth"]
}

Add these object blocks into the claims array in the JSON structure separated by a comma.

Creating the verification query

Register the DCQL query with the service by calling POST /verification-query/create. You can also try it from the API specification a running service serves.

The DCQL query goes inside a dcql_query field, alongside an optional uri_prefix:

curl -X 'POST' \
  '{credential_verification_service_URL}/verification-query/create' \
  -H 'Authorization: Bearer {your API key}' \
  -H 'Content-Type: application/json' \
  -d '{
  "dcql_query": {
    "credentials": [
      {
        "id": "studentCard",
        "format": "jwt_vc_json-ld",
        "claims": [
          {
            "id": "studentId",
            "path": ["credentialSubject", "studentId"]
          },
          {
            "id": "dateOfBirth",
            "path": ["credentialSubject", "dateOfBirth"]
          },
          {
            "id": "enrollmentYear",
            "path": ["credentialSubject", "enrollmentYear"]
          }
        ]
      }
    ]
  }
}'

The DCQL query is not the request body

dcql_query is required, and the credential query array goes inside it. Posting the bare { "credentials": [...] } fails.

uri_prefix is the other field this endpoint accepts, and it belongs to the verification query rather than to the DCQL query inside it. It sets the scheme of the deep link that starting a session from this query returns, and defaults to haip-vp://. Set it only to match a wallet that registers a different scheme — the issuer's equivalent is credentialOfferPrefix.

The service returns 201 - created, and the response body is the new verification query's id as plain text. Keep it: that id is what you pass as verification_query_id when you request a presentation.

You can read a verification query back with GET /verification-query/{verification_query_id}.

What's Next