> 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/api/web-wallet-api/ap2.md).

# Ap2

\[Experimental]

## \[Experimental] Close an imported AP2 mandate into signed Closed Mandate artifacts

> Given a credential ID from a successful import and concrete closed-mandate content for every mandate the grant carries, produces one signed artifact covering all of them.&#x20;

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Web Custodial Wallet Documentation","version":"0.1.2"},"tags":[{"name":"Ap2","description":"[Experimental]"}],"security":[{"user":[]},{"agent":[]},{"user":[]}],"components":{"securitySchemes":{"user":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Holder user. `users` realm token with `principal_type=user`. Authorize one bearer scheme at a time."},"agent":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Holder's AI agent. `users` realm token with `principal_type=agent`. Authorize one bearer scheme at a time."}},"schemas":{"SignAp2CredentialRequest":{"type":"object","properties":{"mandates":{"type":"array","description":"Closed-mandate content for every mandate the addressed grant carries, closed together in one signed artifact.","items":{"oneOf":[{"$ref":"#/components/schemas/Ap2CheckoutMandate"},{"$ref":"#/components/schemas/Ap2PaymentMandate"}]}},"aud":{"type":"string","description":"Audience the closed artifact is bound to."}},"required":["mandates","aud"]},"Ap2CheckoutMandate":{"type":"object","properties":{"vct":{"enum":["mandate.checkout.1"],"type":"string","description":"Discriminator value for this mandate."},"exp":{"type":"number","minimum":0,"description":"Unix epoch. Defaults to iat + the configured mandate TTL when omitted."},"checkout_jwt":{"type":"string","description":"The signed checkout JWT the human approved."},"checkout_hash":{"type":"string","description":"Hash of the checkout content, referenced by a paired closed Payment Mandate's transaction_id."}},"required":["vct","checkout_jwt","checkout_hash"]},"Ap2PaymentMandate":{"type":"object","properties":{"vct":{"enum":["mandate.payment.1"],"type":"string","description":"Discriminator value for this mandate."},"exp":{"type":"number","minimum":0,"description":"Unix epoch. Defaults to iat + the configured mandate TTL when omitted."},"transaction_id":{"type":"string","description":"Must equal the paired closed Checkout Mandate's checkout_hash."},"payee":{"description":"The payee for this payment.","allOf":[{"$ref":"#/components/schemas/Ap2Merchant"}]},"payment_amount":{"description":"The payment amount.","allOf":[{"$ref":"#/components/schemas/Ap2Amount"}]},"payment_instrument":{"description":"The payment instrument used.","allOf":[{"$ref":"#/components/schemas/Ap2PaymentInstrument"}]},"pisp":{"description":"The Payment Initiation Service Provider used, if any.","allOf":[{"$ref":"#/components/schemas/Ap2Pisp"}]},"execution_date":{"type":"string","description":"The date the payment is expected to execute."},"risk_data":{"type":"object","additionalProperties":true,"description":"Opaque risk-assessment data supplied by the agent."}},"required":["vct","transaction_id","payee","payment_amount","payment_instrument"]},"Ap2Merchant":{"type":"object","properties":{"id":{"type":"string","description":"Merchant identifier."},"name":{"type":"string","description":"Merchant display name."},"website":{"type":"string","format":"uri","description":"Merchant website URL."}},"required":["id","name"]},"Ap2Amount":{"type":"object","properties":{"amount":{"type":"number","minimum":0,"description":"Amount in minor units per ISO 4217"},"currency":{"type":"string","description":"ISO 4217 currency code."}},"required":["amount","currency"]},"Ap2PaymentInstrument":{"type":"object","properties":{"id":{"type":"string","description":"Payment instrument identifier."},"type":{"type":"string","description":"Payment instrument type, e.g. card, bank_account."},"description":{"type":"string","description":"Human-readable description of the payment instrument."}},"required":["id","type"]},"Ap2Pisp":{"type":"object","properties":{"legal_name":{"type":"string","description":"The Payment Initiation Service Provider's registered legal name."},"brand_name":{"type":"string","description":"The PISP's consumer-facing brand name."},"domain_name":{"type":"string","description":"The PISP's domain name."}},"required":["legal_name","brand_name","domain_name"]},"SignAp2CredentialResponse":{"type":"object","properties":{"closedAt":{"type":"string","description":"Timestamp the mandates were closed at."},"vcts":{"description":"vct of every mandate closed by this call.","type":"array","items":{"type":"string"}},"credential":{"type":"string","description":"The signed dSD-JWT grant covering every closed mandate — a grant, not a KB-JWT presentation; nothing in this repo verifies or forwards it."}},"required":["closedAt","vcts","credential"]}}},"paths":{"/api/v1/ap2/credentials/{id}/close":{"post":{"description":"Given a credential ID from a successful import and concrete closed-mandate content for every mandate the grant carries, produces one signed artifact covering all of them. ","operationId":"Ap2Controller_closeCredential_api/v1","parameters":[{"name":"id","required":true,"in":"path","description":"Credential unique ID a prior verify-and-import call returned.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignAp2CredentialRequest"}}}},"responses":{"200":{"description":"When every mandate the imported grant carries is closed together into one signed dSD-JWT artifact. Repeatable — closing again produces a fresh artifact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignAp2CredentialResponse"}}}},"400":{"description":"When mandate content fails shape validation, includes a caller-supplied iat, a Checkout/Payment pair is inconsistent, the supplied mandates do not exactly match what the grant carries, or the grant has at least one expired mandate."},"404":{"description":"When the credential ID does not resolve to any grant reachable by the caller."}},"summary":"[Experimental] Close an imported AP2 mandate into signed Closed Mandate artifacts","tags":["Ap2"]}}}}
```

## \[Experimental] Create an AP2 mandate request for the agent's tenant

> Creates an AP2 mandate request on GA Integration under a caller-supplied tenant, on behalf of an authenticated AI agent. Returns the requestUri and txId the caller needs to put the request in front of a human delegator on any wallet — what that wallet retains afterward is that wallet's own concern.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Web Custodial Wallet Documentation","version":"0.1.2"},"tags":[{"name":"Ap2","description":"[Experimental]"}],"security":[{"user":[]},{"agent":[]},{"user":[]}],"components":{"securitySchemes":{"user":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Holder user. `users` realm token with `principal_type=user`. Authorize one bearer scheme at a time."},"agent":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Holder's AI agent. `users` realm token with `principal_type=agent`. Authorize one bearer scheme at a time."}},"schemas":{"CreateMandateRequestRequest":{"type":"object","properties":{"verifierId":{"type":"string","description":"Verifier unique ID"},"tenantId":{"type":"string","description":"Tenant unique ID"},"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"]},"vpSchemaId":{"type":"string","description":"VP Schema unique ID, used to build the DCQL query."},"mandates":{"description":"One or more AP2 mandates. All mandates must be Open, or all must be Closed — mixing is not supported.","type":"array","items":{"$ref":"#/components/schemas/Ap2BaseMandate"}},"kid":{"type":"string","description":"Reference to an existing key in the calling agent's own Askar vault (askar#<rawKid>), reused as agentKey for an Open mandate. Omit to mint a fresh, one-off key instead. Only accepted when the request contains an Open mandate."},"redirectUri":{"type":"string","description":"Same-device redirect target after the delegating wallet responds."},"verifierWebUrl":{"type":"string","description":"Web hand-off / QR surface the delegating human lands on."},"expectedOrigins":{"description":"Expected origins for a Digital Credentials API (DC API) response mode.","type":"array","items":{"type":"string"}}},"required":["verifierId","tenantId","mode","vpSchemaId","mandates"]},"Ap2BaseMandate":{"type":"object","properties":{"vct":{"enum":["mandate.checkout.open.1","mandate.checkout.1","mandate.payment.open.1","mandate.payment.1"],"type":"string","description":"Mandate type discriminator (the verifiable credential type)."},"exp":{"type":"number","minimum":0,"description":"Unix epoch. Defaults to iat + the configured mandate TTL when omitted."}},"required":["vct"]},"CreateMandateRequestResponse":{"type":"object","properties":{"requestUri":{"type":"string","description":"The OID4VP request URI to render as a QR code or embed in a deep link for the delegating human."},"txId":{"type":"string","description":"Transaction unique ID, correlating the eventual verification call."},"kid":{"type":"string","description":"The Askar vault key reference used to build agentKey — the caller-supplied value, or the one freshly minted. Present only when an Open mandate was in the request. Capture this to reference the same key on a later call; note that it is only reachable via the same authentication path (direct agent token vs. user-acting-as-agent) used on this call."}},"required":["requestUri","txId"]}}},"paths":{"/api/v1/ap2/requests":{"post":{"description":"Creates an AP2 mandate request on GA Integration under a caller-supplied tenant, on behalf of an authenticated AI agent. Returns the requestUri and txId the caller needs to put the request in front of a human delegator on any wallet — what that wallet retains afterward is that wallet's own concern.","operationId":"Ap2Controller_createMandateRequest_api/v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMandateRequestRequest"}}}},"responses":{"200":{"description":"When the AP2 mandate request is created successfully. Renders the requestUri as a QR code or deep link to put the request in front of the delegating human on any wallet; txId correlates the eventual verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMandateRequestResponse"}}}},"400":{"description":"When tenantId is missing or malformed, agentKey is supplied directly, kid is malformed or supplied on a request with no Open mandate, or GA Integration rejects the request (invalid mandate content, nonexistent tenantId, unknown VP Schema, etc)."},"404":{"description":"When kid does not resolve within the calling agent's own Askar vault."},"502":{"description":"When GA Integration is unreachable, returns a server error, or rejects the service-to-service credentials this API presents to it."}},"summary":"[Experimental] Create an AP2 mandate request for the agent's tenant","tags":["Ap2"]}}}}
```

