Custom Flow
The full-flow endpoint matches and submits a presentation in a single call. When you're building a wallet UI and need to show the user what will be shared, let them choose between matching credentials, or present a credential that isn't stored in the wallet, drive the isolated endpoints shown on this page yourself.
All endpoints on this page are rooted at /wallet/{walletId}/credentials/present. The examples use http://localhost:7005 as the base URL.
When to Use the Isolated Flow
| You want to… | Use |
|---|---|
| Present in one call | Full flow |
| Read what the verifier is asking for | Resolve the request |
| Get the verifier's DCQL query | Where the DCQL query comes from |
| Show a consent preview of what matches | Match from the wallet stores |
| Present a credential not held by the wallet | Present inline credentials |
Resolve the Request
Parse the verifier's authorization request to read who is asking and what they want.
Endpoint: POST /wallet/{walletId}/credentials/present/resolve-request | API Reference
Example Request
curl -X POST http://localhost:7005/wallet/{walletId}/credentials/present/resolve-request \
-H 'Content-Type: application/json' \
-d '{
"requestUrl": "openid4vp://authorize?client_id=x509_san_dns%3Averifier.example.org&request_uri=http%3A%2F%2Flocalhost%3A7004%2Fopenid4vc%2Frequest%2Fabc123"
}'
Path Parameters
- walletId: String (required) - The wallet handling the presentation. See how to obtain it.
Body Parameters
- Presentation request (required) — provide exactly one of:
- requestUrl: String - The OID4VP authorization request URL.
- requestObject: Object - A pre-fetched authorization request as an inline JSON object.
Example Response
{
"nonce": "n-0S6_WzA2Mj",
"clientId": "x509_san_dns:verifier.example.org",
"responseUri": "http://localhost:7004/openid4vc/response",
"hasRequestUri": true
}
Response Fields
- nonce: String - The verifier's nonce, which the presentation must be bound to.
- clientId: String - The verifier's client identifier.
- responseUri: String - Where the presentation will be submitted.
- hasRequestUri: Boolean - Whether the request was fetched from a
request_uri(vs supplied inline).
resolve-request returns the request's metadata but not the DCQL query itself. To match credentials in the next step you need the query — see Where the DCQL Query Comes From below.
Where the DCQL Query Comes From
The next step matches credentials against a DCQL query — the machine-readable statement of what the verifier wants. The DCQL query travels inside the verifier's authorization request as the dcql_query parameter, and the wallet reads it out of that request.
Given only the openid4vp:// request URL, extract the query from the request object:
- Inline request — the query is the
dcql_queryparameter in the URL itself. Read it directly from the query string. request_urirequest (the common case) — the URL carries arequest_uripointing to the request object rather than the query. Fetch that URL and read thedcql_queryclaim out of what it returns.- By default, Verifier2 returns a plain JSON object (
Content-Type: application/json) — readdcql_querydirectly from it. This is what you get unless the verification session was created withsigned_request: true. - If the session set
signed_request: true, the request object is instead a signed JWT (Content-Type: application/oauth-authz-req+jwt, fetched viaPOST) —dcql_queryis in its payload, so decode the JWT payload to read it.
- By default, Verifier2 returns a plain JSON object (
The wallet has no endpoint that hands you the query directly — resolve-request deliberately returns only the request metadata (nonce, client, response URI), so you extract dcql_query from the request object yourself as above.
Match from the Wallet Stores
Run the verifier's DCQL query (obtained above) against the wallet's stored credentials to see what would satisfy it — without submitting anything. This is the call to enable a consent preview: show the user which credentials match before they approve.
Endpoint: POST /wallet/{walletId}/credentials/present/match-credentials-from-store | API Reference
Example Request
curl -X POST http://localhost:7005/wallet/{walletId}/credentials/present/match-credentials-from-store \
-H 'Content-Type: application/json' \
-d '{
"dcqlQuery": {
"credentials": [
{
"id": "identity_credential",
"format": "dc+sd-jwt",
"meta": { "vct_values": ["https://issuer.example.com/identity_credential"] },
"claims": [
{ "path": ["given_name"] },
{ "path": ["family_name"] }
]
}
]
}
}'
Path Parameters
- walletId: String (required) - The wallet whose stored credentials are matched.
Body Parameters
- dcqlQuery: Object (required) - The verifier's DCQL query — see Where the DCQL Query Comes From for how to obtain it, and DCQL query format for its structure.
Example Response
{
"matchedQueryIds": ["credential_1"],
"matchCount": 2,
"matchedCredentialIds": {
"credential_1": ["0", "1"]
}
}
Response Fields
- matchedQueryIds: String - The DCQL credential-query IDs that were satisfied.
- matchCount: Number - Total number of matching credentials.
- matchedCredentialIds: Object - Map of query ID → identifiers of the matching credentials.
The values in matchedCredentialIds are currently the credential's positional index within the wallet's credential stores ("0", "1", …), not the stored credential ID returned by GET /wallet/{walletId}/credentials. They can't yet be correlated back to a specific stored credential. (The inline Match Inline Credentials endpoint does echo back the id you supply.)
After the user consents, complete the presentation with the full-flow endpoint.
Match Inline Credentials
Run a DCQL query against credentials you supply in the request, rather than the wallet's credential stores. Useful for testing a query, or matching credentials held outside the wallet.
Endpoint: POST /wallet/{walletId}/credentials/present/match-credentials | API Reference
Example Request
curl -X POST http://localhost:7005/wallet/{walletId}/credentials/present/match-credentials \
-H 'Content-Type: application/json' \
-d '{
"dcqlQuery": { "credentials": [ { "id": "credential_1", "format": "dc+sd-jwt", "meta": { "vct_values": ["https://issuer.example.com/identity_credential"] }, "claims": [ { "path": ["given_name"] } ] } ] },
"credentials": [
{ "id": "inline-1", "credential": { "type": "vc-sd_jwt", "format": "dc+sd-jwt", "signed": "eyJ...~WyJ...~", "credentialData": { "vct": "https://issuer.example.com/identity_credential", "given_name": "John" } } }
]
}'
Body Parameters
- dcqlQuery: Object (required) - The DCQL query to match against.
- credentials: Array (required) - The credentials to match. Each entry has an
id(your own label, echoed back in the result) and acredential: the credential in the wallet's own JSON representation — not a raw credential string. Itstypefield marks the format (vc-sd_jwt,vc-w3c_2, ormso_mdoc) and the rest of the object holds the credential data (as in the example above). The simplest way to get one in the right shape is to copy thecredentialobject from aGET /wallet/{walletId}/credentials/{id}response.
Example Response
Returns the same MatchCredentialsResult shape as Match from the wallet stores.
Present Inline Credentials
Present a credential that isn't stored in the wallet — you supply it directly in the request. The wallet resolves the request, builds and signs the presentation from the inline credential, and submits it.
Endpoint: POST /wallet/{walletId}/credentials/present/isolated | API Reference
Example Request
curl -X POST http://localhost:7005/wallet/{walletId}/credentials/present/isolated \
-H 'Content-Type: application/json' \
-d '{
"requestUrl": "openid4vp://authorize?client_id=verifier2&request_uri=http%3A%2F%2Flocalhost%3A7003%2Fverification-session%2Fabc123%2Frequest",
"credentials": [
{ "id": "inline-1", "credential": { "type": "vc-sd_jwt", "format": "dc+sd-jwt", "signed": "eyJ...~WyJ...~", "credentialData": { "vct": "https://issuer.example.com/identity_credential", "given_name": "John" } } }
],
"keyId": "my-holder-key"
}'
Body Parameters
- Presentation request (required) — provide exactly one of:
- requestUrl: String - The OID4VP authorization request URL.
- requestObject: Object - A pre-fetched authorization request as an inline JSON object.
- credentials: Array (required) - The credentials to present. Each entry has an
idand acredential: the credential in the wallet's own JSON representation (the same shape as in Match Inline Credentials above), not a raw credential string. The simplest way to get one is to copy thecredentialobject from aGET /wallet/{walletId}/credentials/{id}response. - keyId: String (optional) - Key used to sign the presentation. Must be the holder key the inline credential is bound to. Defaults to the wallet's default key.
- did: String (optional) - DID for the presenter identity. Defaults to the wallet's default DID.
Example Response
Returns the same shape as the full presentation flow — transmission_success, verifier_response, and optionally redirect_to.
Endpoint Reference
| Endpoint | Method | Description |
|---|---|---|
/wallet/{walletId}/credentials/present | POST | Full presentation flow (match from stores, sign, submit) |
/wallet/{walletId}/credentials/present/isolated | POST | Present inline credentials |
/wallet/{walletId}/credentials/present/resolve-request | POST | Parse a VP authorization request |
/wallet/{walletId}/credentials/present/match-credentials-from-store | POST | DCQL-match the wallet's stored credentials |
/wallet/{walletId}/credentials/present/match-credentials | POST | DCQL-match inline credentials |
