Presenting W3C VC Credentials via OID4VP 1.0
This guide shows how to present a W3C Verifiable Credential stored in an Enterprise wallet to a verifier using the Wallet API v2. You hand the wallet a presentation request — for example one created with Verifier2 — and it matches, signs, and submits in a single call.
This page follows the single-call full flow. To preview matches, show a consent screen, or present credentials that aren't stored in the wallet, see Custom Flow.
Prerequisites
- A wallet service with a linked KMS, DID Store, and Credential Store — see Setup.
- The wallet holds a W3C VC — see Receiving W3C VC Credentials.
- A presentation request from a verifier (an
openid4vp://URL).
Present the Credential
This single call resolves the request, DCQL-matches credentials from the wallet's stores, signs the presentation with the wallet's key, and submits it to the verifier.
Endpoint: POST /v2/{target}/wallet-service-api/credentials/present
Example Request
curl -X POST \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{org}.{tenant}.{wallet-id}/wallet-service-api/credentials/present' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"requestUrl": "openid4vp://authorize?client_id=did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5In0&request_uri=https://verifier.example.org/request/abc123"
}'
Path Parameters
orgIDString — Organization host alias.targetresourceIdentifier — The wallet's resource path, e.g.waltid.tenant1.wallet.
Body Parameters — PresentCredentialRequest
- Presentation request (required) — provide exactly one of:
requestUrlString — The OID4VP authorization request URL from the verifier.requestObjectObject — The authorization request as an already-fetched JSON object, instead of a URL.
keyId(optional) String — ID of the key to sign the presentation with. Defaults to the first key in the wallet's linked KMS (or the service's configured static key if the KMS has none).did(optional) String — DID to present as. Defaults to the first DID in the wallet's linked DID Store (or the configured static DID).runPolicies(optional) Boolean — Whentrue, applies configured holder policies before presenting and blocks if a policy denies it. Omitted orfalseskips policy enforcement.
Example Response — WalletPresentResult
{
"transmission_success": true,
"verifier_response": {
"status": "received",
"message": "Presentation received and is being processed."
}
}
transmission_successBoolean — Whether the wallet successfully transmitted the presentation to the verifier's response endpoint.verifier_responseObject — The raw response returned by the verifier. For adirect_postverifier (e.g. Verifier2) this is{ "status": "received", "message": "…" }; some verifiers instead return aredirect_uri.redirect_toString (optional) — Present only when the verifier returns a redirect URL to send the user to; absent fordirect_post.get_url/form_post_htmlString (optional) — Populated instead ofredirect_tofor the redirect (get_url) orform_post(form_post_html) response modes.
Response Codes
200— Presentation built and submitted.400— The presentation request could not be resolved (e.g. an unfetchablerequest_uri).
When the request resolves but no stored credential satisfies the DCQL query, the call still returns 200 with "transmission_success": false and the verifier's DCQL-fulfillment error inside verifier_response — it does not return 400.
401— Invalid authentication.
🎉 You've presented a W3C VC to the verifier.
Doing It Step by Step
The full-flow call above matches, signs, and submits in one request. To preview which credentials match before presenting, show a consent screen, or present credentials supplied inline, drive the isolated endpoints yourself:
resolve-request → match-credentials-from-store → present
Each step and the isolated (inline) variants are documented in Custom Flow.
Next Steps
- Present other credential types — SD-JWT VC or mDL.
- Receive more credentials — Credential Receiving.
- Manage stored credentials — list and retrieve credentials in the wallet.
