Verifying SD-JWT VC credentials via OID4VP

This guide shows you how to verify SD-JWT VC credentials using the Enterprise Verifier2 Service via OID4VP (OpenID for Verifiable Presentations).

SD-JWT VCs: Credentials based on the IETF SD-JWT VC standard which support selective disclosure, allowing users to share only specific claims from their credentials.

OID4VP: A protocol specifying how parties can present VCs in a way that's consistent and secure across platforms ensuring interoperability.

Prerequisites

Before you begin, ensure you have:

  • Enterprise Verifier2 Service setup — Follow the Setup guide
  • Valid authentication token — Required for all API calls to the Enterprise Stack
  • A test wallet with credentials — Use the walt.id Wallet for testing, or any OID4VP-compatible wallet

Enterprise Architecture: The Enterprise Verifier2 Service runs as a dedicated microservice within your organization's infrastructure. All requests are scoped to {organizationID}.{tenantID}.{verifierServiceID} for multi-tenancy isolation.


Example 1: Basic Verification

This example requests an SD-JWT identity credential and verifies its signature.

CURL

Endpoint: POST /v1/{target}/verifier2-service-api/verification-session/create | API Reference

Example Request
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier2-service-api/verification-session/create' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "flow_type": "cross_device",
  "core_flow": {
    "dcql_query": {
      "credentials": [
        {
          "id": "credential_1",
          "format": "dc+sd-jwt",
          "meta": {
            "vct_values": [
              "https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.issuer/issuer-service-api/openid4vc/draft13/identity_credential"
            ]
          }
        }
      ]
    }
  }
}'

Path Parameters

  • orgID: String (required) - Your organization ID. When performing operations within an organization, use the organization's Base URL. For example, if your organization is named test, your default Base URL will be test.enterprise-sandbox.waltid.dev when using the sandbox environment.
  • target: String (required) - The resource identifier indicating the organization + tenant + verifier service ({organizationID}.{tenantID}.{verifierServiceID}). Example: waltid.tenant1.verifier1

Header Parameters

  • Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format: Bearer {token}.

Body Parameters

  • flow_type: String (required) - Specifies how the credential request will be delivered to the holder's wallet. Options:
    • "cross_device" — User scans a QR code on a different device (e.g. desktop browser → phone wallet)
    • "same_device" — User clicks a deep link on the same device (e.g. phone browser → wallet app on same phone)
    • "dc_api" — Browser/OS-native Digital Credentials API (Chrome, Safari, iOS/Android native) over OpenID4VP 1.0 (Annex D).
    • "dc_api-annex-c" — Browser/OS-native Digital Credentials API (Chrome, Safari, iOS/Android native) over 18013-7 (Annex C).
  • core_flow: Object (required) - Defines what credentials to request and which policies to apply. Contains:
    • dcql_query: Object (required) - Specifies the credential type, format, and claims to request using the DCQL query language. You can also use the DCQL builder here.
      • credentials: Array - List of credential queries. Each credential query contains:
        • id: String - Unique identifier for this credential in the request (used in policy results)
        • format: String - Credential format. For SD-JWT VCs, use "dc+sd-jwt".
        • meta.vct_values: Array - List of credential types. Example: ["https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.issuer/issuer-service-api/openid4vc/draft13/identity_credential"].
        • claims: Array (optional) - Specific claims to request from the credential. Each claim has a path (JSON path to the claim). If omitted, all claims that are non-selectively disclosable are provided by the wallet.
    • policies: Object (optional) - Validation rules applied to the received credential. Defaults to signature verification only if omitted.
      • vc_policies: Array - Policies applied to individual credentials. Each policy has a policy field specifying the policy name. Available policies: signature, expired, not-before, revoked-status-list, schema, and more. See Policies for the complete list.
      • vp_policies: Array (optional) - Policies applied to the entire presentation
    • signedRequest: Boolean (optional) - Whether to sign the authorization request JWT. Required for HAIP profile compliance and DC API Annex C (ISO 18013-7) flows. Defaults to false. See Signed Requests to learn more.
    • encryptedResponse: Boolean (optional) - Whether the wallet should encrypt the VP token response. Defaults to false. See Encrypted Responses to learn more.
    • key: Object (optional) - Signing key for this verification session. Overrides the service-wide default key configured during verifier2 service creation. Must be a serialized key in the format {"type":"jwk","jwk":{...}}. Required when signedRequest: true or encryptedResponse: true and no service-wide default is configured. See Signed Requests and Encrypted Responses for when this is needed.
    • x5c: Array of Strings (optional) - X.509 certificate chain for this verification session. Overrides the service-wide default x5c configured during verifier2 service creation. Must be an ordered chain in DER-encoded, Base64-encoded format where the first certificate corresponds to the key. Required for X.509-based client authentication (x509_san_dns: or x509_hash: as clientId) and signed Annex C requests. See Signed Requests to learn more.
    • verifier_info: Object (optional) - An array of attestations about the Verifier relevant to the Credential Request. Each object is a JSON object with the following fields:
      • format: String - The format of the attestation. Currently only "jwt" is supported.
      • data: String - The attestation data in JWT format.
      • credentialIds: Array (optional) - Specifies which credentials in your DCQL query this attestation applies to. References the id fields from your credentials array in the DCQL query. If omitted, the attestation applies to all requested credentials.
    • expirationDuration: String (optional) - ISO-8601 duration specifying how long the verification session remains valid. Defaults to 10 minutes (PT10M). Example: "PT1H" for 1 hour, "PT30M" for 30 minutes.
    • expirationDate: String (optional) - ISO-8601 datetime specifying the exact time when the session expires. Takes precedence over expirationDuration if both are set. Example: "2026-05-21T15:00:00Z". Session expires if left unused (no presentation pushed). Once a presentation is received, the session is no longer eligible for expiry.
  • openid: Object (optional) - OpenID4VP-specific extensions
    • transactionData: Array (optional) - Bind the credential presentation to a specific transaction (e.g., payment authorization, account access). Each entry references credential IDs and includes transaction details. See Transaction Data Authorization for full documentation.
  • url_config: Object (optional) - URL configuration for this session. Only applies to cross_device and same_device flows (not dc_api).
    • url_prefix: String (optional) - The publicly accessible base URL where the wallet will fetch the authorization request and post its response.
      • The service constructs: Request URI: {urlPrefix}/{target}/verifier2-service-api/{sessionId}/request and Response URI: {urlPrefix}/{target}/verifier2-service-api/{sessionId}/response
      • Must be reachable by the wallet (use ngrok or public URL for local development)
    • url_host: String (optional) - The base URL used to construct the authorization request link. Can be set as a service-wide default during verifier2 service creation and overridden per-session here.
      • For standard OID4VP flows, use "openid4vp://authorize" (default)
      • For custom authorization endpoints (e.g. conformance testing), provide a full HTTPS URL
  • redirects: Object (optional) - Success and error redirect URLs (only for cross_device and same_device flows)
    • successRedirectUri: String - URL to redirect the user after successful verification
    • errorRedirectUri: String - URL to redirect the user if verification fails

    Service-Level Defaults: The key, x5c, and url_host parameters can be configured as service-wide defaults during verifier2 service creation. Request-level parameters provided here override these defaults for that specific session only.


