> For the complete documentation index, see [llms.txt](https://docs.empe.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.empe.io/develop/verifier/server-side-vp-query.md).

# Server-Side VP Queries

This page explains how the Verifier expresses *what* it wants a holder to present. Every authorization request carries its credential query **inline**: you build a **DCQL query** or a **Presentation Exchange v2 definition** in your application code and send it in the request body when you create the authorization request. Queries live in your codebase, so there are no server-side query records to create, fetch, or delete.

***

## Overview

* A verifier asks for credentials by creating an **authorization request** (an OpenID4VP request). The query that describes the acceptable credentials and fields lives **inside that request body**.
* You supply the query in one of two ways:
  * **`dcqlQuery`** — a Digital Credentials Query Language (DCQL) query, or
  * **`presentationDefinition`** — a DIF Presentation Exchange v2 definition.
* Supply exactly one of the two. If neither is supplied, the request fails with `400 Bad Request` and the message `Either dcqlQuery or presentationDefinition must be provided.` Sending both passes the service's own input validation but fails downstream for every `version` value, surfacing as a `500` (see [Query Language](/develop/verifier/query-language.md)).
* Because queries are inline, you standardize them in your own application code and pass the built object on each request, rather than registering reusable query records on the server.

***

## Authorization Request Endpoints

These endpoints live under the **`/verifiers/{verifierId}/authorization-requests`** path. The `verifierId` is the identifier of a registered verifier; it may be a DID. Every endpoint requires a valid **OIDC JWT Bearer token** (`Authorization: Bearer <token>`; see [Authentication](/develop/verifier/authentication.md)).

### Create an Authorization Request

**`POST /verifiers/{verifierId}/authorization-requests`**

Creates an OpenID4VP authorization request and a verification session.

#### Request Body

* **`dcqlQuery`** (object, optional) A DCQL query describing the requested credential configurations. **Required if `presentationDefinition` is not provided.**
* **`presentationDefinition`** (object, optional) A DIF Presentation Exchange v2 definition. **Required if `dcqlQuery` is not provided.** Can only be used with `version` `v1.draft21` or `v1.draft24`.
* **`responseMode`** (string, optional) How the holder returns the presentation. One of `direct_post`, `direct_post.jwt`, `dc_api`, `dc_api.jwt`. Defaults to `direct_post.jwt`.
* **`version`** (string, optional) The OpenID4VP draft to use. One of `v1`, `v1.draft21`, `v1.draft24`. Defaults to `v1`, which supports only `dcqlQuery` — use `v1.draft21` or `v1.draft24` with `presentationDefinition`. Note that `dcqlQuery` cannot be combined with `v1.draft21`.
* **`signingDid`** (string, optional) The DID that signs the authorization request. If omitted, the `verifierId` path parameter must itself be a DID; otherwise the request fails with `400 Bad Request`.
* **`authorizationResponseRedirectUri`** (string, optional) Redirect URI to include in the authorization response.
* **`expectedOrigins`** (array of strings, optional) Expected origins for Digital Credentials API flows (used with the `dc_api` response modes).
* **`transactionData`** (array of objects, optional) Transaction data entries to bind into the request.
* **`verifierInfo`** (array of objects, optional) Verifier attestations to include in the request.

#### Response Body

A success response returns the request details:

* **`authorizationRequestUri`** — an `openid4vp://...` URI the wallet opens to fulfill the request.
* **`verificationSessionId`** — the session identifier used to track and observe the verification.
* **`authorizationRequestId`** — present for hosted requests.
* **`expiresAt`** — ISO timestamp when the request expires.

**Example request body (DCQL)**

```json
{
  "dcqlQuery": {
    "credentials": [
      {
        "id": "employee-badge",
        "format": "dc+sd-jwt",
        "meta": { "vct_values": ["https://issuer.example.com/vct/employee-badge"] },
        "claims": [
          { "path": ["employee_id"] },
          { "path": ["full_name"] },
          { "path": ["department"] }
        ]
      }
    ]
  },
  "responseMode": "direct_post.jwt",
  "version": "v1"
}
```

**Example request body (Presentation Exchange v2)**

```json
{
  "presentationDefinition": {
    "id": "employee-badge-check",
    "input_descriptors": [
      {
        "id": "employee-badge",
        "constraints": {
          "fields": [
            {
              "path": ["$.vct"],
              "filter": { "type": "string", "const": "https://issuer.example.com/vct/employee-badge" }
            },
            { "path": ["$.department"] }
          ]
        }
      }
    ]
  },
  "version": "v1.draft24"
}
```

The `version` field is required here: `presentationDefinition` works only with `v1.draft21` or `v1.draft24`.

**Example response**

```json
{
  "authorizationRequestUri": "openid4vp://?request_uri=...",
  "verificationSessionId": "18b760b1-4ab8-4d38-9d42-6b4c25a4d2e0",
  "authorizationRequestId": "1b8a6a8b-2ac1-4f0b-9d9c-6b9c859b1af2",
  "expiresAt": "2026-06-22T12:34:56.789Z"
}
```

### Create an Authorization Request as a QR Code

**`POST /verifiers/{verifierId}/authorization-requests/qr-code`**

Takes the **same request body** as above, but returns a **PNG image** of a QR code encoding the `authorizationRequestUri`. This is convenient for cross-device flows where a holder scans the code with a wallet.

The request URI and session identifiers are returned in response headers:

* **`X-Authorization-Request-Uri`** — the `openid4vp://...` URI.
* **`X-Verification-Session-Id`** — the verification session identifier.
* **`X-Authorization-Request-Id`** — present for hosted requests.

***

## Observing the Result

After a request is created, track its progress through the verification session endpoints:

* **`GET /verification-sessions/{sessionId}`** — read the current session state (for example `RequestCreated`, and later states as the holder responds).
* **`GET /verification-sessions/{sessionId}/events`** — a **Server-Sent Events (SSE)** stream that emits a `session` event whenever the session updates, plus a `ping` heartbeat every 15 seconds.

Both endpoints require a valid Bearer token.

***

## DCQL vs Presentation Exchange

Both query languages let you target specific credential types and constrain individual claims; pick whichever fits your stack.

* **DCQL** is the newer, compact query model. It describes requested credentials by format and metadata (such as the SD-JWT `vct`) and lists the claim paths you need.
* **Presentation Exchange v2** uses input descriptors with JSONPath `path` expressions and JSON Schema (Draft 7) `filter` rules to validate the value at each path. See the [Query Language](/develop/verifier/query-language.md) page for more on paths and filters.

The Verifier accepts either form and uses it to match credentials the holder presents. In a DCQL query, request an SD-JWT VC with the `dc+sd-jwt` format value (the [DIF Claim Format Registry](https://identity.foundation/claim-format-registry/) identifier the Verifier uses for SD-JWT credentials).

***

## Notes

* Authentication is an OIDC JWT Bearer token; these endpoints require a valid token but no specific role (see [Authentication](/develop/verifier/authentication.md)).
* Queries are not persisted as reusable, ID-addressable configurations. Keep your query objects in your own codebase and pass them inline on each request so you can standardize them across flows.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.empe.io/develop/verifier/server-side-vp-query.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
