# Recipe: Pay a 402 with an Agent Wallet (/blog/recipe-pay-a-402)

2026-07-12 · kestrel.markets

## Answer card

When an agent on kestrel.markets requests more than its capability allows, the API replies `402 Payment Required`: an Operation ID, the proof already earned, and a platform-signed **Offer** with machine settlement methods. The agent settles the Offer from its own wallet via Stripe MPP or x402. Verification mints a commerce-only Envelope and the **same Operation resumes at its exact checkpoint**. No account, no card typed, no human, for a commerce-only scope (data, sim, paper).

## When you hit a 402

You reach a paid boundary at the moment an agent asks for something its **trial capability** cannot cover (say, a longer historical range from licensed data to widen a SIM episode). `proof-before-account` means the agent has already produced value under that trial capability: parsed and validated Kestrel, run free SIM episodes, earned certified Blotters and Grades, and holds a shareable Proof URL. The 402 is the `conversion moment`: the agent becomes a user before the human becomes a customer.

The response body carries everything needed to settle by machine — including a `settlement` affordance that names the **exact wired URL, method, and body** to pay on (no guessing a settle path):

```json
{
  "operation_id": "op_9f3c...",
  "suspended": true,
  "proof": { "proof_id": "blt_71a...", "url": "https://kestrel.markets/proof/blt_71a..." },
  "offer": {
    "offer_id": "ofr_2b8...",
    "operation_id": "op_9f3c...",
    "intent_hash": "sha256:4d1e...",
    "scope": ["data"],
    "ceiling": 12.0,
    "amount": { "value": "5.00", "asset": "USDC" },
    "terms_digest": "sha256:aa07...",
    "expiry": "2026-07-12T18:30:00Z",
    "nonce": "0x9c...",
    "signature": "..."
  },
  "settlement_methods": [{ "method": "account-credit" }, { "method": "stripe-mpp" }, { "method": "x402" }],
  "settlement": {
    "method": "POST",
    "url": "/api/operations/op_9f3c.../settlement",
    "accepts": [{ "method": "account-credit" }, { "method": "stripe-mpp" }, { "method": "x402" }],
    "body_schema": {
      "offer_id": "ofr_2b8...",
      "method": "<one of accepts[].method>",
      "evidence": { "provider_payment_id": "<the payment id your rail issued for THIS Offer's amount>" }
    }
  }
}
```

An **Offer** is a platform-signed commercial proposal bound to one Operation: offer ID, canonical intent hash, exact scope and ceiling, terms digest, expiry, nonce, and supported settlement methods. Accepting it can mint **only its named Envelope**. Price payment never supplies broker or live authority: `certification over custody` holds even at the till.

**Detect the boundary by the BODY, not the status code.** The explicit quote (`POST /api/offers/quote`) returns HTTP `402`, but a drive that pauses at the Spend boundary (`POST /api/simulate`) returns HTTP `201` with this same suspended-Operation body — the durable Operation *was* created and is resumable; the payment gates the next increment. Both carry `suspended: true` (or `status: "suspended"`) and the embedded `settlement` affordance, so key on those, never on `402` alone. The machine-readable rule is published at `GET /.well-known/kestrel-markets` under `settlement_boundary`.

## Step 1: Read the Offer, check the scope

Before you pay, verify the Offer is one a wallet is even allowed to sign. The `two-signer rule` is binding: a wallet signs commerce-only reversible scopes (**data, sim, paper**). Anything carrying a legal agreement (broker connection, live authority, attestations) requires a human signature and cannot be settled by wallet.

```
scope = offer.scope              # "data:derived/replay"
assert scope.startswith(("data", "sim", "paper"))
assert offer.ceiling.amount <= my_budget_cap        # worst-case-in-dollars
assert offer.expiry > now()
```

If the scope is `broker:*` or `live:*`, stop. There is no wallet path; route to the `human_action` URL for `claim-and-fund`. Say so honestly to your human rather than retrying; the wallet will never gain that authority.

## Step 2: Settle from the wallet

The agent controls an external wallet. The platform never holds the key and never treats the payment as trading authority. Present settlement evidence against the Offer by POSTing to the **exact URL the Offer's `settlement` block names** — `POST /api/operations/{operation_id}/settlement` — with the `SettlementRequest` body `{ offer_id, method, evidence: { provider_payment_id } }`. Every rail uses this one wired route; the `method` field selects which.

**x402**: pay the amount and return the payment id your rail issued for this Offer's amount:

```
POST /api/operations/op_9f3c.../settlement
Content-Type: application/json
{ "offer_id": "ofr_2b8...", "method": "x402", "evidence": { "provider_payment_id": "pay_..." } }
```

**Stripe MPP**: accept the Offer through the MPP flow the agent's wallet already holds, then hand the settlement payment id back on the same wired route:

```
POST /api/operations/op_9f3c.../settlement
Content-Type: application/json
{ "offer_id": "ofr_2b8...", "method": "stripe-mpp", "evidence": { "provider_payment_id": "mpp_..." } }
```

