> For the complete documentation index, see [llms.txt](https://docs.toolkit.equs.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.toolkit.equs.ai/standards/agentic/delegation.md).

# Delegation

How a Holder grants an AI agent, or any other party, bounded and verifiable authority on top of a credential they already hold.

A credential says something is true about its Holder. Delegation lets that Holder go further and say *this other party may act on it, within these limits*, and prove it later, cryptographically, to whoever needs convincing.

The party being authorized is usually software. An AI agent that shops, books or pays on someone's behalf has to be able to show a merchant that the person really did approve this, within bounds they really did set, at a moment when that person is nowhere near the transaction. Delegation is how the approval survives the gap between the two.

The mechanism is **dSD-JWT**, a delegated SD-JWT. The Holder takes a credential they already have and adds a signed statement to it, saying what they are authorizing and for whom. That statement is called a **hop**, because authority moves one step along: from the Issuer who vouched for the Holder, to the Holder, to whoever they hand it to next.

```mermaid
flowchart LR
    I["Issuer signs<br/>the credential"] --> H["Holder adds a bound hop<br/>naming the agent's key"]
    H --> A["Agent adds<br/>a terminal hop"]
    A --> V["Verifier checks every<br/>signature back to the Issuer"]
    style H fill:#e8f0fe,stroke:#4285f4,color:#1a1a1a
    style A fill:#fff4e5,stroke:#f9ab00,color:#1a1a1a
    style V fill:#e6f4ea,stroke:#34a853,color:#1a1a1a
```

The result is still one compact credential, and because each hop is signed by the party that held it, the chain traces back to the Issuer's original signature. Whoever checks it at the end can see every step, and that no one added authority they weren't given.

**The Issuer isn't involved.** No reissuance, no new credential type, no call back to whoever issued the root credential. Delegation is something the Holder does with a credential they hold, which is what makes it useful for authority granted long after issuance and on terms the Issuer never anticipated.

### Two kinds of hop 🔗

There's one structural choice to make, and it's whether authority continues past this point.

**A bound hop passes authority on.** It names the party being authorized, and from then on only they can use it, including to add a hop of their own when the time comes. This is what an agent needs in order to act later, on its own, while the person who authorized it is elsewhere.

**A terminal hop ends the chain.** No party is named, the claims are simply attested to whoever verifies them, and nothing travels further. This is the shape for authority that's already been exercised: the human decided, signed, and there's nothing left to delegate.

| Feature                      | Bound hop                                   | Terminal hop    |
| ---------------------------- | ------------------------------------------- | --------------- |
| **Format**                   | `dSD-JWT+KB`                                | `dSD-JWT`       |
| **Names a delegate**         | Yes: the hop carries their public key       | No              |
| **Who can add the next hop** | Only whoever holds the matching private key | No one          |
| **In AP2**                   | Open mandates                               | Closed mandates |

### Alternative payloads 🔀

A hop can carry several alternative payloads over the same credential. The Holder signs them all at once, and each is **selectively disclosable**: when the credential is presented later, exactly one is revealed. That is how a single approval can cover options that exclude each other, and give away only the one that turned out to apply.

### Requesting a delegation 📨

A delegation rides inside an ordinary presentation, as OID4VP **transaction data**: you ask for a credential and, in the same request, for the Holder to sign a hop over it. There's no separate protocol or endpoint: delegation items are an optional `transactionData` array on the usual request call.

{% hint style="info" icon="rectangle-api" %}
All calls mentioned on this page are on the [Integration API](https://docs.toolkit.equs.ai/standards/agentic/pages/MvAvsnLQU3ER2hOIIDU2#id-2.4.1-apis).
{% endhint %}

## Create Authorization Request

> Create Authorization Request by Verifier based on VP Schema

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Integration API Documentation","version":"0.1.2"},"tags":[{"name":"Oid4Vp","description":""}],"security":[{"sp":[]},{"tenant":[]},{"sp":[]}],"components":{"securitySchemes":{"sp":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Service Provider. Token of the Service Provider client in the `agents` realm, with no `tenantId` claim. Authorize one bearer scheme at a time."},"tenant":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant. Token of a Tenant machine client or of a Tenant portal user, carrying the `tenantId` claim. Authorize one bearer scheme at a time."}},"schemas":{"CreateAuthorizationRequestRequest":{"type":"object","properties":{"mode":{"type":"string","description":"Mechanism used by the wallet to deliver the authorization response. Only encrypted modes are supported.","enum":["direct_post.jwt","dc_api.jwt"]},"type":{"type":"string","description":"Type of authorization response requested from the wallet.","enum":["vp_token","vp_token id_token"]},"redirectUri":{"type":"string","description":"URL the wallet redirects the holder to after submitting the response."},"expectedOrigins":{"description":"Web origins (http or https) allowed to complete a DC API presentation for this request. Each value is reduced to its origin: scheme, host and non-default port.","type":"array","items":{"type":"string"}},"vpSchemaId":{"type":"string","description":"VP schema unique ID"},"verifierWebUrl":{"type":"string","description":"URL of the verifier web page that will display the presentation request."},"transactionData":{"description":"Transaction data items the wallet must sign over as part of the response.","type":"array","items":{"$ref":"#/components/schemas/DelegateTransactionDataItem"}},"intendedUseId":{"type":"string","description":"Intended use to create this request under. Required once the Verifier has registered one; its registration certificate is emitted to the Wallet as a `verifier_info` entry."}},"required":["mode","type","vpSchemaId"]},"DelegateTransactionDataItem":{"type":"object","properties":{"type":{"type":"string","description":"Type of transaction data item.","enum":["delegate"]},"credentialInputIndex":{"type":"number","description":"Index of the credential input this transaction data item applies to."},"format":{"type":"string","description":"Delegated SD-JWT format the disclosed payload claims are issued in.","enum":["dSD-JWT","dSD-JWT+KB"]},"delegateJwk":{"type":"object","description":"JWK of the delegate key that the disclosed payload claims are bound to."},"payloadClaims":{"type":"object","description":"Claims disclosed to the verifier via the delegated presentation."}},"required":["type","credentialInputIndex","format","payloadClaims"]},"CreateAuthorizationRequestResponse":{"type":"object","properties":{"requestUri":{"type":"string","description":"URI from which the wallet can fetch the full authorization request object."},"txId":{"type":"string","description":"Transaction unique ID"}},"required":["requestUri","txId"]}}},"paths":{"/api/v1/{verifierId}/oid4vp/requests":{"post":{"description":"Create Authorization Request by Verifier based on VP Schema","operationId":"Oid4VpController_createAuthorizationRequest_api/v1","parameters":[{"name":"verifierId","required":true,"in":"path","description":"Verifier unique ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAuthorizationRequestRequest"}}}},"responses":{"200":{"description":"When Authorization Request is created successfully. The uri for the authorization request and corresponding txId is returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAuthorizationRequestResponse"}}}},"400":{"description":"When the Verifier uses x509_san_dns and the response URI FQDN does not match its Client Identifier."},"404":{"description":"- When no VP Schema exists with such id.\n- When no verifier found."},"422":{"description":"- When the Verifier uses an x509 Client Identifier Prefix and no access certificate is active.\n- When the active access certificate has been revoked, is expired or not yet valid, or carries no dNSName SAN naming the protocol host.\n- When the SDK refuses the x509 Client Identifier, because the certificate chain, the identifier and the signing key do not agree."}},"summary":"Create Authorization Request","tags":["Oid4Vp"]}}}}
```

`transactionData` takes 1 to 10 items, each with these fields:

| Field                  | Notes                                                                                                                                                                                          |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`                 | `delegate` (the only type)                                                                                                                                                                     |
| `credentialInputIndex` | Which credential input of your [VP Schema](/standards/presentation/configuration.md) the hop goes on, counting from zero. Items on the same input are alternatives                             |
| `format`               | `dSD-JWT+KB` for a bound hop, `dSD-JWT` for a terminal one                                                                                                                                     |
| `delegateJwk`          | The delegate's public key. Required on every item of an input if any item on it is a bound hop                                                                                                 |
| `payloadClaims`        | What is being authorized. Free-form: its meaning is yours to define. Two names are reserved for the platform: `cnf`, where the delegate's key goes, and `_sd`, which selective disclosure uses |

```json
"transactionData": [
  {
    "type": "delegate",
    "credentialInputIndex": 0,
    "format": "dSD-JWT+KB",
    "delegateJwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…", "alg": "ES256" },
    "payloadClaims": { "scope": "…", "exp": 1772236800 }
  }
]
```

{% hint style="info" %}
**For payments, use AP2.** The [Agentic Payments (AP2)](/standards/agentic/ap2.md) feature builds these items for you from a description of the mandate, and validates them before anything reaches the wallet.
{% endhint %}

### What the wallet does 📱

Nothing special, and that's the point. The EQUS Wallet shows the delegated claims in its ordinary consent screen, and when the Holder approves, it signs the hop along with the presentation. A third-party wallet can take part if it supports OID4VP transaction data, including `delegate` items.

### Collecting and verifying ✅

The same calls as any other presentation - see [Build Your Own UI](/standards/presentation/flows-1-and-2/build-your-own-ui.md) under Presentation. Verification checks the delegation chain along with the credential, and the result's `transactionDataResponse` reports what the Holder actually signed.

### Holding and extending a delegation ⛓️

A bound hop names a key, so its delegate can store the credential and act on it later, long after the Holder has stopped looking. Adding the next hop is a signature over the stored credential, with the key the bound hop named. One hop can carry several payloads, and the result is still one compact credential.

{% hint style="warning" %}
**Whoever relies on the final credential has to check every hop.** The format doesn't stop a hop from claiming more than the one before it: a widened or unrelated payload still carries valid signatures all the way back to the Issuer. The platform verifies those signatures and the chain, but it doesn't interpret `payloadClaims`, so it can't tell whether a hop stays within the one before. Only a verifier that understands the claims can. A delegate should check too before it signs, so it doesn't produce something that gets rejected.
{% endhint %}

### Errors 🚨

A request with invalid delegation items is rejected with `400` and one of these codes:

| Error                            | Meaning                                                                                                |
| -------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `unknown_credential_input_index` | `credentialInputIndex` names an input your VP Schema doesn't have                                      |
| `delegate_jwk_required`          | An item has no `delegateJwk`, but its input carries a bound hop                                        |
| `reserved_payload_claim`         | `payloadClaims` uses a reserved name, `cnf` or `_sd`. Pass the delegate's key as `delegateJwk` instead |
| `delegate_build_failed`          | The delegation items couldn't be built                                                                 |

### How AP2 uses delegation 💳

[AP2](/standards/agentic/ap2.md) is the first feature built on delegation, and shows the split well: delegation supplies the mechanism, AP2 supplies the meaning.

| Delegation provides                 | AP2 adds                                                                                             |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------- |
| A signed hop with free-form claims  | A mandate vocabulary: `vct` types, spending constraints, line items, payees                          |
| Bound and terminal hops             | Open mandates for *human not present*, Closed mandates for *human present*                           |
| A delegate key named in a bound hop | The AI agent's key - generated and held for it, if the platform hosts the agent                      |
| No rules on what a hop may claim    | Rules for what a Closed mandate may claim - inside the Open bounds, with checkout and payment linked |

Nothing about delegation is payment-specific. Any case that needs *this Holder authorizes that party to do a bounded thing later* (scoped machine access, deferred approvals, mandated actions) can define its own `payloadClaims` over the same mechanism.


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.toolkit.equs.ai/standards/agentic/delegation.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
