# Server-Side VP Queries

This page explains how the Verifier Service allows you to create, retrieve, and delete Verifiable Presentation (VP) query configurations. A VP query configuration defines what credentials and fields a verifier requests from a user. These configurations live on the server side so they can be reused across multiple authorization flows.

***

## Overview

* VP query configurations are managed by the Verifier Service itself, not only by client code.
* Each configuration is stored as a JSON array of query parameters that specify which parts of a credential to request and any constraints on those values.
* Once created, a configuration is assigned a unique identifier and can be fetched or removed by its ID.
* **Optional issuer allow-list**: a configuration may also include `issuerAllowedDomains` (canonical HTTPS URLs) to restrict acceptable **issuer origins** during verification.

***

## Create VP Query Request

**Type**: `CreateVpQueryRequestDto`

### Request Body

* **`query`** (array of `VPQueryParams`, required) A non-empty array where each element defines a set of parameters for a Verifiable Presentation (VP) query. Each `VPQueryParams` element contains:
  * **`fields`** (array of `InputDescriptorField`, required) A list of descriptor fields specifying which parts of a credential to inspect and how to validate them. Each `InputDescriptorField` includes:
    * **`path`** (array of strings, required) One or more JSONPath expressions indicating where in the credential to extract a value.
    * **`filter`** (object, optional) A JSON Schema (Draft 7) that the extracted value(s) must conform to.
* **`issuerAllowedDomains`** (array of strings, optional) An **allow-list of canonical HTTPS URLs** used to restrict acceptable credential *issuers* at verification time.
  * Format: must include `https` scheme; optional `:port`; **no** query/fragment. Examples: `https://issuer.example.com`, `https://issuer.example.com:8443`, `https://issuer.example.com`
  * Normalization at runtime: host case-folded, trailing slashes trimmed, duplicates removed; **matching is by URL.origin**
  * If omitted or empty → **no issuer-domain restriction** (backward-compatible).

> Validation: each entry is checked against `HTTPS_CANONICAL_URL_REGEX`; invalid entries cause `400 Bad Request`.

**Example request body**

```json
{
  "query": [
    {
      "fields": [
        {
          "path": ["$.type"],
          "filter": { "type": "array", "contains": { "const": "IdentityCredential" } }
        }
      ]
    }
  ],
  "issuerAllowedDomains": [
    "https://issuer.example.com",
    "https://partners.example.org:8443"
  ]
}
```

***

## Controller Endpoints

All VP query–related endpoints are under the `/api/v1/verifier/vp-queries` path. Every endpoint requires a valid client‐secret bearer token for authentication.

1. **Create a VP Query Configuration**
   * **Method**: POST
   * **Path**: `/api/v1/verifier/vp-queries`
   * **Request Body**: A JSON object with:
     * `query` — non-empty array of VP query parameter sets (required)
     * `issuerAllowedDomains` — array of canonical HTTPS URLs (optional)
   * **Success Response (201 Created)**: Returns the newly created VP query configuration, including its ID, the full query array, optional `issuerAllowedDomains`, and the creation timestamp.
   * **Error Response (400 Bad Request)**: If `query` is missing/empty/invalid or any `issuerAllowedDomains` entry is not a canonical HTTPS URL.
2. **Retrieve All VP Query Configurations**
   * **Method**: GET
   * **Path**: `/api/v1/verifier/vp-queries`
   * **Success Response (200 OK)**: Returns a JSON array of all stored VP query configurations (each with its ID, query body, optional `issuerAllowedDomains`, and creation timestamp).
   * **Error Response (400 Bad Request)**: If something goes wrong with the request format.
3. **Retrieve a VP Query Configuration by ID**
   * **Method**: GET
   * **Path**: `/api/v1/verifier/vp-queries/{id}`
     * Replace `{id}` with the UUID of the configuration you want.
   * **Success Response (200 OK)**: Returns the single VP query configuration matching that ID, including `issuerAllowedDomains` if set.
   * **Error Response (400 Bad Request)**: If the provided ID is not a valid UUID.
   * **Error Response (404 Not Found)**: If no configuration exists with the given ID.
4. **Delete a VP Query Configuration by ID**
   * **Method**: DELETE
   * **Path**: `/api/v1/verifier/vp-queries/{id}`
     * Replace `{id}` with the UUID of the configuration you want to delete.
   * **Success Response (204 No Content)**: The specified configuration was successfully removed from the database.
   * **Error Response (400 Bad Request)**: If the provided ID is malformed.
   * **Error Response (404 Not Found)**: If no configuration exists with that ID.

***

## How `issuerAllowedDomains` is applied at runtime

* During VP verification, the Verifier passes the stored `issuerAllowedDomains` to its validators.
* For each VC issuer DID:
  1. The resolver extracts any advertised **LinkedDomains** (W3C DID service entries) and fetches `/.well-known/did-configuration.json` at each **origin** to validate **Domain Linkage Credentials**.
  2. The Verifier compares the **origin** set from `issuerAllowedDomains` with the issuer’s validated linked origins. If their **intersection is empty**, the VC is rejected per policy.
* Path entries in `issuerAllowedDomains` are accepted in configuration but do **not** change matching semantics (matching is by **origin** per the W3C Domain Linkage spec).

***

Because these VP queries live on the server side, you can standardize and manage them centrally rather than building the same query structure repeatedly in each client application.


---

# Agent Instructions: 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:

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

The question should be specific, self-contained, and written in natural language.
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.