Example Response
{
  "sessionId": "ff4f0c86-56ce-4e4a-a137-dd5569049ff3",
  "bootstrapAuthorizationRequestUrl": "openid4vp://authorize?client_id=did%3Ajwk%3AeyJr...",
  "fullAuthorizationRequestUrl": "openid4vp://authorize?response_type=vp_token&client_id=did%3Ajwk%3AeyJr...",
  "creationTarget": "org.tenant.verifier.ff4f0c86-56ce-4e4a-a137-dd5569049ff3"
}

Response Fields:

  • sessionId: String - The unique ID of this verification session. Use this to query the session status.
  • bootstrapAuthorizationRequestUrl: String - Shortened URL using request_uri by reference. Use this for QR codes to minimize QR code density.
  • fullAuthorizationRequestUrl: String - Complete URL with all parameters embedded. Use this if the wallet doesn't support request_uri (rare).
  • creationTarget: String - The full resource path including the session ID. Used for querying the session status.

Presenting the Request to the User

After creating the session, you need to present the authorization request to the user based on the flow type you chose.

Cross-Device Flow (QR Code)

  1. Generate a QR code from the bootstrapAuthorizationRequestUrl
  2. Display the QR code to the user on your web page or application
  3. User scans the QR code with their wallet app
  4. Wallet presents the credential and posts the response to your verifier
  5. Monitor the session status by polling the session endpoint or using SSE/callbacks
  1. Redirect the user to the bootstrapAuthorizationRequestUrl
  2. User's wallet app opens automatically (via deep link)
  3. Wallet presents the credential and posts the response to your verifier
  4. User is redirected to your successRedirectUri or errorRedirectUri
  5. Query the session status to retrieve the verification results

Checking Verification Results

You can query the verification session to check if the user has presented their credential and whether validation succeeded.

CURL

Endpoint: GET /v1/{creationTarget}/verifier2-service-api/verification-session/info | API Reference

Example Request
curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{creationTarget}/verifier2-service-api/verification-session/info' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}'

Path Parameters

  • orgID: String (required) - Your organization ID for the base URL.
  • creationTarget: String (required) - The creationTarget value returned when creating the verification session. It is a concatenation of the target resource and the session ID.

Header Parameters

  • Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format: Bearer {token}.

