curl --request POST \
--url https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"asset": "USDC",
"network": "base-sepolia",
"max_per_call": "500000",
"max_per_window": "2000000",
"window_seconds": 3600,
"payee_policy": {
"mode": "domain_allowlist",
"domains": [
"*.marketpulse.example"
]
}
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
asset: 'USDC',
network: 'base-sepolia',
max_per_call: '500000',
max_per_window: '2000000',
window_seconds: 3600,
payee_policy: {mode: 'domain_allowlist', domains: ['*.marketpulse.example']}
})
};
fetch('https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates', 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"
payload = {
"asset": "USDC",
"network": "base-sepolia",
"max_per_call": "500000",
"max_per_window": "2000000",
"window_seconds": 3600,
"payee_policy": {
"mode": "domain_allowlist",
"domains": ["*.marketpulse.example"]
}
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates"
payload := strings.NewReader("{\n \"asset\": \"USDC\",\n \"network\": \"base-sepolia\",\n \"max_per_call\": \"500000\",\n \"max_per_window\": \"2000000\",\n \"window_seconds\": 3600,\n \"payee_policy\": {\n \"mode\": \"domain_allowlist\",\n \"domains\": [\n \"*.marketpulse.example\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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",
"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": "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"
}Create an x402 spend mandate (BETA)
Beta — early access.
Creates the standing allowance an agent pays x402-metered resources under. Unlike a payment mandate this authorizes a BUDGET rather than a payee: x402 payees are discovered at request time from a seller’s 402 response, so the controls are a per-call ceiling plus a rolling aggregate across every payee. Amounts are atomic units of the asset (USDC has 6 decimals, so “100000” is $0.10).
curl --request POST \
--url https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--header 'x-idempotency-key: <x-idempotency-key>' \
--data '
{
"asset": "USDC",
"network": "base-sepolia",
"max_per_call": "500000",
"max_per_window": "2000000",
"window_seconds": 3600,
"payee_policy": {
"mode": "domain_allowlist",
"domains": [
"*.marketpulse.example"
]
}
}
'const options = {
method: 'POST',
headers: {
'x-idempotency-key': '<x-idempotency-key>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
asset: 'USDC',
network: 'base-sepolia',
max_per_call: '500000',
max_per_window: '2000000',
window_seconds: 3600,
payee_policy: {mode: 'domain_allowlist', domains: ['*.marketpulse.example']}
})
};
fetch('https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates', 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"
payload = {
"asset": "USDC",
"network": "base-sepolia",
"max_per_call": "500000",
"max_per_window": "2000000",
"window_seconds": 3600,
"payee_policy": {
"mode": "domain_allowlist",
"domains": ["*.marketpulse.example"]
}
}
headers = {
"x-idempotency-key": "<x-idempotency-key>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.platform.dakota.xyz/payment-agents/{payment_agent_id}/x402/mandates"
payload := strings.NewReader("{\n \"asset\": \"USDC\",\n \"network\": \"base-sepolia\",\n \"max_per_call\": \"500000\",\n \"max_per_window\": \"2000000\",\n \"window_seconds\": 3600,\n \"payee_policy\": {\n \"mode\": \"domain_allowlist\",\n \"domains\": [\n \"*.marketpulse.example\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-idempotency-key", "<x-idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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",
"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": "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"
}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.
Path Parameters
Body
Asset symbol. Only USDC is supported in this release; any other value is refused with a 400, since such a mandate could never be used.
Network the mandate covers, e.g. base-sepolia. Only Base and Base Sepolia are supported.
Per-authorization ceiling, in atomic units.
Ceiling on total committed spend across ALL payees in one rolling window, in atomic units. Omit for unbounded (discouraged).
Rolling aggregate window. Defaults to 24h.
Optional cap on authorizations per window. 0 is no cap.
Mandate lifetime from now. Defaults to 30 days.
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
Response
Mandate created
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
Spend already committed in the current window, in atomic units. Counts outstanding holds as well as settled ones.
Authorizations already issued in the current window.
Was this page helpful?

