Receiving mDL Credentials via OID4VCI

This guide shows you how to receive an ISO 18013-5 mobile driving licence (mDL) into a wallet using the walt.id Wallet API v2. You'll take a credential offer — for example one created with Issuer2 — and claim it into a wallet in a single call, then confirm it was stored.

mDL / mdoc: The ISO/IEC 18013-5 mobile document format (mso_mdoc), used for mobile driving licences and other ISO-standard credentials.

OID4VCI: The protocol used to deliver the credential from the issuer to the wallet.

This page follows the pre-authorized code flow. For the authorization-code flow and for driving each step yourself (custom UIs, deferred issuance), see Custom Flow.

Prerequisites

  • Wallet API v2 running — Follow the Setup guide. The examples use http://localhost:7005 as the base URL.
  • A wallet holding a secp256r1 keyCreate a wallet, then generate a secp256r1 key into it (ES256, the curve mdoc/ISO 18013-5 expects) — it becomes the wallet's default key. You'll need the wallet's walletId.
  • An mDL credential offer — For a full end-to-end run, issue one with the Issuer2 mDL guide. The offer is an openid-credential-offer:// URL.

Running via Docker Compose? The quick-start stack exposes Wallet API v2 on http://localhost:7006 (Issuer2 on 7005, Verifier2 on 7004). Use that base URL instead.


Receive the Credential

Hand the offer to the wallet. This single call resolves the offer, requests a token, signs a proof of possession with the wallet's default key, fetches the credential, and stores it.

CURL

Endpoint: POST /wallet/{walletId}/credentials/receive | API Reference

Example Request
curl -X POST http://localhost:7005/wallet/{walletId}/credentials/receive \
  -H 'Content-Type: application/json' \
  -d '{
    "offerUrl": "openid-credential-offer://?credential_offer_uri=http%3A%2F%2Flocalhost%3A7005%2Fopenid4vci%2Fcredential-offer%3Fid%3D48f1dc54-134c-4e10-b889-17f3c0a595bf"
  }'

Path Parameters

  • walletId: String (required) - The ID of the wallet that will receive the credential. Returned when you create a wallet; to look up an existing one, list your wallets with GET /wallet.

Body Parameters

  • Credential offer (required) — provide exactly one of:
    • offerUrl: String - The OID4VCI credential offer URL, e.g. the credentialOffer value returned by Issuer2.
    • offerJson: Object - The credential offer as an inline JSON object, instead of a URL.
  • txCode: String (optional) - Transaction code (PIN) if the offer requires one. Check the offer, or resolve it first to see txCodeRequired.
  • keyId: String (optional) - Key from the wallet's key store to bind the credential to. Defaults to the wallet's default key.
  • did: String (optional) - DID for holder binding. Defaults to the wallet's default DID. Not needed for mdoc credentials.
  • clientId: String (optional) - The OAuth 2.0 client_id the wallet presents to the issuer's authorization server. Defaults to wallet-client, which works with issuers that don't require client registration.

Example Response
{
  "credentialIds": ["6ba7b810-9dad-11d1-80b4-00c04fd430c8"],
  "deferredTransactionIds": {}
}

Response Fields

  • credentialIds: String - Wallet-assigned IDs of the credentials that were received and stored.
  • deferredTransactionIds: Object - Map of credential configuration ID → transaction_id, present only when the issuer defers issuance. See deferred issuance.

🎉 You've received an mDL credential into the wallet.


Confirm It Was Stored

List the wallet's credentials to see the one you just received. This returns metadata only — no raw credential data.

CURL

Endpoint: GET /wallet/{walletId}/credentials | API Reference

Example Request
curl http://localhost:7005/wallet/{walletId}/credentials

Path Parameters

  • walletId: String (required) - The ID of the wallet whose credentials you want to list. Returned when you create a wallet; to look up an existing one, list your wallets with GET /wallet.

Example Response
[
  {
    "id": "afbfe84f-839b-40ef-bf0c-8a579e433ba8",
    "format": "mso_mdoc",
    "addedAt": "2026-07-08T20:35:47.770818300Z"
  }
]

Response Fields

  • id: String - The stored credential's ID. Use it with Credential Management to view or delete it.
  • format: String - Credential format, mso_mdoc for an ISO 18013-5 mdoc.
  • addedAt: String - ISO-8601 timestamp of when the credential was stored.

For an mdoc the optional issuer, subject, and label fields are not populated (mdoc binds to a device key, not a subject DID), so they're omitted from the response.


Doing It Step by Step

The full-flow call above is the fastest path. If you're building a wallet UI and need to show intermediate state — resolve the offer, preview what's being issued, prompt for a PIN, handle the authorization-code flow — drive the isolated endpoints yourself. Each step and its request/response shape is documented in Custom Flow.


Next Steps

Last updated on July 13, 2026