Example Response
{
  "_id": "waltid.tenant1.verifier1.fc1e70cc-04b3-4c17-a454-cf03826ee520",
  "session": {
    "id": "fc1e70cc-04b3-4c17-a454-cf03826ee520",
    "setup": {
      "flow_type": "cross_device",
      "core_flow": {
        "dcql_query": {
          "credentials": [
            {
              "id": "credential_1",
              "format": "dc+sd-jwt",
              "multiple": false,
              "meta": {
                "vct_values": [
                  "https://issuer.demo.walt.id/draft13/identity_credential"
                ],
                "format": "dc+sd-jwt"
              },
              "require_cryptographic_holder_binding": true,
              "claims": [
                {
                  "path": [
                    "given_name"
                  ]
                },
                {
                  "path": [
                    "family_name"
                  ]
                },
                {
                  "path": [
                    "address",
                    "street_address"
                  ]
                }
              ]
            }
          ]
        },
        "signed_request": false,
        "encrypted_response": false,
        "policies": {}
      },
      "url_config": {}
    },
    "creationDate": "2026-05-20T12:26:38.286031245Z",
    "expirationDate": "2026-05-20T12:36:52.697195591Z",
    "retentionDate": "2036-05-20T12:26:38.286031245Z",
    "status": "SUCCESSFUL",
    "attempted": true,
    "reattemptable": true,
    "bootstrapAuthorizationRequest": {
      "response_type": "vp_token",
      "request_uri": "https://waltid.testing-0-20-0.enterprise.test.waltid.cloud/v1/waltid.tenant1.verifier1/verifier2-service-api/fc1e70cc-04b3-4c17-a454-cf03826ee520/request"
    },
    "bootstrapAuthorizationRequestUrl": "openid4vp://authorize?request_uri=https%3A%2F%2Fwaltid.testing-0-20-0.enterprise.test.waltid.cloud%2Fv1%2Fwaltid.tenant1.verifier1%2Fverifier2-service-api%2Ffc1e70cc-04b3-4c17-a454-cf03826ee520%2Frequest",
    "authorizationRequest": {
      "response_type": "vp_token",
      "state": "295283f9-a5fa-4040-afc3-8af30bdb8e54",
      "response_mode": "direct_post",
      "nonce": "a63dca7c-1557-46ac-9972-cea6696ebf28",
      "response_uri": "https://waltid.testing-0-20-0.enterprise.test.waltid.cloud/v1/waltid.tenant1.verifier1/verifier2-service-api/fc1e70cc-04b3-4c17-a454-cf03826ee520/response",
      "dcql_query": {
        "credentials": [
          {
            "id": "credential_1",
            "format": "dc+sd-jwt",
            "multiple": false,
            "meta": {
              "vct_values": [
                "https://issuer.demo.walt.id/draft13/identity_credential"
              ],
              "format": "dc+sd-jwt"
            },
            "require_cryptographic_holder_binding": true,
            "claims": [
              {
                "path": [
                  "given_name"
                ]
              },
              {
                "path": [
                  "family_name"
                ]
              },
              {
                "path": [
                  "address",
                  "street_address"
                ]
              }
            ]
          }
        ]
      },
      "client_metadata": {
        "vp_formats_supported": {
          "mso_mdoc": {
            "issuerauth_alg_values": [
              -7,
              -9,
              -50
            ],
            "deviceauth_alg_values": [
              -7,
              -9,
              -50,
              -65537
            ]
          }
        },
        "client_name": "Verifier"
      }
    },
    "authorizationRequestUrl": "openid4vp://authorize?response_type=vp_token&state=295283f9-a5fa-4040-afc3-8af30bdb8e54&response_mode=direct_post&nonce=a63dca7c-1557-46ac-9972-cea6696ebf28&response_uri=https%3A%2F%2Fwaltid.testing-0-20-0.enterprise.test.waltid.cloud%2Fv1%2Fwaltid.tenant1.verifier1%2Fverifier2-service-api%2Ffc1e70cc-04b3-4c17-a454-cf03826ee520%2Fresponse&dcql_query=%7B%22credentials%22%3A%5B%7B%22id%22%3A%22credential_1%22%2C%22format%22%3A%22dc%2Bsd-jwt%22%2C%22meta%22%3A%7B%22vct_values%22%3A%5B%22https%3A%2F%2Fissuer.demo.walt.id%2Fdraft13%2Fidentity_credential%22%5D%7D%2C%22claims%22%3A%5B%7B%22path%22%3A%5B%22given_name%22%5D%7D%2C%7B%22path%22%3A%5B%22family_name%22%5D%7D%2C%7B%22path%22%3A%5B%22address%22%2C%22street_address%22%5D%7D%5D%7D%5D%7D&client_metadata=%7B%22vp_formats_supported%22%3A%7B%22mso_mdoc%22%3A%7B%22issuerauth_alg_values%22%3A%5B-7%2C-9%2C-50%5D%2C%22deviceauth_alg_values%22%3A%5B-7%2C-9%2C-50%2C-65537%5D%7D%7D%2C%22client_name%22%3A%22Verifier%22%7D",
    "requestMode": "REQUEST_URI",
    "policies": {
      "vp_policies": {
        "jwt_vc_json": [
          "jwt_vc_json/audience-check",
          "jwt_vc_json/nonce-check",
          "jwt_vc_json/envelope_signature"
        ],
        "dc+sd-jwt": [
          "dc+sd-jwt/audience-check",
          "dc+sd-jwt/kb-jwt_signature",
          "dc+sd-jwt/nonce-check",
          "dc+sd-jwt/sd_hash-check"
        ],
        "mso_mdoc": [
          "mso_mdoc/device-auth",
          "mso_mdoc/device_key_auth",
          "mso_mdoc/issuer_auth",
          "mso_mdoc/issuer_signed_integrity",
          "mso_mdoc/mso"
        ]
      },
      "vc_policies": [
        {
          "policy": "signature",
          "id": "signature"
        }
      ]
    },
    "policy_results": {
      "vp_policies": {
        "credential_1": {
          "dc+sd-jwt/audience-check": {
            "policy_executed": {
              "policy": "dc+sd-jwt/audience-check",
              "id": "dc+sd-jwt/audience-check",
              "description": "Check if presentation audience matches expected audience for session"
            },
            "success": true,
            "results": {},
            "errors": [],
            "execution_time": "PT0.000023300S"
          },
          "dc+sd-jwt/kb-jwt_signature": {
            "policy_executed": {
              "policy": "dc+sd-jwt/kb-jwt_signature",
              "id": "dc+sd-jwt/kb-jwt_signature",
              "description": "Verify the KB-JWTs signature with the holders key"
            },
            "success": true,
            "results": {
              "holder_key_jwk": {
                "kty": "EC",
                "crv": "P-256",
                "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
                "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
                "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
              },
              "verified_kb_jwt_content": {
                "nonce": "a63dca7c-1557-46ac-9972-cea6696ebf28",
                "iat": 1779280012,
                "sd_hash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4"
              }
            },
            "errors": [],
            "execution_time": "PT0.001774609S"
          },
          "dc+sd-jwt/nonce-check": {
            "policy_executed": {
              "policy": "dc+sd-jwt/nonce-check",
              "id": "dc+sd-jwt/nonce-check",
              "description": "Check if presentation nonce matches expected nonce for session"
            },
            "success": true,
            "results": {},
            "errors": [],
            "execution_time": "PT0.000009700S"
          },
          "dc+sd-jwt/sd_hash-check": {
            "policy_executed": {
              "policy": "dc+sd-jwt/sd_hash-check",
              "id": "dc+sd-jwt/sd_hash-check",
              "description": "Verify SD-JWT Key Binding by recalculating SD Hashes"
            },
            "success": true,
            "results": {
              "presentation_sdhash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4",
              "recalculated_sdhash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4"
            },
            "errors": [],
            "execution_time": "PT0.000107600S"
          }
        }
      },
      "vc_policies": [
        {
          "policy": {
            "policy": "signature",
            "id": "signature"
          },
          "success": true,
          "result": {
            "verification_result": true,
            "signed_credential": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
            "credential_signature": {
              "type": "signature-sd_jwt",
              "signature": "wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
              "jwtHeader": {
                "kid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp#z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
                "typ": "vc+sd-jwt",
                "alg": "EdDSA"
              }
            },
            "verified_data": {
              "given_name": "John",
              "family_name": "Doe",
              "email": "johndoe@example.com",
              "phone_number": "+1-202-555-0101",
              "address": {
                "street_address": "123 Main St",
                "locality": "Anytown",
                "region": "Anystate",
                "country": "US"
              },
              "is_over_18": true,
              "is_over_21": true,
              "is_over_65": true,
              "id": "urn:uuid:d8cfebda-9601-4d71-89ec-9e1aebf94ad9",
              "iat": 1779278510,
              "nbf": 1779278510,
              "exp": 1810814510,
              "_sd_alg": "sha-256",
              "iss": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
              "cnf": {
                "jwk": {
                  "kty": "EC",
                  "crv": "P-256",
                  "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
                  "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
                  "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
                }
              },
              "vct": "https://issuer.demo.walt.id/draft13/identity_credential",
              "_sd": [
                "_79Sb32NAIFy22CB3Gu9gqRWsxB0rNvvKXRxdAf-FXM"
              ]
            },
            "successful_issuer_public_key": {
              "kty": "OKP",
              "crv": "Ed25519",
              "x": "T3T4-u1Xz3vAV2JwPNxWfs4pik_JLiArz_WTCvrCFUM"
            },
            "successful_issuer_public_key_id": "Vzx7l5fh56F3Pf9aR3DECU5BwfrY6ZJe05aiWYWzan8"
          }
        }
      ],
      "specific_vc_policies": {},
      "overallSuccess": true
    },
    "presentation_validation_results": {
      "credential_1": {
        "dc+sd-jwt/audience-check": {
          "policy_executed": {
            "policy": "dc+sd-jwt/audience-check",
            "id": "dc+sd-jwt/audience-check",
            "description": "Check if presentation audience matches expected audience for session"
          },
          "success": true,
          "results": {},
          "errors": [],
          "execution_time": "PT0.000023300S"
        },
        "dc+sd-jwt/kb-jwt_signature": {
          "policy_executed": {
            "policy": "dc+sd-jwt/kb-jwt_signature",
            "id": "dc+sd-jwt/kb-jwt_signature",
            "description": "Verify the KB-JWTs signature with the holders key"
          },
          "success": true,
          "results": {
            "holder_key_jwk": {
              "kty": "EC",
              "crv": "P-256",
              "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
              "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
              "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
            },
            "verified_kb_jwt_content": {
              "nonce": "a63dca7c-1557-46ac-9972-cea6696ebf28",
              "iat": 1779280012,
              "sd_hash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4"
            }
          },
          "errors": [],
          "execution_time": "PT0.001774609S"
        },
        "dc+sd-jwt/nonce-check": {
          "policy_executed": {
            "policy": "dc+sd-jwt/nonce-check",
            "id": "dc+sd-jwt/nonce-check",
            "description": "Check if presentation nonce matches expected nonce for session"
          },
          "success": true,
          "results": {},
          "errors": [],
          "execution_time": "PT0.000009700S"
        },
        "dc+sd-jwt/sd_hash-check": {
          "policy_executed": {
            "policy": "dc+sd-jwt/sd_hash-check",
            "id": "dc+sd-jwt/sd_hash-check",
            "description": "Verify SD-JWT Key Binding by recalculating SD Hashes"
          },
          "success": true,
          "results": {
            "presentation_sdhash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4",
            "recalculated_sdhash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4"
          },
          "errors": [],
          "execution_time": "PT0.000107600S"
        }
      }
    },
    "presented_raw_data": {
      "vpToken": {
        "credential_1": [
          "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA~eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOm51bGwsIm5vbmNlIjoiYTYzZGNhN2MtMTU1Ny00NmFjLTk5NzItY2VhNjY5NmViZjI4IiwiaWF0IjoxNzc5MjgwMDEyLCJzZF9oYXNoIjoiWHQ0VmVOUUJrc1ItcFF3dHJZZTh4TGhhYmJkUWVLZFVKdE4tMEVMbkdSNCJ9.BEWOb3oQNcMWNyyAVlM9MZeKBn7S-xQawumUEcGNZa_3PYcw9XKOwo0EEOb02m7zv7iv3ew9xOm5P0_42zQrRQ"
        ]
      },
      "state": "295283f9-a5fa-4040-afc3-8af30bdb8e54"
    },
    "presented_presentations": {
      "credential_1": {
        "type": "dc+sd-jwt",
        "format": "dc+sd-jwt",
        "sdJwt": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
        "disclosures": [],
        "keyBindingJwt": "eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOm51bGwsIm5vbmNlIjoiYTYzZGNhN2MtMTU1Ny00NmFjLTk5NzItY2VhNjY5NmViZjI4IiwiaWF0IjoxNzc5MjgwMDEyLCJzZF9oYXNoIjoiWHQ0VmVOUUJrc1ItcFF3dHJZZTh4TGhhYmJkUWVLZFVKdE4tMEVMbkdSNCJ9.BEWOb3oQNcMWNyyAVlM9MZeKBn7S-xQawumUEcGNZa_3PYcw9XKOwo0EEOb02m7zv7iv3ew9xOm5P0_42zQrRQ",
        "credential": {
          "dmtype": "sdjwtvcdm",
          "disclosables": {
            "_sd": [
              "_79Sb32NAIFy22CB3Gu9gqRWsxB0rNvvKXRxdAf-FXM"
            ]
          },
          "signedWithDisclosures": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA~",
          "credentialData": {
            "given_name": "John",
            "family_name": "Doe",
            "email": "johndoe@example.com",
            "phone_number": "+1-202-555-0101",
            "address": {
              "street_address": "123 Main St",
              "locality": "Anytown",
              "region": "Anystate",
              "country": "US"
            },
            "is_over_18": true,
            "is_over_21": true,
            "is_over_65": true,
            "id": "urn:uuid:d8cfebda-9601-4d71-89ec-9e1aebf94ad9",
            "iat": 1779278510,
            "nbf": 1779278510,
            "exp": 1810814510,
            "_sd_alg": "sha-256",
            "iss": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
            "cnf": {
              "jwk": {
                "kty": "EC",
                "crv": "P-256",
                "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
                "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
                "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
              }
            },
            "vct": "https://issuer.demo.walt.id/draft13/identity_credential"
          },
          "originalCredentialData": {
            "given_name": "John",
            "family_name": "Doe",
            "email": "johndoe@example.com",
            "phone_number": "+1-202-555-0101",
            "address": {
              "street_address": "123 Main St",
              "locality": "Anytown",
              "region": "Anystate",
              "country": "US"
            },
            "is_over_18": true,
            "is_over_21": true,
            "is_over_65": true,
            "id": "urn:uuid:d8cfebda-9601-4d71-89ec-9e1aebf94ad9",
            "iat": 1779278510,
            "nbf": 1779278510,
            "exp": 1810814510,
            "_sd_alg": "sha-256",
            "iss": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
            "cnf": {
              "jwk": {
                "kty": "EC",
                "crv": "P-256",
                "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
                "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
                "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
              }
            },
            "vct": "https://issuer.demo.walt.id/draft13/identity_credential",
            "_sd": [
              "_79Sb32NAIFy22CB3Gu9gqRWsxB0rNvvKXRxdAf-FXM"
            ]
          },
          "issuer": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
          "signature": {
            "type": "signature-sd_jwt",
            "signature": "wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
            "jwtHeader": {
              "kid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp#z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
              "typ": "vc+sd-jwt",
              "alg": "EdDSA"
            }
          },
          "signed": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
          "format": "dc+sd-jwt"
        },
        "nonce": "a63dca7c-1557-46ac-9972-cea6696ebf28",
        "sdHash": "Xt4VeNQBksR-pQwtrYe8xLhabbdQeKdUJtN-0ELnGR4",
        "presentationStringHashable": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA~"
      }
    },
    "presented_credentials": {
      "credential_1": [
        {
          "type": "vc-sd_jwt",
          "dmtype": "sdjwtvcdm",
          "disclosables": {
            "_sd": [
              "_79Sb32NAIFy22CB3Gu9gqRWsxB0rNvvKXRxdAf-FXM"
            ]
          },
          "signedWithDisclosures": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA~",
          "credentialData": {
            "given_name": "John",
            "family_name": "Doe",
            "email": "johndoe@example.com",
            "phone_number": "+1-202-555-0101",
            "address": {
              "street_address": "123 Main St",
              "locality": "Anytown",
              "region": "Anystate",
              "country": "US"
            },
            "is_over_18": true,
            "is_over_21": true,
            "is_over_65": true,
            "id": "urn:uuid:d8cfebda-9601-4d71-89ec-9e1aebf94ad9",
            "iat": 1779278510,
            "nbf": 1779278510,
            "exp": 1810814510,
            "_sd_alg": "sha-256",
            "iss": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
            "cnf": {
              "jwk": {
                "kty": "EC",
                "crv": "P-256",
                "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
                "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
                "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
              }
            },
            "vct": "https://issuer.demo.walt.id/draft13/identity_credential"
          },
          "originalCredentialData": {
            "given_name": "John",
            "family_name": "Doe",
            "email": "johndoe@example.com",
            "phone_number": "+1-202-555-0101",
            "address": {
              "street_address": "123 Main St",
              "locality": "Anytown",
              "region": "Anystate",
              "country": "US"
            },
            "is_over_18": true,
            "is_over_21": true,
            "is_over_65": true,
            "id": "urn:uuid:d8cfebda-9601-4d71-89ec-9e1aebf94ad9",
            "iat": 1779278510,
            "nbf": 1779278510,
            "exp": 1810814510,
            "_sd_alg": "sha-256",
            "iss": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
            "cnf": {
              "jwk": {
                "kty": "EC",
                "crv": "P-256",
                "kid": "61BF1dMVfrdRMGIEO4ZOSZX39a0stj0_d8h4CkATQRU",
                "x": "m4r2Sf0jYK3OXLPrdrwC2OSSkwCBUVNJH-kpIlzmBzo",
                "y": "Uqa4uWu4rgrm3Cj9wugwYIig5ZS9DkLKxKnGk8sYr1o"
              }
            },
            "vct": "https://issuer.demo.walt.id/draft13/identity_credential",
            "_sd": [
              "_79Sb32NAIFy22CB3Gu9gqRWsxB0rNvvKXRxdAf-FXM"
            ]
          },
          "issuer": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
          "signature": {
            "type": "signature-sd_jwt",
            "signature": "wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
            "jwtHeader": {
              "kid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp#z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
              "typ": "vc+sd-jwt",
              "alg": "EdDSA"
            }
          },
          "signed": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDpkOGNmZWJkYS05NjAxLTRkNzEtODllYy05ZTFhZWJmOTRhZDkiLCJpYXQiOjE3NzkyNzg1MTAsIm5iZiI6MTc3OTI3ODUxMCwiZXhwIjoxODEwODE0NTEwLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiNjFCRjFkTVZmcmRSTUdJRU80Wk9TWlgzOWEwc3RqMF9kOGg0Q2tBVFFSVSIsIngiOiJtNHIyU2YwallLM09YTFByZHJ3QzJPU1Nrd0NCVVZOSkgta3BJbHptQnpvIiwieSI6IlVxYTR1V3U0cmdybTNDajl3dWd3WUlpZzVaUzlEa0xLeEtuR2s4c1lyMW8ifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsiXzc5U2IzMk5BSUZ5MjJDQjNHdTlncVJXc3hCMHJOdnZLWFJ4ZEFmLUZYTSJdfQ.wbfTBi1yW6RbcOwhPRxVYrwcOZBYrktAUWgqqkQpmY0cZH6Ckki3qHLtBx51lasoHUIdIAgqWLvr5CMuy3YfDA",
          "format": "dc+sd-jwt"
        }
      ]
    }
  },
  "timestamp": 1779279998286,
  "parent": "waltid.tenant1.verifier1"
}