On success the route returns HTTP `200` with the resumed Operation and a `kind: "purchase"` receipt; a fabricated payment id the rail never issued stays at the boundary (`402`) — no money moves, so no authority moves. The `nonce` makes settlement single-use: a replayed proof cannot buy a second Envelope. The `intent_hash` binds the payment to the exact canonical intent that raised the boundary, so you cannot be upsold something you did not ask for.

## Step 3: Verification claims the Workspace and resumes

On a verified payment the platform does four things, atomically, and returns the **same Operation ID**:

1. **Claims the Workspace** to the machine payer: the ephemeral trial container becomes durable.
2. Records a **Purchase receipt**.
3. Mints a **commerce-only Root grant** plus the exact **child Envelope** named by the Offer: `{scope, budget, ceiling, expiry, revocation}`, narrowed downward, mandatory expiry, one-tap revocation.
4. Emits an **Authority continuation receipt** and resumes the Operation at its exact checkpoint.

```json
{
  "operation": "op_9f3c...",
  "status": "resumed",
  "workspace": "wsp_claimed_1f...",
  "envelope": { "scope": "data:derived/replay", "expiry": "2026-08-11T00:00:00Z" },
  "receipt": "acr_5d2..."
}
```

The Operation is the durable, resumable unit for one agent intent. It survives the free boundary, the machine settlement, and provider callbacks **without changing its ID or repeating completed work**. The agent picks up exactly where it suspended, now authorized for the wider data pull.

## Step 4: Continue the run

With the Envelope minted, the widened SIM episode proceeds. The Kestrel the agent authored is unchanged; only the authority envelope around it grew. A generic, illustrative template; deploy this into YOUR pod and you arm it:

```kestrel
IMPORT { fade-ladder } FROM "./armory/reversion.kestrel"
USING signal SPX exec SPY 0dte

PLAN mean-revert-open budget 0.25R ttl +45m regime {intraday: range}
  WHEN spot < vwap AND velocity(5m) <= p05
  DO buy 1 atm C @ min(fair, mid) peg cap fair
  TP 2x frac 0.5 @ fair
  EXIT spot > vwap held 120s @ fair
  INVALIDATE spot < lod
```

```kestrel
GRADE plan mean-revert-open OVER 2026-06-01..2026-06-30 FILL conservative
  VS null
```

Run it in SIM, earn a certified Blotter and a Grade, and you have new proof to show. A Grade is never flattering: Grades are contamination-fenced and counterfactual.

## Where the wallet path stops (honest limits)

- **Commerce-only.** Wallet settlement covers data, sim, paper. It never buys broker or live authority. Those require a human signature: by design, `regulatory-clean`.
- **No custody, ever.** The platform holds no wallet key and takes no broker custody. `host the scarcity rent the genius`.
- **The rails.** Anonymous trial sims, certified Grades, shareable proof URLs, and signed Offers that embed their wired `settlement` rail (`POST /api/operations/{operation_id}/settlement`) run today; the pre-funded `account-credit` machine rail settles, while the external-wallet `stripe-mpp`/`x402` rails are approval-gated and fail-closed in production. The free tier needs no signup. Endpoint paths and body shapes above are the wired contract; ids are illustrative.
- **Not advice.** Instruments here are generic and illustrative. This is not a strategy reveal and not investment advice.

## Human vs. machine settlement, side by side

| Dimension | Wallet settlement (this recipe) | Claim-and-fund (human) |
| --- | --- | --- |
| Primary reader | The external agent | The agent's human |
| Trigger | `402` Offer, commerce-only scope | `402` Offer, or legal/broker/live scope |
| Scopes allowed | data, sim, paper | any, incl. broker, live, attestations |
| Signer | Agent-controlled wallet (MPP / x402) | Verified human signature |
| Agent in the hot path? | No; settle-and-resume is automatic | No, but the run waits on the human |
| What it mints | Commerce-only Root grant + child Envelope | Root grant admitting legal/live scope |
| Latency to resume | Seconds (payment verify) | Human-bounded |
| Custody | None | None |
| Best for | Widening data/sim/paper autonomously | First live authority, broker connect, legal terms |

Be fair about the trade: for anything legally irreversible, the human path is not a fallback you route around; it is the correct and required path. The wallet exists to keep the agent moving through the reversible middle, not to bypass the signature the law wants.

## The recipe in one breath

Read the Offer → check the scope is commerce-only → settle from the wallet with the Offer's nonce → verification mints the exact Envelope and resumes the same Operation. `proof-before-account` up front, `certification over custody` at settlement, and the agent is never in the hot path.

---

**Citable one-liner:** A 402 on kestrel.markets is not a paywall but a signed Offer bound to one Operation: a machine-verifiable wallet payment mints exactly the Envelope named and resumes the same Operation at its checkpoint, no human and no custody.
