> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dakota.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# x402 Budgets & Holds

> How an x402 mandate bounds an agent's spend, and how every signature is tracked until it settles or expires

An x402 seller is discovered at request time: its address arrives in a 402 response, not from a list your customer approved. And the risk is rarely one large payment; it is thousands of small ones adding up. So an x402 mandate authorizes a **budget** rather than a payee: a per-call ceiling, a rolling total across every seller, and a policy on who may be paid.

## The x402 mandate

`POST /payment-agents/{payment_agent_id}/x402/mandates`

| Field                  | Required | Meaning                                                                                                                                                                                                              |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `asset`                | yes      | `USDC`. Any other asset is refused with a `400`.                                                                                                                                                                     |
| `network`              | yes      | `base` or `base-sepolia`                                                                                                                                                                                             |
| `max_per_call`         | yes      | Ceiling on a single payment, in atomic units                                                                                                                                                                         |
| `max_per_window`       | no       | Ceiling on the total committed across **all** sellers in one rolling window, in atomic units. Omit for no aggregate ceiling, which is not recommended: `max_per_call` alone does not bound how often the agent pays. |
| `window_seconds`       | no       | Length of the rolling window. Default 24 hours.                                                                                                                                                                      |
| `max_calls_per_window` | no       | Cap on the number of payments per window. `0` or omitted: no cap.                                                                                                                                                    |
| `valid_for_seconds`    | no       | Mandate lifetime from now. Default 30 days.                                                                                                                                                                          |
| `payee_policy`         | no       | Who may be paid. Default `any_screened`. See [payee policies](#payee-policies).                                                                                                                                      |

Amounts are atomic units: USDC has 6 decimals, so `"1000000"` is \$1.00.

`GET /payment-agents/{payment_agent_id}/x402/mandates` lists the agent's mandates, newest first and paged like the holds list (`limit`, `starting_after`, `ending_before`, answering `data` plus `meta`). Each shows the current window's `window_committed` (atomic units) and `window_calls`.

### Which mandate applies

A signature request is checked against the agent's **newest** mandate that is currently valid and covers the payment's asset and network. Older mandates for the same asset and network are not consulted, and each mandate counts its own window. A new mandate therefore starts with an empty window.

## Payee policies

| `mode`              | Pays                                         | Set                                                 |
| ------------------- | -------------------------------------------- | --------------------------------------------------- |
| `any_screened`      | Any seller that passes address screening     | nothing else                                        |
| `address_allowlist` | Only sellers whose `payTo` address is listed | `addresses`                                         |
| `domain_allowlist`  | Only resources whose host matches a pattern  | `domains`: exact hosts, or `*.example.com` suffixes |

Every payee is screened before anything is signed, whatever the mode — a refused address is a `403` and no budget is held. `any_screened` means screening is the only payee control; the allowlists add to it rather than replacing it. Omit `payee_policy` entirely to get `any_screened`. If you send it, `mode` is required and the list must match it — `addresses` only with `address_allowlist`, `domains` only with `domain_allowlist`, and neither with `any_screened`. Anything else is a `400`, so a policy is never stored looking like a restriction that isn't applied.

`domain_allowlist` is the readable form: a person can approve "any metered API under `marketpulse.example`" in a way they can't approve a hex address. It judges the host of the `resource_url` you send with each signature request, so `resource_url` is required under this policy. When the seller's terms name their `resource`, the two must match.

<Warning>
  x402 **v2** sellers name their resource outside the payment terms, so under `domain_allowlist` Dakota checks the `resource_url` you supply without a second source to compare it against. If you need a limit that doesn't depend on the calling application, use `address_allowlist`.
</Warning>

## Holds

Every signature Dakota issues is recorded as a **hold** before the signature exists. The hold is what the budget counts, and it's the only record of x402 spend: the seller's facilitator moves the money, so there is no Dakota wallet transaction.

```mermaid theme={null}
stateDiagram-v2
    [*] --> outstanding: signature issued
    outstanding --> settled: transfer seen on-chain
    outstanding --> released: expired unused
    settled --> [*]
    released --> [*]
```

| State         | Meaning                                                    | Counts against the budget            |
| ------------- | ---------------------------------------------------------- | ------------------------------------ |
| `outstanding` | Signed, and still settleable by whoever holds it           | yes                                  |
| `settled`     | The transfer happened. `tx_hash` and `settled_at` are set. | yes                                  |
| `released`    | It expired unused and can never settle                     | no: the amount returns to the window |

`outstanding` counts because an issued signature is spendable money whether or not it has reached the chain yet. The budget never assumes a payment didn't happen.

`GET /payment-agents/{payment_agent_id}/x402/holds` lists the agent's holds, **newest first**, in pages: `limit`, `starting_after` and `ending_before`, with the rows in `data` and a `meta` object carrying `total_count`, `has_more_after` and `has_more_before`. Filter with `?state=outstanding`, `settled` or `released`.

Reading holds needs both `ReadMandates` and `ReadTransactions`: they are the only record of what an agent paid over x402.

### How holds resolve

Dakota reads the USDC contract directly rather than waiting to be told:

* **Settled:** usually within about a minute of the seller's facilitator submitting the transfer. The `tx_hash` is the transaction the token contract recorded.
* **Released:** a few minutes after `valid_before`, once a Base block that can no longer be reorganized away (at least two minutes past `valid_before`) shows the authorization still unused. From that point the token refuses it for good.
* **Anything uncertain stays `outstanding`**, and so stays counted, until the chain gives a definite answer.

### How long a signature is valid

`valid_before` is the earliest of:

* the seller's `maxTimeoutSeconds` from now
* **10 minutes** from now
* the mandate's `valid_until`

So no signature outlives the mandate that allowed it.

## Refusals

A refused payment is **never signed**, and it doesn't count against the budget.

| Status | `detail` names                                                                         | Cause                                                                                                                                                                                                                                                         |
| ------ | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `403`  | `exceeds the per-call limit`                                                           | `value` is over `max_per_call`                                                                                                                                                                                                                                |
| `403`  | `over the limit` (the window)                                                          | Committed spend or call count in the window would pass `max_per_window` or `max_calls_per_window`                                                                                                                                                             |
| `403`  | `not on this mandate's allowlist`                                                      | `payTo` isn't in `addresses` (`address_allowlist`)                                                                                                                                                                                                            |
| `403`  | `not on this mandate's domain allowlist`                                               | The resource host doesn't match `domains` (`domain_allowlist`)                                                                                                                                                                                                |
| `403`  | `no usable URL`                                                                        | `domain_allowlist` is set, but the request carried no `resource_url`                                                                                                                                                                                          |
| `403`  | `no active x402 mandate`                                                               | No valid mandate covers this asset and network                                                                                                                                                                                                                |
| `403`  | the supported set                                                                      | The terms name a token other than USDC                                                                                                                                                                                                                        |
| `403`  | `not enabled on this network`                                                          | x402 isn't available on the terms' network in this environment                                                                                                                                                                                                |
| `403`  | frozen                                                                                 | The customer is frozen                                                                                                                                                                                                                                        |
| `400`  | `invalid payment terms`                                                                | Malformed terms: a scheme other than `exact`, an unsupported network or version, a `payTo` that isn't an address, a token `extra.name` / `extra.version` that doesn't match the token, or a `resource_url` that differs from the `resource` the seller priced |
| `404`  | `x402 is not enabled`                                                                  | x402 hasn't been [enabled](/documentation/agentic-payments/x402/quickstart#1-enable-x402-on-the-agent) for the agent. Every x402 route answers this the same way, and the detail names the call that fixes it.                                                |
| `404`  |                                                                                        | Agentic payments aren't enabled for your client, or the agent doesn't exist                                                                                                                                                                                   |
| `409`  | the key was used for a different payment, or its authorization expired or was released | Reuse of an `X-Idempotency-Key`. Use a new key. See [Retrying safely](/documentation/agentic-payments/x402/quickstart#retrying-safely).                                                                                                                       |
| `409`  | already settled                                                                        | The payment under this key already happened, and the detail names the transaction. **Do not retry** — a new key would pay again.                                                                                                                              |
| `503`  | the payee could not be screened                                                        | Nothing was signed and no budget was held. Retry the payment.                                                                                                                                                                                                 |

Every `403` carries the specific reason in `detail`, for example `payment of 700000 exceeds the per-call limit of 500000`.
