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.

CURL

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

  • orgID String — Organization host alias.
  • target resourceIdentifier — The wallet's resource path, e.g. waltid.tenant1.wallet.

Body Parameters — PresentCredentialRequest

  • Presentation request (required) — provide exactly one of:
    • requestUrl String — The OID4VP authorization request URL from the verifier.
    • requestObject Object — 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 — When true, applies configured holder policies before presenting and blocks if a policy denies it. Omitted or false skips policy enforcement.

Example Response — WalletPresentResult

{
  "transmission_success": true,
  "verifier_response": {
    "status": "received",
    "message": "Presentation received and is being processed."
  }
}
  • transmission_success Boolean — Whether the wallet successfully transmitted the presentation to the verifier's response endpoint.
  • verifier_response Object — The raw response returned by the verifier. For a direct_post verifier (e.g. Verifier2) this is { "status": "received", "message": "…" }; some verifiers instead return a redirect_uri.
  • redirect_to String (optional) — Present only when the verifier returns a redirect URL to send the user to; absent for direct_post.
  • get_url / form_post_html String (optional) — Populated instead of redirect_to for the redirect (get_url) or form_post (form_post_html) response modes.

Response Codes

  • 200 — Presentation built and submitted.
  • 400 — The presentation request could not be resolved (e.g. an unfetchable request_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-requestmatch-credentials-from-storepresent

Each step and the isolated (inline) variants are documented in Custom Flow.


Next Steps

Last updated on July 13, 2026