curl --request POST \
--url https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>'const options = {
method: 'POST',
headers: {'x-idempotency-key': '<x-idempotency-key>', 'x-api-key': '<api-key>'}
};
fetch('https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel"
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>"
}
response = requests.post(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "2vWxX402Mandate000000000001",
"agent_id": "2vWxAgent000000000000000000",
"wallet_id": "2vWxWallet00000000000000000",
"asset": "USDC",
"network": "base-sepolia",
"max_per_call": "500000",
"max_per_window": "2000000",
"window_seconds": 3600,
"payee_policy": {
"mode": "domain_allowlist",
"domains": [
"*.marketpulse.example"
]
},
"valid_from": "2026-09-08T00:00:00Z",
"valid_until": "2026-10-08T00:00:00Z",
"revoked_at": "2026-09-09T12:00:00Z",
"window_committed": "100000",
"window_calls": 1
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Not Found",
"status": 404,
"detail": "x402 mandate not found"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}Cancel an x402 spend mandate (BETA)
Beta — early access.
Revokes one of the agent’s x402 mandates: from the moment this returns, it authorizes no new payment. A signing request already past its budget check when the cancel landed can still receive its signature, as can a retry of it under the same X-Idempotency-Key; both are the same single payment, committed before the cancel. Any authorization signed under the mandate stays payable by the seller until its valid_before, which is never more than 10 minutes after it was signed, and its hold keeps counting against the budget until it settles or is released. Cancel is idempotent: cancelling a cancelled mandate answers 200 with the mandate unchanged, revoked_at still the time of the first cancel. To change a budget rather than stop it, create a new mandate instead: it replaces this one.
curl --request POST \
--url https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>'const options = {
method: 'POST',
headers: {'x-idempotency-key': '<x-idempotency-key>', 'x-api-key': '<api-key>'}
};
fetch('https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel"
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>"
}
response = requests.post(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates/{mandate_id}/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "2vWxX402Mandate000000000001",
"agent_id": "2vWxAgent000000000000000000",
"wallet_id": "2vWxWallet00000000000000000",
"asset": "USDC",
"network": "base-sepolia",
"max_per_call": "500000",
"max_per_window": "2000000",
"window_seconds": 3600,
"payee_policy": {
"mode": "domain_allowlist",
"domains": [
"*.marketpulse.example"
]
},
"valid_from": "2026-09-08T00:00:00Z",
"valid_until": "2026-10-08T00:00:00Z",
"revoked_at": "2026-09-09T12:00:00Z",
"window_committed": "100000",
"window_calls": 1
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Not Found",
"status": 404,
"detail": "x402 mandate not found"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}{
"type": "https://docs.dakota.xyz/api-reference/errors#not-found",
"title": "Customer Not Found",
"status": 404,
"detail": "Customer cst_2abc123 was not found in your organization.",
"instance": "https://api.platform.dakota.xyz/customers/cst_2abc123",
"request_id": "req_7f3a8b2c"
}Authorizations
Headers
Unique key to ensure request idempotency. If the same key is used within a certain time window, the original response will be returned instead of executing the request again.
Response
The mandate, cancelled
What an x402 mandate may pay for, beyond its budget. Omit the whole object to leave the budget as the only control.
mode is required when the object is present, and the list must match it: address_allowlist needs addresses and reads no domains, domain_allowlist needs domains and reads no addresses, and any_screened enforces neither, so it carries no list. A policy that breaks those rules is refused with a 400 rather than stored as a restriction nothing applies.
any_screened accepts any payee that passes address screening. address_allowlist pins the payee address itself. domain_allowlist pins the RESOURCE host the caller names when it asks for a signature - the readable form, since an operator approves "any metered API under this vendor's domain" rather than a hex address. Note that it bounds the resource, not the payee: a seller who prices one resource can be paid for it whatever address it nominates.
Show child attributes
Show child attributes
When the mandate was cancelled, or replaced by a newer mandate for the same asset and network. A revoked mandate authorizes nothing.
Spend already committed on this mandate's budget in the window ending now, in atomic units: every authorization from the agent's x402 wallet in this asset and network over this mandate's window_seconds, whichever mandate issued it, counting outstanding holds as well as settled ones. It is the budget's figure, not this mandate's own: a replaced or cancelled mandate shows the same spend as the mandate in force, so never add it up across mandates.
Authorizations already issued in the current window, counted the same way as window_committed.
Was this page helpful?

