> For the complete documentation index, see [llms.txt](https://docs.indicio.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.indicio.tech/developer/indicio-proven-r/how-to-guides/mdoc-mdl.md).

# mdoc/mDL

Proven and the Holdr SDK provide the capability to issue, hold, and verify credentials in the mdoc/mDL format over a variety of protocols. The following documentation describes how to use Proven for the server portions of mdoc/mDL workflows.

There are currently four categories of APIs for working with mdoc/mDL credentials over OID4VC: Keys, Schemas, Issuance, and Verification. These categories of APIs should be approached sequentially, e.g. it doesn't work to use the verification APIs if you haven't configured keys.

## Keys

### Key Initialization

Provision mDoc issuer key material so that you can securely issue mdoc and mDL credentials.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vci/setup/mdoc' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4=' \
--header 'Content-Type: application/json' \
--header 'Cookie: sessionId=s%3AIxantPaS5ZGMmrHZDetRQHQIVTRBiNBL.DAjBpQO8pxrjJdM4jQUYJU%2FlxzGAGIJcUzM%2FM7zltk0' \
--data '{
  "force": false 
}'
```

#### Request (POST)

* `force` {boolean}: Whether to force the creation of a new key or not. Use false for first-time initialization or in case you don't want to overwrite the key (if one exists). Use true to rotate the key.

#### Response

* `key_id` {string}: This string will allow you to identify the key that the system is using for mdoc, allowing you assess the state of the system (e.g., are we still using the same key as 6 months ago?). Useful to save. Sample: `8d3e8f18-5e7d-4f1a-a72b-1db2f1d0c001`&#x20;
* `cert_id` {string}: This string will allow you to identify the certificate that the system is using to identify itself to other entities, allowing you to assess the state of the system (e.g. is this the endpoint or agent I think it is?). Useful to save. Sample: `6af84a3c-b6e9-4b1c-844a-6ce6a1f2d002`
* `message` {string}: Human readable text that describes the result of the operation (e.g., mDoc issuer keys provisioned successfully). Sample: `mDoc issuer keys provisioned successfully.`

### Key Status

Use this API to check whether the agent has been initialized with mdoc issuer key material and is ready to issue credentials.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vci/status/mdoc' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request

No request body or parameters.

#### Response

* `keys` {array of objects}: The key(s) currently provisioned for mdoc issuance. Each object contains:
  * `key_id` {string}: The identifier of the provisioned key. Sample: `8d3e8f18-5e7d-4f1a-a72b-1db2f1d0c001`
  * `cert_id` {string}: The identifier of the certificate associated with this key. Sample: `6af84a3c-b6e9-4b1c-844a-6ce6a1f2d002`
* `defaultCertificate` {object}: The certificate currently designated as the default for mdoc issuance.
  * `cert_id` {string}: The identifier of the default certificate. Sample: `6af84a3c-b6e9-4b1c-844a-6ce6a1f2d002`
  * `key_id` {string}: The identifier of the key associated with this certificate. Sample: `8d3e8f18-5e7d-4f1a-a72b-1db2f1d0c001`
  * `subject_dn` {string}: The subject distinguished name of the certificate. Sample: `CN=Proven mDoc Issuer`
  * `issuer_dn` {string}: The issuer distinguished name of the certificate. Sample: `CN=Proven mDoc Issuer`
* `trustAnchors` {array}: The trust anchors configured for this issuer. Empty if none have been configured.

## Schemas

### Setup a Schema

Use this API to configure the system to issue credentials of a particular schema, i.e. set things up so you can issue mDLs, passports, national IDs, etc.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vci/credentials-supported/mdoc' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4=' \
--header 'Content-Type: application/json' \
--header 'Cookie: sessionId=s%3AIxantPaS5ZGMmrHZDetRQHQIVTRBiNBL.DAjBpQO8pxrjJdM4jQUYJU%2FlxzGAGIJcUzM%2FM7zltk0' \
--data '{
  "doctype": "org.iso.18013.5.1.mDL",
  "label": "Mobile Driver'\''s License",
  "description": "ISO 18013-5 Mobile Driver'\''s License" 
}'
```

