Receiving Credentials via OID4VCI
This guide shows you how to receive a verifiable credential into the walt.id Wallet SDK using OID4VCI 1.0. You hand the wallet a credential offer — typically an openid-credential-offer:// URL from Portal2 — and the wallet claims the credential and stores it.
OID4VCI: The protocol used to deliver credentials from an issuer to a wallet.
This page uses isolated session steps so you can show issuer, credential, and transaction-code metadata before the holder accepts. The same session APIs work for SD-JWT VC, W3C VC, and ISO 18013-5 mDL.
Prerequisites
Before you begin, ensure you have:
- A wallet with an active signing identity — Follow Integrate the SDK.
- A credential offer — Create one in portal2.demo.walt.id, or follow an Issuer2 issuance guide such as SD-JWT VC.
Always test receive through portal2.demo.walt.id.
How Issuance Works
Issuance is a session. Start it to resolve the offer and show issuer, credential, and transaction-code metadata. Continue it after the holder accepts — and after they enter a transaction code when the issuer requires one.
Loading diagram...
- Start the session with the offer URI (or inline JSON for the Digital Credentials API create flow).
- Show the typed issuer and credential metadata, and collect a transaction code only when the session requires one.
- Continue the matching grant, or cancel if the holder declines.
Pre-authorized Code
Use this path when the offer includes a pre-authorized code.
val session = wallet.startIssuance(
MobileWalletIssuanceRequest(offer = MobileWalletCredentialOffer.Uri(offerUrl))
)
val transactionCode = session.offer.transactionCode?.let { requirement ->
collectTransactionCode(
inputMode = requirement.inputMode ?: "numeric",
expectedLength = requirement.length,
description = requirement.descriptionText,
)
}
val outcome = wallet.continuePreAuthorizedIssuance(session.id, transactionCode)
val credentialIds = (outcome as? WalletIssuanceOutcome.Stored)?.credentialIds
?: error("Issuance did not store credentials: $outcome")
MobileWalletCredentialOffer.Uri is for QR and deep-link offers. Use MobileWalletCredentialOffer.InlineJson when the offer arrives through the Digital Credentials API create flow.
🎉 You've received a credential into the wallet.
Authorization Code
For an authorization-code offer, start the session, let the holder accept, then open the authorization URL and continue with the callback. beginAuthorizationIssuance creates browser state, PKCE, and the callback binding only after that explicit acceptance.
val authorization = wallet.beginAuthorizationIssuance(session.id)
openBrowser(authorization.url)
val outcome = wallet.continueAuthorizationIssuance(session.id, callbackUri)
If the holder closes the review without accepting, cancel the session instead of continuing:
wallet.cancelIssuance(session.id)
Deferred Issuance
When the issuer defers credential delivery, continuation returns WalletIssuanceOutcome.Deferred instead of Stored. Poll with resumeDeferredIssuance(deferredCredentialId) until the credential is stored.
Next Steps
- Present the credential you just received — Presenting Credentials via OID4VP.
- Issue through the OS picker — Digital Credentials API.
- See which holder key signed the proof — Keys and Storage.