Key Response Fields:

  • id: String - The verification session ID
  • setup: Object - The complete session configuration used to create this verification session
  • creationDate: String - ISO 8601 timestamp when the session was created
  • expirationDate: String - ISO 8601 timestamp when the session expires (default: 10 minutes after creation)
  • status: String - The current status of the verification session. Possible values:
    • "ACTIVE" — Session was created and is active
    • "IN_USE" — AuthorizationRequest was requested by wallet
    • "PROCESSING_FLOW" — Received presentation is being processed
    • "EXPIRED" — Verification request expired
    • "SUCCESSFUL" — Verification completed successfully (all policies passed)
    • "FAILED" — Verification was unsuccessful
  • attempted: Boolean - Whether the wallet has attempted to respond
  • reattemptable: Boolean - Whether the user can retry this verification session if it failed
  • policy_results: Object (optional) - Detailed results for all policies applied to the verification:
    • vp_policies: Object - Results for presentation-level policies
    • vc_policies: Array - Results for credential-level policies. Each item contains policy, success, and result.
    • overallSuccess: Boolean - Whether all policies passed
  • presented_credentials: Object (optional) - The credentials presented by the user, organized by credential ID

Instead of polling the session status, you can use callbacks or Server Sent Events (SSE) to be notified when the verification completes. See Callbacks & SSE for details.