## \[Experimental] Verify and import an approved AP2 mandate request

> Given a txCode relayed by the delegating human out of band, verifies the wallet response on the caller's behalf and imports the resulting delegation grant into a dedicated Askar profile, isolated from the credential API and OID4VP matching.

```json
{"openapi":"3.0.0","info":{"title":"EqusDTK Web Custodial Wallet Documentation","version":"0.1.2"},"tags":[{"name":"Ap2","description":"[Experimental]"}],"security":[{"user":[]},{"agent":[]},{"user":[]}],"components":{"securitySchemes":{"user":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Holder user. `users` realm token with `principal_type=user`. Authorize one bearer scheme at a time."},"agent":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Holder's AI agent. `users` realm token with `principal_type=agent`. Authorize one bearer scheme at a time."}},"schemas":{"VerifyMandateRequestRequest":{"type":"object","properties":{"verifierId":{"type":"string","description":"Verifier unique ID"},"tenantId":{"type":"string","description":"Tenant unique ID"},"kid":{"type":"string","description":"Reference to a key in the calling agent's own Askar vault (askar#<rawKid>), reused to sign every future close of the imported grant. Must already exist — this call never mints one."},"txCode":{"type":"string","description":"One-time code relayed by the delegating human, out of band. Exactly one of txCode, responseCode or authResponse may be supplied."},"responseCode":{"type":"string","description":"Code identifying the verification session, alternative to txCode."},"authResponse":{"description":"Authorization response the caller already holds, for a wallet that fetches it itself (Embed UI). Supplying it skips the code-based lookup on GA Integration; txCode and responseCode are then neither needed nor accepted.","allOf":[{"$ref":"#/components/schemas/Ap2AuthResponse"}]},"origin":{"type":"string","description":"Origin the wallet submitted the presentation from. Verified as the audience for a DC API request; ignored otherwise."}},"required":["verifierId","tenantId","kid"]},"Ap2AuthResponse":{"type":"object","properties":{"vpToken":{"type":"object","description":"Plain verifiable presentation token. Mutually exclusive with jwe."},"jwe":{"type":"string","description":"Encrypted JWE containing the authorization response. Mutually exclusive with vpToken."},"transactionDataResponse":{"type":"object","description":"Hashes of the transaction data items the wallet signed over. An AP2 mandate rides in transaction data, so a response that omits these cannot be verified as a delegation."},"type":{"type":"number","description":"Indicates whether the authorization response is plain or encrypted."}},"required":["type"]},"VerifyMandateRequestResponse":{"type":"object","properties":{"credentialId":{"type":"string","description":"Identifies the imported grant for a later close call."}},"required":["credentialId"]}}},"paths":{"/api/v1/ap2/requests/{txId}/verify":{"post":{"description":"Given a txCode relayed by the delegating human out of band, verifies the wallet response on the caller's behalf and imports the resulting delegation grant into a dedicated Askar profile, isolated from the credential API and OID4VP matching.","operationId":"Ap2Controller_verifyAndImportMandate_api/v1","parameters":[{"name":"txId","required":true,"in":"path","description":"Transaction unique ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMandateRequestRequest"}}}},"responses":{"200":{"description":"When the human-approved mandate request is verified and its delegation grant is imported into a dedicated Askar profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMandateRequestResponse"}}}},"400":{"description":"When kid is malformed, more than one of txCode/responseCode/authResponse is supplied or none is, the verification session is not accepted (never reached it, or already imported), the txCode does not match, has expired, or was already used, or the verified presentation carries no AP2 mandate."},"404":{"description":"When kid does not resolve within the calling agent's own Askar vault."},"502":{"description":"When GA Integration is unreachable, returns a server error, or rejects the service-to-service credentials this API presents to it."}},"summary":"[Experimental] Verify and import an approved AP2 mandate request","tags":["Ap2"]}}}}
```


---

# 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/api/web-wallet-api/ap2.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.
