Default Requests

A wallet service acts as one holder, so its presentation calls keep repeating the same thing: which key and which DID to sign with. Default requests let you save that once on your Wallet2 service, so a presentation call only carries the request URL.

Default requests are optional. Nothing on this page is required to present credentials. If your wallet holds a single key and DID, you don't need them at all: the wallet uses them automatically.

When This Is Worth It

When a call omits keyReference and didReference, the wallet uses the first key in its linked KMS and the first DID in its DID Store. With one key that is exactly what you want. It stops being reliable once the wallet holds more than one key, for example an Ed25519 key next to a P-256 key: the first one is not necessarily the one your credentials are bound to.

This matters because a credential is bound to its holder's key. Presenting with any other key fails at the verifier. A default removes the guesswork and keeps every call on the same holder identity:

  • Presenting from stored credentials. wallet2-present-credential. Only the requestUrl changes per call. This is the case this page walks through.
  • Driving the isolated flow step by step. Previewing a request and building the VP token must use the same key, otherwise the two steps disagree about what the wallet can do. Store the same key as the default of wallet2-preview-presentation and wallet2-build-vp-token and neither step can drift.

What Changes

Without a default, every presentation names the key and DID it should use:

{
  "requestUrl": "openid4vp://authorize?client_id=...&request_uri=...",
  "keyReference": "waltid.tenant1.wallet1.kms.wallet_key",
  "didReference": "waltid.tenant1.wallet1.didstore.wallet_did"
}

With the key and DID stored as a default, the call becomes:

{
  "requestUrl": "openid4vp://authorize?client_id=...&request_uri=..."
}

The service fills in everything you left out. Anything you do send in the call wins over the stored value.

Prerequisites

  • A Wallet2 service with a KMS and a DID Store attached, holding a key and a DID. See Setup.
  • A credential in the wallet. See Receiving credentials.
  • A presentation request from a verifier, for example a Verifier2 session.
  • A bearer token with the update-default-requests permission and the permission to present credentials. Both are needed to store a default.

Step 1: Store a Default

Store the holder identity with a PUT. The last part of the URL, wallet2-present-credential, names the API call the default applies to: the one behind POST /v2/{target}/wallet-service-api/credentials/present. The body is an ordinary presentation request. Leave out requestUrl, which changes on every call.

CURL

Endpoint: PUT /v2/{target}/wallet-service-api/default-requests/wallet2-present-credential | API Reference

Example Request
curl -X 'PUT' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{target}/wallet-service-api/default-requests/wallet2-present-credential' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "keyReference": "waltid.tenant1.wallet1.kms.wallet_key",
  "didReference": "waltid.tenant1.wallet1.didstore.wallet_did"
}'

Path Parameters

  • orgID: String (required) - Organization host alias. For the sandbox organization test, the base URL is https://test.enterprise-sandbox.waltid.dev.
  • target: resourceIdentifier (required) - {organizationID}.{tenantID}.{walletServiceID}, for example waltid.tenant1.wallet1.

Header Parameters

  • Authorization: String (required) - Bearer token. Format: Bearer {yourToken}.

Body Parameters

  • The body is a partial presentation request. It accepts the same fields as presenting a credential, and you can send any subset of them. Unknown or misspelled keys are rejected now, not later when you present. The key and DID references themselves are not checked here, see Good to Know.
Example Response 200 OK

The stored document is echoed back.

{
  "keyReference": "waltid.tenant1.wallet1.kms.wallet_key",
  "didReference": "waltid.tenant1.wallet1.didstore.wallet_did"
}

Response Codes

  • 200 - Default request stored.
  • 400 - The document is not a valid partial body for this operation.
  • 401 / 403 - Authentication or authorization failure. update-default-requests and the operation's own permission are both required.
  • 404 - Service not found, or the operation name is unknown.

Step 2: Present a Credential

Send only the request URL.

CURL

Endpoint: POST /v2/{target}/wallet-service-api/credentials/present | API Reference