Example 2: Requesting Specific Claims

SD-JWT VCs support selective disclosure. You can request specific claims using the claims array:

CURL

Endpoint: POST /v1/{target}/verifier2-service-api/verification-session/create | API Reference

Example Request
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier2-service-api/verification-session/create' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "flow_type": "cross_device",
  "core_flow": {
    "dcql_query": {
      "credentials": [
        {
          "id": "credential_1",
          "format": "dc+sd-jwt",
          "meta": {
            "vct_values": [
              "https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.issuer/issuer-service-api/openid4vc/draft13/identity_credential"
            ]
          },
          "claims": [
            {
              "path": ["given_name"]
            },
            {
              "path": ["family_name"]
            },
            {
              "path": ["address", "street_address"]
            }
          ]
        }
      ]
    }
  }
}'

This requests only given_name, family_name, and address.street_address from the identity credential. The user's wallet will only disclose these specific claims.

Understanding Flow Types and Core Concepts

Now that you've seen verification in action, let's understand the underlying structure.

Verification Session Structure

A VerificationSession defines the full lifecycle: authorization request → user presentation → policy validation → final result.

Every verification request follows this structure:

{
  "flow_type": "cross_device | same_device | dc_api",
  "core_flow": { /* common to all flows */ },
  "url_config": { /* specific to cross_device and same_device */ },
  "redirects": { /* optional */ }
}

