> For the complete documentation index, see [llms.txt](https://docs.empe.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.empe.io/develop/wallet-server/processing-uris.md).

# Processing URIs

A cloud wallet (a **holder**) interacts with issuers and verifiers by **processing a URI** — the same `openid-credential-offer://`, `openid4vp://`, or `https://` content that a mobile wallet would obtain by scanning a QR code or following a deep link. A single endpoint handles both directions: claiming offered credentials from an issuer (**OpenID4VCI**) and responding to a presentation request from a verifier (**OpenID4VP**). The wallet inspects the URI scheme and runs the matching protocol automatically, so the caller never has to know in advance whether a given QR code is an offer or a request.

This page is the endpoint reference — request and response bodies, options, and errors. For a step-by-step walkthrough of what happens inside each flow, see [Processing Credential Offers and Presentation Requests](/develop/wallet-server/flows-claim-and-presentation.md).

All routes in this section are scoped to one holder under `/holders/:holderId` and require a valid Bearer token with the **admin** role. Ownership is enforced, so a user can only process URIs for holders they own.

A holder is created beforehand via `POST /agent/holder` (see [Holders and Tenancy](/develop/wallet-server/holders-and-tenancy.md)). The `holderId` returned there is the tenant id used in the path below.

## Processing a URI

**POST** `/holders/:holderId/process`

Accepts a URI scanned from a QR code, copied from a deep link, or received directly from an issuer or verifier. The endpoint dispatches on the URI scheme:

* `openid-credential-offer://...` — accepts a **credential offer**. The wallet resolves the offer, requests an access token, requests the offered credential(s), binds them to the holder's DID, and stores them.
* `openid4vp://...` or `https://...` — responds to an **authorization request**. The wallet resolves the request, selects matching credentials, builds the presentation, and submits it.

Any other scheme returns `400 Bad Request` with the message `Unknown URI protocol. Expected openid-credential-offer:// or openid4vp://`.

### Request Body

* **uri** (string, required): the URI to process. Supports both `openid-credential-offer://...` credential offers and `openid4vp://...` (or `https://...`) authorization requests — the same content a mobile wallet would scan.

```
curl -X POST http://localhost:3000/holders/594b464b-20bd-495a-9fb6-87328c759629/process \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{"uri": "openid-credential-offer://?credential_offer_uri=https://issuer.example.com/offers/abc123"}'
```

### Response Body — Credential Offer

When the URI is a credential offer, the wallet claims the offered credential(s) and returns:

```
{
  "status": "success",
  "claimed": 1,
  "ids": ["8f2c1d4e-6a7b-4c9d-90ef-12ab34cd56ef"]
}
```

* **status**: `success` on completion.
* **claimed**: number of credentials stored from the offer.
* **ids**: wallet record identifiers of the newly stored credentials, usable to correlate entries returned by the credential listing endpoints.

For example, processing an `EmployeeBadge@1.0:sd-jwt` offer stores one SD-JWT VC, and the decoded listing then shows its `vct` and selectively disclosable claims such as `employee_id`, `full_name`, and `department`.

### Response Body — Authorization Request

When the URI is an authorization request, the wallet selects the credentials that satisfy the verifier's query and sends the presentation. Selection is automatic — the caller never supplies a credential — and uses **DIF Presentation Exchange v2** or **DCQL**, depending on the query carried by the request. The response is:

```
{
  "status": "success",
  "action": "presentation_sent"
}
```

* **status**: `success` on completion.
* **action**: `presentation_sent`.

```
curl -X POST http://localhost:3000/holders/594b464b-20bd-495a-9fb6-87328c759629/process \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{"uri": "openid4vp://?request_uri=https://verifier.example.com/requests/xyz789"}'
```

## Prerequisites and Errors

* **Credential offers** require the holder to have at least one DID, used to bind the issued credential. If the holder has no DID, the request fails with `400 Bad Request` (`Holder has no DIDs created. Cannot accept credential offer.`). A DID is created when the holder is registered via `POST /agent/holder`.
* **Authorization requests** require the holder to already hold a credential that satisfies the verifier's query. If nothing in the wallet matches the Presentation Exchange definition or DCQL query, the presentation cannot be built.
* An unrecognized URI scheme returns `400 Bad Request` (`Unknown URI protocol. Expected openid-credential-offer:// or openid4vp://`).

## Notes

* The endpoint runs the full protocol synchronously and returns the final result. There is no separate initialize/confirm step and no per-call flow lifecycle to track.
* Isolation between callers comes from holder ownership on the route, not from a per-flow session — only the owner of a holder can process URIs for it.
* The same URI content that this endpoint consumes is exactly what an end user's mobile wallet would scan. Issuers expose offer URIs and PNG QR codes from their credential-offer endpoints, and verifiers expose authorization-request URIs and PNG QR codes from their authorization-request endpoints.
* After processing an offer, inspect what the holder now holds with `GET /holders/:holderId/credentials` (raw) and `GET /holders/:holderId/credentials/decoded` (decoded). See [Credential Management](/develop/wallet-server/credential-management.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.empe.io/develop/wallet-server/processing-uris.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
