Receiving mDL / mDoc Credentials via OID4VCI 1.0
This guide shows how to receive an ISO 18013-5 mDL / mDoc credential into an Enterprise wallet using the Wallet API v2. You take a credential offer — for example one created with Issuer2 — and claim it into the wallet in a single call, then confirm it was stored.
mDL / mDoc: The ISO/IEC 18013-5 mobile document format, used for mobile driving licences and other ISO mDocs.
This page follows the pre-authorized code flow. For the authorization-code grant and for driving each step yourself (custom UIs, deferred issuance), see Custom Flow.
Prerequisites
- A wallet service with a linked KMS, DID Store, and Credential Store — see Setup. 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 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.
Endpoint: POST /v2/{target}/wallet-service-api/credentials/receive
Example Request
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
orgIDString — Organization host alias to call against, e.g.test.enterprise-sandbox.waltid.devfor organizationtest.targetresourceIdentifier — The wallet's resource path,{organization}.{tenant}.{wallet-id}, e.g.waltid.tenant1.wallet.
Body Parameters
- Credential offer (required) — provide exactly one of:
offerUrlString — OID4VCI credential offer URL.offerJsonObject — Raw credential offer as a JSON object, instead of a URL.
keyId(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).key(optional) Object — Inline serialized key ({ "type": "jwk", "jwk": { … } }). Takes precedence overkeyId.txCode(optional) String — Transaction code (PIN), if the pre-authorized offer requires one.clientId(optional) String — OAuth 2.0client_idpresented to the issuer's authorization server. Defaults towallet-client.
Example Response — ReceiveCredentialResult
{
"credentialIds": [
"550e8400-e29b-41d4-a716-446655440000"
],
"deferredTransactionIds": {}
}
credentialIdsString — IDs of the credentials received and stored in the wallet's Credential Store.deferredTransactionIdsObject — Map of credential configuration ID →transaction_id, present only when the issuer defers issuance. See deferred credentials.
Response Codes
200— Credential(s) received and stored.400— Invalid request (e.g. neitherofferUrlnorofferJsonprovided, 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.
Endpoint: GET /v2/{target}/wallet-service-api/credentials
Example Request
curl \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{org}.{tenant}.{wallet-id}/wallet-service-api/credentials' \
-H 'Authorization: Bearer {yourToken}'
Path Parameters
orgIDString — Organization host alias.targetresourceIdentifier — The wallet's resource path, e.g.waltid.tenant1.wallet.
Example Response
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"format": "mso_mdoc",
"addedAt": "2026-07-09T13:24:04.282744Z"
}
]
idString — The stored credential's ID. Use it with the management endpoints to view or delete it.formatString — Credential format. For an mDL / mDoc this ismso_mdoc.issuer/subject(optional) String — Issuer and holder identifiers, when present (often absent for mDocs, which bind to keys and certificates rather than DIDs).addedAtString — 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 Custom Flow.
Next Steps
- Present the credential you just received — Presenting mDL / mDoc Credentials.
- Receive other credential types — SD-JWT VC or W3C VC.
- Manage stored credentials — list and retrieve credentials in the wallet.
