Receiving W3C VC Credentials via OID4VCI 1.0
This guide shows how to receive a W3C Verifiable 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.
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. - A W3C VC 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.did(optional) String — Holder DID. Defaults to the first DID in the wallet's linked DID Store (or the configured static DID). If the issuer uses DID-based proof binding and you pass a customkeyId/key, also pass thedidassociated with that key — otherwise the wallet's default DID is used for binding instead.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": [
"f58ac347-0728-45c6-ba59-bde9d3343aa6"
],
"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 a W3C VC 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": "f58ac347-0728-45c6-ba59-bde9d3343aa6",
"format": "jwt_vc_json",
"issuer": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
"subject": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5Ii...",
"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 a W3C VC this isjwt_vc_json.issuer/subject(optional) String — Issuer and holder identifiers, when present.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 W3C VC Credentials.
- Receive other credential types — SD-JWT VC or mDL.
- Manage stored credentials — list and retrieve credentials in the wallet.