#### Request (POST)

* `doctype` {string} **Required**: The mdoc document type identifier (e.g., `org.iso.18013.5.1.mDL`).
* `label` {string}: A human-readable name for this credential type (e.g., `Mobile Driver's License`).
* `description` {string}: A human-readable description of this credential type (e.g., `ISO 18013-5 Mobile Driver's License`).
* `display` {array of objects}: Display metadata for the credential type, used for rendering in wallets and verifier UIs.
* `verification_method` {string}: The verification method to use when signing credentials of this type.
* `issuer_id` {string}: The DID or identifier of the issuer for this credential type.
* `claims_schema` {object}: An object defining the namespaces and claims this credential type supports.
* `vc_additional_data` {object}: Additional data to include in the credential.
* `cryptographic_binding_methods_supported` {array of strings}: Cryptographic binding methods supported for this credential type.
* `cryptographic_suites_supported` {array of strings}: Cryptographic suites supported for this credential type.
* `proof_types_supported` {object}: Proof types supported for this credential type.

#### Response

* `agentRecord` {object}: The record created in the agent.
  * `supported_cred_id` {string}: Unique identifier for this credential type in the agent. Sample: `9fd5ef9d-b8b8-4f52-b6a9-95b9ce4f6f8a`
  * `identifier` {string}: The doctype string used as the credential type identifier. Sample: `org.iso.18013.5.1.mDL`
  * `format` {string}: The credential format. Always `mso_mdoc` for mdoc credentials.
  * `display` {array of objects}: Display metadata as stored in the agent.
  * `format_data` {object}: The doctype and claims as stored in the agent.
* `dbConfig` {object}: The configuration record stored in the Proven database.
  * `config_id` {string}: Unique identifier for this configuration record. Sample: `c4d8f7f2-f8d0-4d0b-93d0-9f9f31a5c003`
  * `wallet_id` {string}: The wallet this configuration is associated with. Sample: `wallet-123`
  * `doctype` {string}: The document type identifier as provided in the request.
  * `supported_cred_id` {string}: Matches the `supported_cred_id` in `agentRecord`.
  * `format` {string}: The credential format. Always `mso_mdoc`.
  * `label` {string}: The human-readable label as provided in the request.
  * `description` {string}: The human-readable description as provided in the request.
  * `created_at` {string}: ISO 8601 timestamp of when the record was created.
  * `updated_at` {string}: ISO 8601 timestamp of when the record was last updated.

### List Schemas

#### Example curl Command:

```

curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vci/credentials-supported/mdoc' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request (GET)

Optional query parameters:

* `doctype` {string}: Filter results to a specific document type.
* `config_id` {string}: Filter results to a specific configuration record.

#### Response

Returns an array of configuration objects, each with the same fields as the `dbConfig` object in the POST response above.

## Issuance

Use this API to create a credential exchange and generate an offer that can be delivered to a holder's wallet.

### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vci/issue' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4=' \
--header 'Content-Type: application/json' \
--header 'Cookie: sessionId=s%3AIxantPaS5ZGMmrHZDetRQHQIVTRBiNBL.DAjBpQO8pxrjJdM4jQUYJU%2FlxzGAGIJcUzM%2FM7zltk0' \
--data '{
  "supported_cred_id": "9fd5ef9d-b8b8-4f52-b6a9-95b9ce4f6f8a",
  "credential_subject": {
    "family_name": "Doe",
    "given_name": "Jane",
    "birth_date": "1990-01-15",
    "issue_date": "2026-03-10",
    "expiry_date": "2031-03-10",
    "issuing_country": "US",
    "issuing_authority": "State DMV",
    "document_number": "DL123456",
    "driving_privileges": "A,B,C",
    "un_distinguishing_sign": "USA",
    "sex": "2",
    "height": "170",
    "eye_colour": "BLU",
    "birth_place": "New York",
    "resident_city": "Springfield",
    "resident_state": "IL",
    "resident_postal_code": "62701",
    "resident_country": "US",
    "nationality": "US",
    "age_over_18": "true",
    "portrait": ""
  }
}'
```

