---
id: dcql-2-4-7-delivery-service-restricted-postal-codes
title: "DCQL: Values Constraint"
hide_title: false
description: DCQL values constraint for restricting accepted claim values to a predefined allowed list.
keywords: [DCQL, values constraint, allowed values, credential query, OpenID4VP, EUDI Wallet, claim validation, verifiable credentials]
sidebar_label: Values Constraint
slug: /dcql-2-4-7-delivery-service-restricted-postal-codes/
---

> **Build this with an AI coding agent.** Install the iGrant.io Agent Skills, then ask your agent to build the integration:
>
> ```bash
> npx skills add L3-iGrant/skills
> ```
>
> This page maps to the `igrantio-dcql-postal-codes` skill. Install just that one with:
>
> ```bash
> npx skills add L3-iGrant/skills -s igrantio-dcql-postal-codes
> ```


import Link from "@docusaurus/Link";
import { ApiKeyManager } from "@site/src/components/ApiKeyManager";
import DcqlStepTemplate from "@site/src/components/DCQL/DcqlStepTemplate";

The DCQL `values` constraint restricts accepted claim values to a predefined allowed list, enabling a verifier to enforce eligibility criteria directly in the query.

**Scenario:** A delivery service requests a PID credential (in `dc+sd-jwt` format) containing the holder's residential address, accepting only postal codes from an allowed list.