Example Request
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{target}/wallet-service-api/credentials/present' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "requestUrl": "openid4vp://authorize?client_id=...&request_uri=..."
}'

Path Parameters

  • orgID: String (required) - Organization host alias.
  • target: resourceIdentifier (required) - {organizationID}.{tenantID}.{walletServiceID}.

Header Parameters

  • Authorization: String (required) - Bearer token. Format: Bearer {yourToken}.

Body Parameters

  • requestUrl: String (required) - The OID4VP authorization request URL from the verifier. Any other field you send overrides the stored value.
Example Response 200 OK

The response is the same as for any presentation. See Presenting SD-JWT VC Credentials for the fields.

{
  "transmission_success": true,
  "verifier_response": {
    "status": "received",
    "message": "Presentation received and is being processed."
  }
}

Response Codes

  • 200 - Presentation built and submitted.
  • 400 - The request could not be resolved, or the merged request is invalid, for example when the stored keyReference does not exist.
  • 401 / 403 - Authentication or authorization failure.

Override Part of the Default

To sign with a different key for one call, send it. The rest of the default stays:

{
  "requestUrl": "openid4vp://authorize?client_id=...&request_uri=...",
  "keyReference": "waltid.tenant1.wallet1.kms.other_key"
}

Keep Isolated-Flow Steps on the Same Key

In the isolated flow, you preview the request and later build the VP token in separate calls. Both must use the same key. A default on each operation guarantees it.

CURL

Endpoint: PUT /v2/{target}/wallet-service-api/default-requests/wallet2-preview-presentation | API Reference

Example Request
curl -X 'PUT' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{target}/wallet-service-api/default-requests/wallet2-preview-presentation' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "keyReference": "waltid.tenant1.wallet1.kms.wallet_key"
}'

Path Parameters

  • orgID: String (required) - Organization host alias.
  • target: resourceIdentifier (required) - {organizationID}.{tenantID}.{walletServiceID}.

Body Parameters

  • A partial preview request. Store the same keyReference for wallet2-build-vp-token with a second PUT to …/default-requests/wallet2-build-vp-token.
Example Response 200 OK
{
  "keyReference": "waltid.tenant1.wallet1.kms.wallet_key"
}

Response Codes

  • 200 - Default request stored.
  • 400 - The document is not a valid partial body for this operation.
  • 401 / 403 - Authentication or authorization failure.

A preview call with only requestUrl now reports the stored key as the effective keyId in its response.

Good to Know

  • Receive defaults need an offer. wallet2-receive-credential and wallet2-receive-credential-pre-authorized require offerUrl or offerJson when the request is decoded, so a default that only pins the key can't be stored. The PUT currently fails with 500 ("Either offerUrl or offerJson must be provided"). Send keyReference on each receive call, or rely on the wallet's first key and DID.
  • References are checked when you present, not when you store. A default with a key that doesn't exist is accepted with 200. The next presentation then fails with 400 ("No key found at path …"), which looks like an error in that call rather than in the default.
  • The key must be the credential's holder key. A credential is bound to the key it was issued to. A default that points at another key makes the verifier reject the presentation (the key-binding signature check fails).
  • Defaults are not guardrails. Anyone allowed to present can override any stored field in their own call.
  • Each operation has its own default. Presenting, previewing and building a VP token are separate operations, and 24 Wallet2 operations in total accept a default. Store one for each operation you use.
  • Explicit values win, including false over a stored true. Arrays and primitives are replaced wholesale.

Read or Remove a Default

  • List all stored defaults: GET /v2/{target}/wallet-service-api/default-requests (needs view-default-requests).
  • Read one: GET …/default-requests/wallet2-present-credential. Returns 404 if none is stored.
  • Remove one: DELETE …/default-requests/wallet2-present-credential. Returns 204, also when nothing was stored.

Full details, permissions and the other services that support default requests: Default Requests.

Last updated on September 29, 2026