Why this structure?

  • flow_type determines how the credential request is delivered (QR code vs deep link vs browser API)
  • core_flow contains the credential query and policies (same regardless of delivery method)
  • url_config and redirects are flow-specific attributes

This separation makes it easy to switch between flows without changing your credential requirements.

Flow Type Comparison

Flow TypeUse CaseRequired AttributesUser Experience
cross_deviceUser scans QR code from desktopNone beyond core flowDesktop shows QR → User scans with phone → Phone wallet opens
same_deviceUser clicks link on mobileredirects (success/error URLs)Browser redirects to wallet → Wallet opens → User returns to browser
dc_apiBrowser-native credential exchangeexpectedOrigins (array of allowed origins)Browser shows native credential picker → User selects → Instant return

Advanced Options

Signed Requests

Sign the authorization request JWT using a verifier signing key. This is required for:

  • HAIP profile compliance
  • DC API Annex C (ISO 18013-7) flows

Enable by setting signedRequest: true in the request body.

Key Configuration Required: Signed requests require a signing key (key) to be configured. You can either:

  • Set the key parameter during verifier2 service creation as a service-wide default
  • Override or provide the key directly in the verification request body

Certificate Chain (x5c) Required for:

  • X.509-based client authentication when using x509_san_dns: or x509_hash: as the clientId format
  • Signed Annex C (ISO 18013-7) requests