For the underlying DCQL query, diagram and example, see the **“Delivery service restricted to specific postal codes”** use case in our [DCQL concepts article](/concepts/eudi-wallet-dcql-openid4vp-business-wallet-payments/#247-use-case-delivery-service-restricted-to-specific-postal-codes).

![Fig 07: Require a PID and an address credential with a postal code matching 43242 or 43243 for eligibility.](../cDocs/articles/dcql-images/fig-07-dcql-eudi-wallet-address-postal-code-eligibility.png)

## Step 1: Get the API Key (Issuer Admin)

To obtain your API key, please contact [support@igrant.io](mailto:support@igrant.io?subject=Request%20API%20Key). Once you have received your API key, enter it in the field below and click the **Set API Key** button to save it for future use.

<ApiKeyManager />

## Step 2: Create Credential Definition (Issuer Admin)

To create a credential definition, run the JSON body using the **Run** button. Alternatively, you can manually copy the JSON and use it in the body of the API request available [here](/docs/openid4vc-api/config-create-digital-wallet-open-id-credential-definition).

> Note: The `kid` value is mandatory with trust anchor `x509`. To obtain the `kid` value for the respective organisation use the API available [here](/docs/openid4vc-api/config-read-digital-wallet-open-id-organisation-identifier).

From the API response, copy the `credentialDefinitionId` and `id` value from the `credentialDefinitions` array for use in the Step 3.

The issuer can define credential definition for the `PID` of credential format `dc+sd-jwt`

<DcqlStepTemplate
  endpointPath="/v2/config/digital-wallet/openid/sdjwt/credential-definition"
  method="POST"
  initialJsonData={`{
  "label": "Person Identification Data",
  "trustAnchor": "x509",
  "kid": "<kid>",
  "credentialDefinitions": [
    {
      "credentialFormat": "dc+sd-jwt",
      "vct": "urn:eu.europa.ec.eudi:pid:1",
      "claims": {
        "claims": [
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "residential_address",
              "street_address"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "residential_address",
              "postal_code"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "residential_address",
              "locality"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "residential_address",
              "country"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "birthdate"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "email"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "family_name"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "given_name"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "is_over_18"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "is_over_21"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "is_over_65"
            ]
          },
          {
            "limitDisclosure": true,
            "mandatory": true,
            "path": [
              "phone_number"
            ]
          }
        ]
      },
      "display": {
        "name": "Person Identification Data",
        "description": "Proof of identity and address"
      }
    }
  ]
}`}
/>

## Step 3: Issue and Receive Credential (Issuer/Holder)

The holder of the wallet submits a request for the issuance of a credential by executing the JSON code block below using the **Run** button in `InTime` issuance mode. Choose the credential format and replace `<credentialDefinitionId>` and `<id>` with the actual values obtained from the previous step. Alternatively, you may use the API available [here](/docs/openid4vc-api/config-digital-wallet-open-id-issue-credential).

After receiving the response, toggle the button provided to dynamically generate a QR code. The EUDI Wallet/Holder can then accept the credential offer using the [Data Wallet](https://www.igrant.io/datawallet.html) (or any other EU Digital Identity Wallet) by either scanning the QR code or directly accessing the credential offer on their mobile device, such as via a browser.

### PID

Person Identification Data (PID) is a standardised European identity credential defined under the [EU Digital Identity Framework (eIDAS 2.0)](https://digital-strategy.ec.europa.eu/en/policies/eudi-regulation). It contains essential personal information including family name, given name, date of birth and address, enabling secure digital identification across EU member states.

<DcqlStepTemplate
  endpointPath="/v2/config/digital-wallet/openid/sdjwt/credential/issue"
  method="POST"
  extractQrValue={(result) => result?.credentialHistory?.credentialOffer || ""}
  initialJsonData={`{
  "issuanceMode": "InTime",
  "credentialDefinitionId": "<credentialDefinitionId>",
  "urlScheme": "openid-credential-offer://",
  "credentials": [
    {
      "id": "<id>",
      "claims": {
        "residential_address": {
          "country": "Sweden",
          "locality": "Stockholm",
          "region": "Stockholms län",
          "street_address": "Sveavägen 44",
          "postal_code": "11134"
        },
        "birthdate": "1990-04-15",
        "email": "alice.andersson@example.se",
        "family_name": "Andersson",
        "given_name": "Alice",
        "is_over_18": true,
        "is_over_21": true,
        "is_over_65": false,
        "phone_number": "+46 70 123 45 67"
      }
    }
  ],
  "userPin": ""
}`}
/>

After receiving the response, toggle the button provided to dynamically generate a QR code. The EUDI Wallet/Holder can then accept the credential offer using the [Data Wallet](https://www.igrant.io/datawallet.html) (or any other EU Digital Identity Wallet) by either scanning the QR code or directly accessing the credential offer on their mobile device, such as via a browser.

## Step 4: Create Presentation Definition (Verifier Admin)

To create a presentation definition for requesting proof, you can run the code block below using the **Run** button. Alternatively, you can manually copy the code block and use it in the body of the API request provided [here](/docs/openid4vc-api/config-digital-wallet-open-id-presentation-definition).

In this use case, the verifier expresses a requirement for a residential address credential where the postal code is in an allowed list of delivery zones.

<DcqlStepTemplate
  endpointPath="/v2/config/digital-wallet/openid/sdjwt/presentation-definition"
  method="POST"
  initialJsonData={`{
  "label": "Delivery service restricted to specific postal codes",
  "trustAnchor": "x509",
  "kid": "<kid>",
  "dcqlQuery": {
    "credentials": [
      {
        "id": "residential_address",
        "format": "dc+sd-jwt",
        "meta": {
          "vct_values": [
            "urn:eu.europa.ec.eudi:pid:1"
          ]
        },
        "display": {
          "name": "Person Identification Data",
          "description": "PID credential with residential address and contact details"
        },
        "claims": [
        {
          "id": "full_address",
          "path": [
            "residential_address",
            "street_address"
          ]
        },
        {
          "id": "postal_code",
          "path": [
            "residential_address",
            "postal_code"
          ],
          "values": [
            "11134",
            "41103"
          ]
        },
        {
          "id": "city",
          "path": [
            "residential_address",
            "locality"
          ]
        },
        {
          "id": "country",
          "path": [
            "residential_address",
            "country"
          ]
        }
      ],
        "claim_sets": [
          [
            "full_address",
            "postal_code",
            "city",
            "country"
          ]
        ]
      }
    ]
  }
}`}
/>

Once a presentation definition is created, the `presentationDefinitionId` can be reused to verify multiple credentials in Step 5.

## Step 5: Create Verification Request (Verifier/Relying Party)

To create the verification request, execute the code block below using the **Run** button. Alternatively, you can manually copy the JSON and use it in the body of the API available [here](/docs/openid4vc-api/config-create-digital-wallet-open-id-verification-request-v-3).

After receiving the response, toggle the button provided to dynamically generate a QR code. The EUDI Wallet/Holder can then accept the verification request using the Data Wallet (or any other EU Digital Identity Wallet) by either scanning the QR code or directly accessing the verification request on their mobile device, such as via a browser.

<DcqlStepTemplate
  endpointPath="/v3/config/digital-wallet/openid/sdjwt/verification/send"
  method="POST"
  extractQrValue={(result) => result?.verificationHistory?.vpTokenQrCode || ""}
  initialJsonData={`{
  "requestByReference": true,
  "presentationDefinitionId": "<presentationDefinitionId>"
}`}
/>

Users can copy the `presentationExchangeId` from the JSON response for use in Step 8 to read verification history.

## Step 6: Send and Receive Verifiable Presentation (Holder)

The holder wallet accepts (consents) to send the requested credentials.

- **Receive Verification:**
  - Use the `vpTokenQrCode`(step 5) with the API available [here](/docs/openid4vc-api/config-receive-digital-wallet-open-id-verification-v-3/) to receive the verification.
  - Copy the `presentationId` from the JSON response received from **Receive Verification** for use in Step 6b.
- **Filter Verification:**
  - Use that `presentationId` with the API available [here](/docs/openid4vc-api/config-filter-digital-wallet-open-id-verification) to find matching credentials.
  - Save the `<id>` and `<credentialId>` from the response.
- **Send Verification:**
  - Use the `presentationId`, `<id>` and `<credentialId>` with the API available [here](/docs/openid4vc-api/config-send-digital-wallet-open-id-verification-presentation-v-3) to send the credentials to the verifier.

## Step 7: Send and Receive Verifiable Presentation (Verifier/Relying Party)

- The Verfier (Relying Party) receives the requested credentials and can verify it. They may read the received credential by executing the [Read Verification History API](/docs/openid4vc-api/config-read-digital-wallet-open-id-verification-history-v-3).
- From the response received, the `vpTokenResponse` can be decoded using [JWT Decoder](/docs/devtools-jwt-decoder/).
- From the decoded response, the `verifiableCredential` inside the 'vp' can be further decoded to view the received credentials.