### Request (POST)

* `supported_cred_id` {string}: The ID of the registered credential type to issue, obtained from the Schema Setup step. Sample: `9fd5ef9d-b8b8-4f52-b6a9-95b9ce4f6f8a`
* `credential_subject` {object}: The claims to include in the credential. Keys should match the claims defined when the credential type was registered. For an mDL, common fields include `family_name`, `given_name`, `birth_date`, `issue_date`, `expiry_date`, `issuing_country`, `issuing_authority`, `document_number`, `driving_privileges`, `un_distinguishing_sign`, and `portrait`.
* `did` {string}: The DID to associate with the credential subject.
* `verification_method` {string}: The verification method to use for signing this credential. If omitted, the system uses the verification method configured for the credential type.
* `pin` {string}: An optional user PIN for the credential offer, adding an extra layer of security to the issuance flow.
* `label` {string}: A human-readable label for this credential exchange.
* `connection_id` {string}: The connection ID to associate with this credential exchange.

### Response

* `offer` {object}: The credential offer object, suitable for delivery to a holder's wallet.
  * `credential_issuer` {string}: The URL of the credential issuer. Sample: `https://example/oid4vc/tenant/c286d1c7-c548-48d1-8580-76d3fe317bff`
  * `credentials` {array of strings}: The credential type identifiers included in this offer. For an mDL this will be `["org.iso.18013.5.1.mDL"]`.
  * `grants` {object}: The grant types available for this offer. For mdoc/mDL issuance, this will contain a pre-authorized code grant.
    * `urn:ietf:params:oauth:grant-type:pre-authorized_code` {object}: The pre-authorized code grant.
      * `pre-authorized_code` {string}: The pre-authorized code the holder's wallet uses to retrieve the credential. Sample: `iQ7DWmf2vjogMtQ_bdrDQg`
      * `user_pin_required` {boolean}: Whether the holder is required to supply a PIN to redeem the offer.
* `credential_offer` {string}: A URL-encoded `openid-credential-offer://` URI. This is typically rendered as a QR code or deep link for the holder's wallet to scan or tap.
* `exchange` {object}: The credential exchange record created by this request.
  * `exchange_id` {string}: Unique identifier for this exchange. Sample: `921786c9-dd65-473a-bebf-e5283d689c96`
  * `supported_cred_id` {string}: The credential type ID used for this exchange, matching the value from the request.
  * `credential_subject` {object}: The claims as provided in the request.
  * `verification_method` {string}: The verification method that will be used to sign the credential. Sample: `did:key:zDnaevgeiLuxFHYTHCHb1eAr489xPuCy3pDamtiGe5pWPvU41#zDnaevgeiLuxFHYTHCHb1eAr489xPuCy3pDamtiGe5pWPvU41`
  * `issuer_id` {string}: The DID of the issuer. Sample: `did:key:zDnaevgeiLuxFHYTHCHb1eAr489xPuCy3pDamtiGe5pWPvU41`
  * `state` {string}: The current state of the exchange. Will be `created` immediately after issuance is initiated.
  * `created_at` {string}: ISO 8601 timestamp of when the exchange was created.
  * `updated_at` {string}: ISO 8601 timestamp of when the exchange was last updated.

## Verification

Verification is a multi-step process. First, you create a presentation definition that describes what claims you want to verify. Then, you use that definition to create a presentation request, which generates a URI that can be delivered to a holder's wallet (e.g., as a QR code). Finally, after the holder responds, you retrieve the presentation results.

### Create a Presentation Definition