The x5c parameter can be configured the same way as key — as a service-wide default or per-session override.

Encrypted Responses

The wallet can encrypt the VP token response. Enable by setting encryptedResponse: true in the request body.

Key Configuration Required: Encrypted responses require a key (key) for decrypting the VP token response. Configure it during verifier2 service creation or provide it in the verification request body.

Custom Policies

Override default validation policies:

{
  "flow_type": "cross_device",
  "core_flow": {
    "dcql_query": { /* ... */ },
    "policies": {
      "vc_policies": [
        {
          "policy": "signature"
        },
        {
          "policy": "expired"
        },
        {
          "policy": "not-before"
        }
      ]
    }
  }
}

See Policies overview for all available policies.

Transaction Data Authorization

Bind credential presentations to specific transactions via transaction data like payment authorization or account access.

Use Cases:

  • Payment authorization (amount, currency, payee)
  • Account access requests (account ID, scope)
  • Custom transaction types via configuration

Supported Formats: dc+sd-jwt and mso_mdoc

For SD-JWT VC credentials, the wallet signs the requested transaction data hashes in the KB-JWT and the verifier evaluates the dc+sd-jwt/transaction-data-hash-check policy. For mdoc credentials, the wallet embeds transaction data hashes in the DeviceSigned namespaces and the verifier evaluates the mso_mdoc/transaction-data-hash-check policy.

