Receiving SD-JWT VC Credentials via OID4VCI

This guide shows you how to receive an IETF SD-JWT VC credential 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.

SD-JWT VC: An IETF credential format supporting selective disclosure, letting the holder reveal only specific claims when presenting.

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

Before you begin, ensure you have:

  • Wallet API v2 running — Follow the Setup guide. The examples below use http://localhost:7005 as the base URL.
  • A wallet holding a keyCreate a wallet, then generate a key into it (any type, e.g. Ed25519) — it becomes the wallet's default key. You'll need the wallet's walletId.
  • An SD-JWT VC credential offer — For a full end-to-end run, issue one with the Issuer2 SD-JWT VC 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, so the wallet can reach the issuer running alongside it.


Receive the Credential

Hand the offer to the wallet. This single call resolves the offer, requests an access 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.
  • 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 SD-JWT VC 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": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
    "format": "dc+sd-jwt",
    "issuer": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwi...",
    "addedAt": "2026-07-08T20:30:11.663155755Z"
  }
]

Response Fields

  • id: String - The stored credential's ID. Use it with Credential Management to view or delete it.
  • format: String - Credential format. For an SD-JWT VC this is dc+sd-jwt.
  • issuer: String (optional) - Issuer identifier when it can be determined — for the credential above, the issuer's did:jwk.
  • subject: String (optional) - Holder/subject identifier, when the credential carries one. Often absent (as above).
  • label: String (optional) - User-assigned label, when set.
  • addedAt: String - ISO-8601 timestamp of when the credential was stored.

Optional fields (issuer, subject, label) are omitted from the response when not present.


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 deferred issuance — drive the isolated endpoints yourself:

resolve-offerrequest-tokensign-prooffetch-credential

Each step, its request/response shape, and the authorization-code variant are documented in Custom Flow.


Next Steps

Last updated on July 13, 2026