Use this API to define what credentials and claims you want to request from a holder.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vp/presentation-definitions' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4=' \
--header 'Content-Type: application/json' \
--header 'Cookie: sessionId=s%3AIxantPaS5ZGMmrHZDetRQHQIVTRBiNBL.DAjBpQO8pxrjJdM4jQUYJU%2FlxzGAGIJcUzM%2FM7zltk0' \
--data '{
    "pres_def": {
        "input_descriptors": [
            {
                "id": "org.iso.18013.5.1.mDL",
                "format": {
                    "mso_mdoc": {
                        "alg": ["ES256"]
                    }
                },
                "constraints": {
                    "limit_disclosure": "required",
                    "fields": [
                        {
                            "path": ["$['\''org.iso.18013.5.1'\'']['\''given_name'\'']"]
                        },
                        {
                            "path": ["$['\''org.iso.18013.5.1'\'']['\''family_name'\'']"]
                        }
                    ]
                }
            }
        ]
    }
}'
```

#### Request (POST)

`pres_def` {object}: The presentation definition object, following the DIF Presentation Exchange specification.

* `id` {string}: An optional identifier for the presentation definition. If omitted, the system will generate one.
* `purpose` {string}: A human-readable string describing the purpose of the verification request.
* `input_descriptors` {array of objects}: One or more descriptors specifying what credentials and claims are required.
  * `id` {string}: An identifier for this input descriptor. For mdoc, typically the doctype (e.g., `org.iso.18013.5.1.mDL`).
  * `format` {object}: Specifies the credential format. For mdoc verification, use `"mso_mdoc": { "alg": ["ES256"] }`.
  * `constraints` {object}: Defines the constraints on the requested claims.
    * `limit_disclosure` {string}: Set to `"required"` to ensure only the requested claims are disclosed.
    * `fields` {array of objects}: The specific claims to request. Each field has a `path` array using JSONPath notation. For mdoc claims, use the namespace-qualified syntax: `$['org.iso.18013.5.1']['claim_name']`.

#### Response

* `pres_def_id` {string}: The system-generated identifier for this presentation definition. Save this — you will need it to create a presentation request. Sample: `42c870ae-b605-4121-b5e3-1e6bb3a00c6f`
* `pres_def` {object}: The presentation definition as stored, including any system-generated fields such as `id`.
* `wallet_id` {string}: The wallet associated with this definition. Sample: `c286d1c7-c548-48d1-8580-76d3fe317bff`
* `created_at` {string}: ISO 8601 timestamp of when the record was created.
* `updated_at` {string}: ISO 8601 timestamp of when the record was last updated.

### List Presentation Definitions

Retrieve all presentation definitions registered for your wallet.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vp/presentation-definitions' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request (GET)

No request body or parameters.

#### Response

Returns an array of presentation definition objects, each with the same fields as the POST response for creating a presentation definition above.

### Get a Single Presentation Definition

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vp/presentation-definitions/{pres_def_id}' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request (GET)

* `pres_def_id` {string} (path parameter, required): The identifier of the presentation definition to retrieve.

#### Response

Returns a single presentation definition object with the same fields as the POST response for creating a presentation definition above.

### Delete a Presentation Definition

#### Example curl Command:

```
curl --location --request DELETE 'https://buckets4life.share.zrok.io/api/v1/oid4vp/presentation-definitions/{pres_def_id}' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request (DELETE)

* `pres_def_id` {string} (path parameter, required): The identifier of the presentation definition to delete.

#### Response

* Only an HTTP status response code is returned.

### Create a Presentation Request

