# Approval flow

Approval is the control that turns an agent's intent into a bounded human decision. The threshold
is stored on the agent and on the partner account. Threshold enforcement is **Current**: an order above the threshold returns `approval_required` and
no order or debit is created. The approval exchange is **Planned**: no approval endpoint is live today.

This page separates the target contract from the interim pattern so no integration assumes a
control that is not active.

## Target flow

```text
agent prices order
    │
    ├── total < threshold ──> order proceeds normally
    │
    └── total >= threshold
            │
            ├── API returns approval_required + approval URL
            ├── agent stops and surfaces the URL to the principal
            ├── principal approves, rejects or lets it expire
            ├── approval is bound to amount, currency, reference and expiry
            └── agent resumes with a single-use approval reference
```

| State | Meaning |
| --- | --- |
| `not_required` | Total is below the decision threshold. |
| `pending` | A human decision is required. No order and no debit. |
| `approved` | The decision covers the exact amount, currency and reference. |
| `rejected` | The decision denies the purchase. |
| `expired` | The decision window closed. |
| `consumed` | The approval was used for one order and cannot be reused. |

The target contract returns `approval_required` and an approval URL. The exact HTTP status,
approval id format and resume mechanics are not final. Handle the code without assuming a status
until the published OpenAPI documents it.

## What to do today

The current order handler enforces `approvalThresholdMinor` and fails closed with
`approval_required`. Because no approval exchange is live yet, treat that code as a hard stop and
escalate to the principal.

1. Compute the quote or expected total.
2. If the total is at or above the agent threshold, stop.
3. Ask the principal for a decision with the agent id, amount, currency, reference, item summary
   and quote expiry.
4. Record the decision in durable storage with a unique approval id, approver, timestamp, amount,
   currency and expiry.
5. Only after an explicit approval, place the order with `expectedTotalMinor` equal to the approved
   amount.
6. Mark the approval consumed. Never reuse it for a second order.

Do not treat a chat message, a model assertion or an unattended timer as approval.

## Decision record

Use a record that can be audited:

```json
{
  "approvalId": "approval-2026-11-04-0001",
  "agentId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  "decision": "approved",
  "approver": "partner-owner-id",
  "amountMinor": 1618,
  "currency": "USD",
  "reference": "field-kit-2026-11-04-0001",
  "expiresAt": "2026-11-04T03:30:00.000Z",
  "consumedAt": null
}
```

Keep the record server-side. Do not put an approval token, secret or personal data in a prompt.

## Escalate when

- The amount, currency or recipient is outside the written mandate.
- The new total after `409 price_changed` exceeds the approved amount.
- The order would cross the per-order, daily or rolling limit.
- The agent cannot identify a human owner.
- The wallet is short and the principal has not authorised funding.
- The egress IP is blocked and the agent cannot fix it.

Escalation means stop and report. It does not mean retrying with a larger budget, a second key or
a different payment source.

## Once approval is live

- `approval_required` must stop the agent; it must not be retried as a transient error.
- The approval must be single-use and bound to amount, currency and reference.
- An expired approval must be discarded, not extended by the agent.
- A rejected approval is final for that request.
- The order must fail closed if approval cannot be verified.
- Approval events should be auditable and visible to the partner owner.

## Relationship to payment

Approval is not funding. A wallet can have enough credit and still require approval, and an
approved order can still fail with `402` if the wallet is short. Keep the two decisions separate:
first approve the spend, then confirm available credit.

## Related

- [Agent identities](/docs/agent-identities) for thresholds and scopes.
- [Agent payment](/docs/agent-payment) for the order flow.
- [Wallet](/docs/wallet) for available credit.
- [Errors](/docs/errors) for `approval_required` handling.
