---
title: "Verify Mobile Driver's Licenses (ISO/IEC 18013-7 mDL)"
description: "Request and verify mDLs using the walt.id Enterprise Stack Verifier API."
stack: "Enterprise Stack (commercial) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/verifier-service/credential-verification/mdl-oid4vc
generated: 2026-07-20
---
# Verify Mobile Driver's Licenses (ISO/IEC 18013-7 mDL) via OID4VP

This guide provides a comprehensive walkthrough for verifying an mDL based on
the [ISO/IEC 18103-7 standard](https://www.iso.org/standard/91154.html) using
the walt.id Enterprise Verifier API. The verification process will utilize the OID4VP protocol.

## Enterprise Service Dependencies

To verify credentials, you need to have the following enterprise services setup:

1. [Verifier Service](https://docs.walt.id/enterprise-stack/services/verifier-service/overview.md) - Have a running verifier service. Setup instructions can be found [here](https://docs.walt.id/enterprise-stack/services/verifier-service/setup.md).

## Verification Process

1. Set mDL as the credential type to request from a user.
2. Specify the claims from the mDL that are subject to presentation.
3. Optionally provide a success and failure redirect URL, which the user will be redirected to after the verification
   process is completed.

After you have provided the required information, the Verifier API:

1. Generates an appropriate [Presentation Definition](https://identity.foundation/presentation-exchange/#presentation-definition).
2. Returns a URL which can passed to a compliant wallet to fulfill the request.

If you have provided a success or failure redirect URL, the user will be redirected to that URL. You can then access the
verification results by using the id of the verification session, which can be found in the URL generated by the API, as
well as in the query or path parameters of the redirect URL.

### Example Verification Request

**Option: CURL**

**Endpoint:** `/v1/{target}/verifier-service-api/credentials/verify` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Verifier%20Service/post_v1__target__verifier_service_api_credentials_verify)

**Example Request**

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier-service-api/credentials/verify' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'authorizeBaseUrl: mdoc-openid4vp://' \
  -H 'responseMode: direct_post.jwt' \
  -H 'successRedirectUri: https://example.com/success?id=$id' \
  -H 'errorRedirectUri: https://example.com/error?id=$id' \
  -H 'statusCallbackUri: https://example.com/verificationResult' \
  -H 'statusCallbackApiKey: myAPIKey' \
  -H 'stateId: myUniqueStateValue' \
  -H 'Content-Type: application/json' \
  -d '{
  "request_credentials": [
    {
      "id": "mDL-request",
      "input_descriptor": {
        "id": "org.iso.18013.5.1.mDL",
        "format": {
          "mso_mdoc": {
            "alg": [
              "ES256"
            ]
          }
        },
        "constraints": {
          "fields": [
            {
              "path": [
                "$['org.iso.18013.5.1']['birth_date']"
              ],
              "intent_to_retain": false
            },
            {
              "path": [
                "$['org.iso.18013.5.1']['issue_date']"
              ],
              "intent_to_retain": false
            },
            {
              "path": [
                "$['org.iso.18013.5.1']['expiry_date']"
              ],
              "intent_to_retain": false
            }
          ],
          "limit_disclosure": "required"
        }
      }
    }
  ],
  "trusted_root_cas": [
    "-----BEGIN CERTIFICATE-----\nMIIBtDCCAVmgAwIBAgIUAOXLkeu9penFRno6oDcOBgT1odYwCgYIKoZIzj0EAwIwKDELMAkGA1UEBhMCQVQxGTAXBgNVBAMMEFdhbHRpZCBUZXN0IElBQ0EwHhcNMjUwNjAyMDYzOTQ0WhcNNDAwNTI5MDYzOTQ0WjAoMQswCQYDVQQGEwJBVDEZMBcGA1UEAwwQV2FsdGlkIFRlc3QgSUFDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZGrRN7Oeanhn7MOaGU6HhaCt8ZMySk/nRHefLbRq8lChr+PS6JqpCJ503sEvByXzPDgPsp0urKg/y0E+F7q9+jYTBfMB0GA1UdDgQWBBTxCn2nWMrE70qXb614U14BweY2azASBgNVHRMBAf8ECDAGAQH/AgEAMBoGA1UdEgQTMBGGD2h0dHBzOi8vd2FsdC5pZDAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSQAwRgIhAOM37BjC48KhsSlU6mdJwlTLrad9VzlXVKc1GmjoCNm1AiEAkFRJalpz62QCOby9l7Vkq0LAdWVKiFMd0DmSxjsdT2U=\n-----END CERTIFICATE-----\n"
  ],
  "openid_profile": "ISO_18013_7_MDOC",
  "x509SanDnsConfig": {
    "jarSigningKeyId": "waltid.tenant1.verifier1-kms.iso-mdl-reader-jar-signingkey",
    "x5Chain": [
      "-----BEGIN CERTIFICATE-----\nMIIB1jCCAXygAwIBAgIUVWGgqDn/DectsPZgdM+MGZD4rlAwCgYIKoZIzj0EAwIwJjEkMCIGA1UEAwwbVGVzdCBTZWxmLVNpZ25lZCBtREwgUmVhZGVyMB4XDTI1MDkwOTA3MDgyMVoXDTQ1MDkwNDA3MDkyMVowJjEkMCIGA1UEAwwbVGVzdCBTZWxmLVNpZ25lZCBtREwgUmVhZGVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4olVtT1WWw/keXg3Bu2cIvQiBTuzuIoSo3OsJXOjQc4SznsMmVFc/b4WTuXu/uBFztn+2Op0k7MNflbAxIyVo6OBhzCBhDAPBgNVHRMBAf8EBTADAQH/MDEGA1UdEQQqMCiCG3dhbHRpZC5lbnRlcnByaXNlLmxvY2FsaG9zdIIJbG9jYWxob3N0MB0GA1UdDgQWBBS9SQQ+meofY5U4e3+nZteQeposUDAfBgNVHSMEGDAWgBS9SQQ+meofY5U4e3+nZteQeposUDAKBggqhkjOPQQDAgNIADBFAiEAp3Mlv8Xoj2aDS3rh7FyzfXRb6Oam3cLwzLznLVMyhxICIFGmhg928AE+wFXZjo+PC7GI/B/nJ3KKRWCkMLSSY3IC+R5eDcG7Zwi9CIFO7O4ihKjc6wlc6NBzhLOewyZUVz9vhZO5e7+4EXO2f7Y6nSTsw1+VsDEjJWjoxMwETAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCR/jD5iEjY/9jZd8VStys0y4MPOKA4LIyXlePJjKFOGQIhAOrf28yStk8Evz4TOzzKgq41kX3uO8q/X75JdQ86ZvH+\n-----END CERTIFICATE-----\n"
    ]
  }
}'
```

**Path Parameters**

- `orgID`: Your organization ID (e.g., `test` for `test.enterprise-sandbox.waltid.dev`)
- `target`: The verifier service target path (e.g., `waltid.verifier1`)

**Header Parameters**

- **Authorization**: Bearer token authentication is required for enterprise stack
- **authorizeBaseUrl**: Should be set to `mdoc-openid4vp://` for mDL verification
- **responseMode**: Must be set to `direct_post.jwt` for mDL verification
- **successRedirectUri** (optional): Used to redirect the user if verification is successful. You can use the `$id`
  placeholder to get access to the id of verification session in your application in order to retrieve the verification results.
  E.g. `/success?id=$id` will be replaced with `/success?id=1234567890`
- **errorRedirectUri** (optional): Used to redirect the user if verification is unsuccessful. You can use the `$id`
  placeholder to get access to the id of verification session in your application in order to retrieve the verification results.
  E.g. `/error?id=$id` will be replaced with `/error?id=1234567890`
- **statusCallbackUri** (optional): URL that should be called when the presentation request has been fulfilled by a
  wallet. The request sent will be a `POST` including the whole presentation result.
- **statusCallbackApiKey** (optional): If the endpoint you provide via `statusCallbackUri` is protected, you can use
  the `statusCallbackApiKey` to authenticate. The provided key will be appended as Authorization Header to the request.
- **stateId** (optional): Overwrite the unique `state` value which gets created for each verification request with your
  own.

**Body**

```json
{
  "request_credentials": [
    {
      "id": "mDL-request",
      "input_descriptor": {
        "id": "org.iso.18013.5.1.mDL",
        "format": {
          "mso_mdoc": {
            "alg": [
              "ES256"
            ]
          }
        },
        "constraints": {
          "fields": [
            {
              "path": [
                "$['org.iso.18013.5.1']['birth_date']"
              ],
              "intent_to_retain": false
            },
            {
              "path": [
                "$['org.iso.18013.5.1']['issue_date']"
              ],
              "intent_to_retain": false
            },
            {
              "path": [
                "$['org.iso.18013.5.1']['expiry_date']"
              ],
              "intent_to_retain": false
            }
          ],
          "limit_disclosure": "required"
        }
      }
    }
  ],
  "trusted_root_cas": [
    "-----BEGIN CERTIFICATE-----\nMIIBtDCCAVmgAwIBAgIUAOXLkeu9penFRno6oDcOBgT1odYwCgYIKoZIzj0EAwIwKDELMAkGA1UEBhMCQVQxGTAXBgNVBAMMEFdhbHRpZCBUZXN0IElBQ0EwHhcNMjUwNjAyMDYzOTQ0WhcNNDAwNTI5MDYzOTQ0WjAoMQswCQYDVQQGEwJBVDEZMBcGA1UEAwwQV2FsdGlkIFRlc3QgSUFDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZGrRN7Oeanhn7MOaGU6HhaCt8ZMySk/nRHefLbRq8lChr+PS6JqpCJ503sEvByXzPDgPsp0urKg/y0E+F7q9+jYTBfMB0GA1UdDgQWBBTxCn2nWMrE70qXb614U14BweY2azASBgNVHRMBAf8ECDAGAQH/AgEAMBoGA1UdEgQTMBGGD2h0dHBzOi8vd2FsdC5pZDAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSQAwRgIhAOM37BjC48KhsSlU6mdJwlTLrad9VzlXVKc1GmjoCNm1AiEAkFRJalpz62QCOby9l7Vkq0LAdWVKiFMd0DmSxjsdT2U=\n-----END CERTIFICATE-----\n"
  ],
  "openid_profile": "ISO_18013_7_MDOC",
  "x509SanDnsConfig": {
    "jarSigningKeyId": "waltid.tenant1.verifier1-kms.iso-mdl-reader-jar-signingkey",
    "x5Chain": [
      "-----BEGIN CERTIFICATE-----\nMIIB1jCCAXygAwIBAgIUVWGgqDn/DectsPZgdM+MGZD4rlAwCgYIKoZIzj0EAwIwJjEkMCIGA1UEAwwbVGVzdCBTZWxmLVNpZ25lZCBtREwgUmVhZGVyMB4XDTI1MDkwOTA3MDgyMVoXDTQ1MDkwNDA3MDkyMVowJjEkMCIGA1UEAwwbVGVzdCBTZWxmLVNpZ25lZCBtREwgUmVhZGVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4olVtT1WWw/keXg3Bu2cIvQiBTuzuIoSo3OsJXOjQc4SznsMmVFc/b4WTuXu/uBFztn+2Op0k7MNflbAxIyVo6OBhzCBhDAPBgNVHRMBAf8EBTADAQH/MDEGA1UdEQQqMCiCG3dhbHRpZC5lbnRlcnByaXNlLmxvY2FsaG9zdIIJbG9jYWxob3N0MB0GA1UdDgQWBBS9SQQ+meofY5U4e3+nZteQeposUDAfBgNVHSMEGDAWgBS9SQQ+meofY5U4e3+nZteQeposUDAKBggqhkjOPQQDAgNIADBFAiEAp3Mlv8Xoj2aDS3rh7FyzfXRb6Oam3cLwzLznLVMyhxICIFGmhg928AE+wFXZjo+PC7GI/B/nJ3KKRWCkMLSSY3IC+R5eDcG7Zwi9CIFO7O4ihKjc6wlc6NBzhLOewyZUVz9vhZO5e7+4EXO2f7Y6nSTsw1+VsDEjJWjoxMwETAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCR/jD5iEjY/9jZd8VStys0y4MPOKA4LIyXlePJjKFOGQIhAOrf28yStk8Evz4TOzzKgq41kX3uO8q/X75JdQ86ZvH+\n-----END CERTIFICATE-----\n"
    ]
  }
}
```

**Body Parameters**

- **request_credentials**: An array of objects detailing the credentials to be requested from the user. For mDL credentials:
    - **id**: A unique identifier for the credential request
    - **input_descriptor**: Contains the credential specification
        - **id**: Must be `"org.iso.18013.5.1.mDL"` for mDL credentials
        - **format**: Must be `"mso_mdoc"` for mDL credentials
        - **constraints**: Defines which fields to request and validation rules
            - **fields**: Array of field specifications with paths to the requested data
            - **limit_disclosure**: Set to `"required"` for mDL verification

- **trusted_root_cas**: List of trusted IACA root certificates used to verify the authenticity of the presented mDL
  credential. These are PEM-encoded X.509 certificates.

- **openid_profile**: Must be set to `"ISO_18013_7_MDOC"` for mDL verification.
- **x509SanDnsConfig**: This object is required for mDL verification and contains parameters that are related with the `x509_san_dns` client identifier scheme, such as:
  - **jarSigningKeyId**: The identifier (full target path) of the KMS key that will be used to sign the JWT-secured Authorization Request (JAR).
  - **x5Chain**: The X509 certificate chain (provided as a list of PEM-encoded certificates) of the verifier's trust 
    chain that will be used to populate the `x5c` JWS header of the JAR. The public key of the first (leaf) 
    certificate of the chain must match the public key that corresponds to the private key that will be used to sign 
    the JAR.

---

**Example Response**

The verification endpoint will return a presentation session with a URL that can be used to complete the verification process:

```
mdoc-openid4vp://authorize?client_id=waltid.verifier1&request_uri=https://test.enterprise-sandbox.waltid.dev/v1/waltid.verifier1/verifier-service-api/openid4vc/request&response_type=vp_token&response_mode=direct_post.jwt&scope=openid&state=1234567890
```

## Presenting the Credential via walt.id Wallet

Using the URL returned by the verification request, we can fulfill the request using the
[hosted wallet](https://wallet.demo.walt.id) by walt.id. Either show the URL as QR code and scan it with a camera or provide
the URL as is in the
text field below the camera once you click on "Scan to receive or present credentials" in the web wallet credentials
overview page in the top right corner.

## Retrieving the Verification Status

After the user presents the credential(s), you can verify the status by performing the following call with the
`state` value obtained from the URL query params you shared with the user previously.

**Example**

**Option: CURL**

```
mdoc-openid4vp://authorize...state=waltid.tenant1.verifier1.fb94470b-bcee-4ed7-93f5-906a4f5f585d...
```

Making the call to receive the verification result

```bash
curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier-service-api/credentials/sessions/view' \
  -H 'accept: */*'
  -H 'Authorization: Bearer {yourToken}'
```

**Path Parameters**

- `orgID`: - When performing operations within an organization, it is essential to use the organization's Base URL or
  another valid host alias. For example, if your organization is named `test`, your default Base URL will
  be `test.enterprise-sandbox.walt.dev` when using the sandbox environment.
- `target`: _resourceIdentifier_ - The target indicates the organization + tenant + verifier service + sessionID to request
  (`{organizationID}.{tenantID}.{verifierServiceID}.{sessionID}`),
  e.g. `waltid.tenant1.verifier1.fb94470b-bcee-4ed7-93f5-906a4f5f585d`