Use this API to generate a presentation request from a previously created presentation definition. The response includes a URI that can be rendered as a QR code or delivered as a deep link for the holder's wallet to scan.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/oid4vp/request' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4=' \
--header 'Content-Type: application/json' \
--header 'Cookie: sessionId=s%3AIxantPaS5ZGMmrHZDetRQHQIVTRBiNBL.DAjBpQO8pxrjJdM4jQUYJU%2FlxzGAGIJcUzM%2FM7zltk0' \
--data '{
    "pres_def_id": "42c870ae-b605-4121-b5e3-1e6bb3a00c6f",
    "vp_formats": {
        "mso_mdoc": {
            "alg": ["ES256"]
        }
    }
}'
```

#### Request (POST)

* `pres_def_id` {string}: The identifier of the presentation definition to use, obtained from Step 1. Sample: `42c870ae-b605-4121-b5e3-1e6bb3a00c6f`
* `vp_formats` {object}: The verifiable presentation formats to accept. For mdoc verification, use `"mso_mdoc": { "alg": ["ES256"] }`.

#### Response

* `request_uri` {string}: A URL-encoded `openid4vp://` URI. This is typically rendered as a QR code or deep link for the holder's wallet to scan or tap. Sample: `openid4vp://?client_id=did%3Ajwk%3A...&request_uri=https%3A//example/oid4vc/tenant/.../oid4vp/request/43050ce4-bfb4-4454-b5de-9bbd1c564a85`
* `request` {object}: The presentation request record.
  * `request_id` {string}: Unique identifier for this request. Sample: `43050ce4-bfb4-4454-b5de-9bbd1c564a85`
  * `pres_def_id` {string}: The presentation definition used for this request.
  * `vp_formats` {object}: The verifiable presentation formats as provided in the request.
  * `created_at` {string}: ISO 8601 timestamp of when the request was created.
  * `updated_at` {string}: ISO 8601 timestamp of when the request was last updated.
* `presentation` {object}: The presentation exchange record created by this request.
  * `presentation_id` {string}: Unique identifier for this presentation exchange. Use this to poll for results. Sample: `5e871b45-3821-4a94-8695-303517939afb`
  * `pres_def_id` {string}: The presentation definition used.
  * `request_id` {string}: The request that initiated this presentation exchange.
  * `state` {string}: The current state of the presentation. Will be `request-created` immediately after the request is made.
  * `created_at` {string}: ISO 8601 timestamp of when the presentation exchange was created.
  * `updated_at` {string}: ISO 8601 timestamp of when the presentation exchange was last updated.

### Retrieve Presentation Results

After the holder's wallet responds to the presentation request, use this API to retrieve all of the results.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/presentations' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request (GET)

Optional query parameters:

* `sort-field` {string}: The field to sort by (default `updated_at`).
* `sort-direction` {string}: Sort direction, `ASC` or `DESC` (default `DESC`).
* `page-size` {integer}: Number of results per page (default `20`).
* `current-page` {integer}: The page number to retrieve (default `1`).
* `item-count` {integer}: The total number of items.
* `state-filter` {string}: Filter results to a specific state (e.g., `done`, `request-created`).
* `contact-id` {string}: Filter results to a specific contact.

#### Response

* `params` {object}: The pagination and filter parameters applied to the query.
* `rows` {array of objects}: The presentation records. Key fields on each record include:
  * `presentation_exchange_id` {string}: Unique identifier for the presentation exchange.
  * `state` {string}: The current state (e.g., `request-created`, `done`).
  * `verified` {boolean}: Whether the presented credentials were successfully verified.
  * `role` {string}: The role in the exchange (e.g., `verifier`).
  * `presentation` {object}: The presented credentials, if available.
  * `created_at` {string}: ISO 8601 timestamp of when the record was created.
  * `updated_at` {string}: ISO 8601 timestamp of when the record was last updated.
* `count` {integer}: The total number of presentation records.

### Get a Single Presentation

After the holder's wallet responds to the presentation request, use this API to retrieve a specific result.

#### Example curl Command:

```
curl --location 'https://buckets4life.share.zrok.io/api/v1/presentations/{presentation_exchange_id}' \
--header 'x-api-key: HuNsaIP9w0LsM5vqRhWprqLShgWLvb2yMAyuYUjWqd4='
```

#### Request (GET)

* `presentation_exchange_id` {string} (path parameter, required): The identifier of the presentation exchange to retrieve.

#### Response

Returns a single presentation record with the same fields as described in the list response above.


---

# 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.indicio.tech/developer/indicio-proven-r/how-to-guides/mdoc-mdl.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.
