<!--
Sitemap:
- [PayBox](/index): The non-custodial wallet for AI agents
- [Getting started](/getting-started)
- [Credentials & agents](/concepts/model): The PayBox model
- [Approvals & passkeys](/concepts/approvals)
- [Request lifecycle](/concepts/requests): From intent to result
- [MCP connector](/connect/mcp)
- [OAuth 2.1](/connect/oauth)
- [MCP tools](/reference/mcp-tools): What an agent can call
- [API & endpoints](/api-reference)
- [SDK & CLI](/sdk-cli)
-->

# Request lifecycle \[From intent to result]

Every operation an agent requests — a payment, a signature, a secret, a swap —
runs through the same lifecycle. Understanding it is the difference between an
integration that waits correctly and one that double-charges.

## The shape of every request

An agent submits an **intent** (via an [MCP tool](/reference/mcp-tools)). PayBox
evaluates it against the grant and returns one of:

::::steps

### Allow (autonomous)

The grant's approval mode is *autonomous* and the operation is within its limits.
Payments and secrets complete immediately (`success`). Wallet signs and swaps
move to `pending_signature` — they still need the [signing
window](#the-signing-window) to produce the artifact.

### Needs approval

The grant requires human approval, or the operation crosses a threshold. PayBox
returns `pending_approval` with an `approval_url`. Surface it to the user; they
approve with a passkey in the PayBox app.

### Deny

Policy rejects it outright (e.g. a chain or merchant not in the grant). PayBox
returns `denied` with a `reason`.

::::

## Statuses

| Status | Terminal? | Meaning |
| --- | --- | --- |
| `pending_approval` | no | Waiting on the user's passkey approval. |
| `pending_signature` | no | Approved or autonomous; the signing window is producing the artifact (wallet sign / swap only). |
| `pending_settlement` | no | A cross-chain swap's source tx is broadcast; the bridge is settling on the destination chain. Each poll re-checks and flips it forward. |
| `pending_confirmation` | no | Broadcast but not yet confirmed on-chain. Each poll re-checks and flips to `success` (confirmed) or `error` (dropped or failed). |
| `success` | yes | Done — `output` carries the result. For on-chain operations this means **confirmed on-chain**, never merely broadcast. |
| `denied` | yes | A policy or user decision. Carries a `reason`. |
| `error` | yes | An internal failure (not a decision). Carries a `message`. |

## The poll pattern

The one rule that matters: **submit once, then poll** — never re-issue the
original tool call to "finish" it. Re-calling starts a *new* operation (a second
charge, a second signature).

::::steps

### Submit

Call the `request_*` tool. Keep the `request_id` from the result.

### Surface approval (if pending)

If `status` is `pending_approval`, show the `approval_url`. The user opens it in
the PayBox app and approves with their passkey. Approvals are **operation-bound**
and expire after ~10 minutes — change any parameter and it's a new request, so an
approval can never be replayed against different details.

### Poll

Call [`get_request`](/reference/mcp-tools#get_request) with the `request_id`
until it reaches a terminal status. It walks `pending_approval` →
`pending_signature` → `success` on its own as the user approves and the signing
window completes.

### Use the output

On `success`, read `output` — a payment token, a `0x` signature, a broadcastable
serialized transaction, a swap transaction hash, or a secret token.

::::

## The signing window

Wallet signing never happens in agent code. When a wallet sign or swap is cleared
(`pending_signature`), the MCP host opens the **signing window** — an interactive
UI rendered in the chat (the MCP resource `ui://paybox/wallet-sign`).

Hosts differ in *when* they draw it. Most draw it as soon as the tool result
arrives. Grok draws it only once the agent's reply is finished, so nothing is on
screen while the agent is still writing — the agent hands off and ends its turn
rather than polling for a window that isn't drawn yet.

* The window signs **client-side** via MoonX MPC. The private key never reaches
  PayBox, the agent, or the model.
* It posts the signed artifact back to PayBox itself. The agent's only job is to
  check `get_request` until `success`.

So a basic wallet flow looks like: `request_wallet_sign` → (`pending_approval`
→ user passkey) → `pending_signature` → *window signs* → `success` with the
signature.

The same window also handles higher-level wallet operations:

* `request_swap` signs the swap transaction or gasless UserOperation envelopes;
  PayBox broadcasts after the window submits the signatures.
* `pay_x402` signs the EIP-3009 typed data; PayBox assembles the x402 payment
  header and, in gateway mode, can re-fetch the paid resource.
* When x402 auto-undelegate is enabled, delegated x402 payers use one composite
  window flow: undelegate first, verify code is gone, then sign the x402 payment.

These operations still follow the same rule: the agent submits once, surfaces
approval if needed, and polls `get_request`.

:::info
The window's own calls back to PayBox use internal tools that are hidden from the
agent. You don't implement or call them — just surface `approval_url` when asked
and poll for the result.
:::

## Audit

Every step — request, approval, denial, completion, revocation — is an audit
event tied to the user, the client, and the request. Users review the trail in
the app; see **[Approvals & passkeys](/concepts/approvals)** for the auth tiers
each action requires.
