---
title: "mDL / mDoc via OID4VCI"
description: "Receive an ISO 18013-5 mDL / mDoc credential into an Enterprise wallet service using OID4VCI 1.0 (Wallet2 Service)."
stack: "Enterprise Stack (commercial) — version 1.1.1"
stack_version: "1.1.1"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-receiving/mdl
generated: 2026-10-01
---
# Receiving mDL / mDoc Credentials via OID4VCI 1.0

This guide shows how to receive an [ISO 18013-5 mDL / mDoc](https://docs.walt.id/concepts/digital-credentials/mdoc-mdl-iso.md) credential into an Enterprise wallet using the **Wallet2 Service**. You take a credential offer — for example one created with [Issuer2](https://docs.walt.id/enterprise-stack/services/issuer2-service/overview.md) — and claim it into the wallet in a single call, then confirm it was stored.

[**mDL / mDoc**](https://docs.walt.id/concepts/digital-credentials/mdoc-mdl-iso.md): The ISO/IEC 18013-5 mobile document format, used for mobile driving licences and other ISO mDocs.

**Note:**

This page follows the **pre-authorized code flow**. For the authorization-code grant and for driving each step yourself (custom UIs, deferred issuance), see [Isolated Flow](https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-receiving/isolated-flow.md).

## Prerequisites

- A **wallet service** with a linked KMS, DID Store, and Credential Store — see [Setup](https://docs.walt.id/enterprise-stack/services/wallet2-service/setup.md). The wallet's default key and DID are used unless you override them.
- The wallet's **target** — `{organization}.{tenant}.{wallet-id}`, e.g. `waltid.tenant1.wallet`.
- An **mDL / mDoc credential offer** (`openid-credential-offer://…`), for example from the [Issuer2](https://docs.walt.id/enterprise-stack/services/issuer2-service/overview.md) service.

---

## Receive the Credential

This single call resolves the offer, requests an access token, signs a proof of possession with the wallet's key, fetches the credential, and stores it in the linked Credential Store.

**Option: CURL**

Endpoint: `POST /v2/{target}/wallet-service-api/credentials/receive`

**Example Request**

```bash
curl -X POST \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{org}.{tenant}.{wallet-id}/wallet-service-api/credentials/receive' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "offerUrl": "openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fissuer.example.org%2Fcredential-offer%3Fid%3Dabc123"
}'
```

**Path Parameters**

- `orgID` _String_ — Organization host alias to call against, e.g. `test.enterprise-sandbox.waltid.dev` for organization `test`.
- `target` _resourceIdentifier_ — The wallet's resource path, `{organization}.{tenant}.{wallet-id}`, e.g. `waltid.tenant1.wallet`.

**Body Parameters**

- **Credential offer** (required) — provide exactly one of:
    - `offerUrl` _String_ — OID4VCI credential offer URL.
    - `offerJson` _Object_ — Raw credential offer as a JSON object, instead of a URL.
- `keyReference` (optional) _String_ — Full resource path of a key in a linked KMS (`{org}.{tenant}.{kms}.{key}`). Defaults to the first key in the wallet's linked KMS (or the service's configured static key if the KMS has none). Referenced keys stay in the KMS, so PKCS#11 / HSM backends work in this flow.
- `key` (optional) _Object_ — Inline serialized key (`{ "type": "jwk", "jwk": { … } }`). Takes precedence over `keyReference`.
- `txCode` (optional) _String_ — Transaction code (PIN), if the pre-authorized offer requires one.
- `clientId` (optional) _String_ — OAuth 2.0 `client_id` presented to the issuer's authorization server. Defaults to `wallet-client`. If one client attester service is linked and the issuer supports attestation-based client authentication, Enterprise uses the wallet resource path as the effective client ID.

**Example Response — `ReceiveCredentialResult`**

```json
{
  "credentialIds": [
    "550e8400-e29b-41d4-a716-446655440000"
  ],
  "deferredTransactionIds": {}
}
```

- `credentialIds` _String[]_ — IDs of the credentials received and stored in the wallet's Credential Store.
- `deferredTransactionIds` _Object_ — Map of credential configuration ID → `transaction_id`, present only when the issuer defers issuance. See [deferred credentials](https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-receiving/isolated-flow.md#deferred-issuance).

**Response Codes**

- `200` — Credential(s) received and stored.
- `400` — Invalid request (e.g. neither `offerUrl` nor `offerJson` provided, or the offer could not be resolved).
- `401` — Invalid authentication.

🎉 You've received an mDL / mDoc into the wallet.

---

## Confirm It Was Stored

List the wallet's credentials to see the one you just received. This returns metadata only.

**Option: CURL**

Endpoint: `GET /v2/{target}/wallet-service-api/credentials`

**Example Request**

```bash
curl \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{org}.{tenant}.{wallet-id}/wallet-service-api/credentials' \
  -H 'Authorization: Bearer {yourToken}'
```

**Path Parameters**

- `orgID` _String_ — Organization host alias.
- `target` _resourceIdentifier_ — The wallet's resource path, e.g. `waltid.tenant1.wallet`.

**Example Response**

```json
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "format": "mso_mdoc",
    "addedAt": "2026-07-09T13:24:04.282744Z"
  }
]
```

- `id` _String_ — The stored credential's ID. Use it with the [management endpoints](https://docs.walt.id/enterprise-stack/services/wallet2-service/management.md) to view or delete it.
- `format` _String_ — Credential format. For an mDL / mDoc this is `mso_mdoc`.
- `issuer` / `subject` (optional) _String_ — Issuer and holder identifiers, when present (often absent for mDocs, which bind to keys and certificates rather than DIDs).
- `addedAt` _String_ — ISO-8601 timestamp of when the credential was stored.

**Response Codes**

- `200` — Credential metadata returned.
- `401` — Invalid authentication.

---

## Doing It Step by Step

The full-flow call above is the fastest path. To show intermediate state in a wallet UI — resolve the offer, preview what's being issued, prompt for a PIN, handle deferred issuance — drive the isolated endpoints yourself:

`resolve-offer` → `request-token` → `sign-proof` → `fetch-credential`

Each step, its request/response shape, and the authorization-code variant are documented in [Isolated Flow](https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-receiving/isolated-flow.md).

---

## Next Steps

- **Present the credential you just received** — [Presenting mDL / mDoc Credentials](https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-presenting/mdl.md).
- **Receive other credential types** — [SD-JWT VC](https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-receiving/sd-jwt-vc.md) or [W3C VC](https://docs.walt.id/enterprise-stack/services/wallet2-service/credential-receiving/w3c-vc.md).
- **Manage stored credentials** — [list and retrieve](https://docs.walt.id/enterprise-stack/services/wallet2-service/management.md) credentials in the wallet.