Example Request:

{
  "flow_type": "cross_device",
  "core_flow": {
    "dcql_query": {
      "credentials": [
        {
          "id": "pid",
          "format": "dc+sd-jwt",
          "meta": {
            "vct_values": [
              "https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.issuer/issuer-service-api/openid4vc/draft13/identity_credential"
            ]
          },
          "claims": [
            { "path": ["given_name"] },
            { "path": ["family_name"] }
          ]
        }
      ]
    }
  },
  "openid": {
    "transactionData": [
      {
        "type": "org.waltid.transaction-data.payment-authorization",
        "credential_ids": ["pid"],
        "require_cryptographic_holder_binding": true,
        "transaction_data_hashes_alg": ["sha-256"],
        "amount": "42.00",
        "currency": "EUR",
        "payee": "ACME Corp"
      }
    ]
  }
}

Transaction Data Parameters

Each entry in the transactionData array includes:

Common Parameters (Required for all types):

  • type: String (required) — The transaction data type identifier. Must match a type defined in your transaction-data-profiles configuration. Built-in types:
    • "org.waltid.transaction-data.payment-authorization" — For payment authorizations
    • "org.waltid.transaction-data.account-access" — For account access requests
  • credential_ids: Array of Strings (required) — References the id fields from your DCQL credentials array. Specifies which credential(s) this transaction data applies to. Example: ["pid"] if your credential query has "id": "pid".
  • require_cryptographic_holder_binding: Boolean (optional) - If provided, it must be set to true. Transaction data requires cryptographic holder binding (KB-JWT for SD-JWT VC, DeviceAuth for mDL). Requests with false are rejected per OpenID4VP §B.3.3.
  • transaction_data_hashes_alg: Array of Strings (optional) — Hash algorithms the wallet uses to bind transaction data. e.g. ["sha-256"]. If omitted "sha-256" is used.

Type-Specific Parameters:

The remaining parameters depend on the type field and are defined by your transaction data profile configuration:

  • For payment-authorization type:
    • amount: String — Payment amount (e.g., "42.00")
    • currency: String — Currency code (e.g., "EUR")
    • payee: String — Payee identifier or name (e.g., "ACME Corp")
  • For account-access type:
    • account_identifier: String — Account identifier
    • access_scope: String — Scope of access being requested

See Transaction Data Profiles for how to define custom types and fields.

Encoding Behavior: You pass transaction data entries as plain JSON objects in your verification request. The verifier service automatically base64url-encodes each entry before placing it in the authorization request sent to the wallet. Do not base64-encode the entries yourself.

Constraints

  • transaction_data requires a dcql_query. Requests without one are rejected with invalid_request.
  • Each entry's credential_ids must reference DCQL credential query ids declared in the same request.
  • Each referenced credential query must use a transaction-data-capable format: dc+sd-jwt or mso_mdoc.
  • Transaction data with require_cryptographic_holder_binding: false is rejected. See OpenID4VP §B.3.3.
  • Transaction-data types are configurable via transaction data profiles. Built-in profiles include payment-authorization and account-access. Custom types can be added through the transaction-data-profiles configuration.
  • Available on cross_device, same_device, and dc_api (Annex D) flows via the openid.transactionData field.

Automatic Policy Enforcement: When transactionData is present, the verifier automatically adds the appropriate transaction-data hash-check policy (dc+sd-jwt/transaction-data-hash-check for SD-JWT, mso_mdoc/transaction-data-hash-check for mDL) to ensure the wallet properly binds the transaction data. This happens even if you specify custom vp_policies. Your custom policies are preserved; the hash-check policy is added on top.

Discovery & Configuration

To see which transaction data types your verifier service recognizes:

curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier2-service-api/transaction-data-profiles' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}'

This endpoint requires CREATE_VERIFIER_SESSION permission. See Transaction Data Profiles to add custom types.

Next Steps

  • Apply custom policies — See Policies for validation rules beyond signature verification
  • Set up notifications — Use Callbacks & SSE instead of polling for session status
  • Verify other credential types — Try W3C VC or mDL
  • Use DC API — Try the Digital Credentials API for browser-native credential exchange
Last updated on June 17, 2026