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

# HTTP 402 Payment Required

> A primer on the 402 status code and the payment protocols built on it.

`402 Payment Required` is an HTTP status code reserved since the early web for "you must pay to access this." For most of its history it sat unused. Pay-per-use APIs and agentic payments have revived it as the standard way for a server to ask a client for payment and for the client to pay and retry — all in-band, over normal HTTP.

## A status code reserved for decades

The 402 status code has been part of HTTP since the HTTP/1.1 drafts of the late 1990s (RFC 2068, carried into RFC 2616 and later RFC 7231), where it is described simply as "reserved for future use." For most of the web's history there was no interoperable way to attach a payment to a request, so 402 went essentially unused.

That changed with agentic and pay-per-use workloads. A status code that lets a server say *"pay, then try again"* — without redirecting to a checkout page or provisioning an API key — is exactly what an autonomous agent needs. The protocols in this section all use 402 as that in-band signal.

## The 402 flow

1. The client requests a protected resource.
2. The server responds **`402 Payment Required`** with a payment challenge (amount, asset, recipient, accepted protocols/rails).
3. The client constructs and signs a payment that satisfies the challenge.
4. The client retries the request with the payment attached.
5. The server verifies settlement and returns the resource.

SELAT implements this flow for agents: it discovers the challenge, picks a rail, signs, pays, and returns the final response — see the [SELAT Router SDK](/docs/selat-sdk).

## How SELAT implements 402

The `selat-pay` payer (used under the hood by the [SELAT CLI](/docs/selat-cli)) walks the 402 handshake end to end. The stages below map directly to its implementation.

### 1. Probe the upstream

`selat-pay` first sends a single probe request with **no `Authorization` header**. From one `402` response it parses *both* supported protocols:

* **x402** — from a base64 `payment-required:` body header, or from a `www-authenticate: X402 requirements="..."` header (used by some services alongside the body header).
* **MPP** — from a `www-authenticate: Payment ...` HTTP-auth challenge.

<Note>
  A second probe — sending `Authorization: Payment probe` — is fired only when needed: when MPP was asked for (`--prefer-mpp`) but the first probe didn't surface it, or as a last resort when the first probe surfaced no payable protocol at all (some dual-protocol services gate the MPP path behind that header). Sending the header blindly breaks services that reject unknown auth, so it is conditional, not default.
</Note>

If the upstream answers `2xx` with no challenge, the call is treated as **free** and still routed through the SELAT Router so the call is logged — the client never signs anything.

### 2. Detect and decode the challenge

<CodeGroup>
  ```http x402 (payment-required header) theme={null}
  HTTP/1.1 402 Payment Required
  payment-required: <base64 JSON with an "accepts" array>
  ```

  ```http MPP (www-authenticate) theme={null}
  HTTP/1.1 402 Payment Required
  www-authenticate: Payment id="...", realm="...", method="tempo",
    intent="charge", request="<base64-json>"
  ```
</CodeGroup>

For x402, each entry in the `accepts` array carries a `scheme`, `network` (an `eip155:<id>`), `asset`, `payTo`, and an `amount`. For MPP, `selat-pay` base64-decodes the `request` parameter into a JSON object carrying `amount`, `currency`, `recipient`, and `methodDetails.chainId`. Amounts are USDC base units (6 decimals — divide by 1,000,000).

### 3. Select the outbound protocol

**Every paid call is routed through the SELAT Router.** What the probe decides is the router's **outbound protocol** on the upstream leg — same-rail Gateway passthrough when the upstream is Gateway-capable, cross-protocol translation (carrying the router's default \~5% markup, included in the live quote) otherwise. The default selection:

| Condition                                                                          | Mode                                                                                           |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Upstream advertises a `GatewayWalletBatched` `exact` accept on the requested chain | `routed-x402` — same-rail passthrough, no cross-protocol translation (currently quoted at par) |
| No Gateway accept, MPP available                                                   | `routed-mpp` (MPP wins by default)                                                             |
| No Gateway accept, only x402 available                                             | `routed-x402` (cross-protocol, \~5% markup)                                                    |
| Free upstream                                                                      | `routed-free` (logged passthrough, nothing signed)                                             |

Flags adjust this: `--prefer-mpp` forces MPP even for a Gateway-capable upstream, and `--prefer-x402` opts out of the MPP default; the two are mutually exclusive. `selat-pay` targets `${routerUrl}/proxy?target=<encoded upstream>`, sends the choice in an `x-selat-prefer-protocol` header, and expects a `402` carrying both a `payment-required` challenge and an `x-selat-quote-id` — the client always signs against the router's challenge, never the upstream's.

<Note>
  Par pricing on same-rail passthrough is the operator's current live behavior, not a protocol guarantee — the per-call 402 quote is authoritative. Earlier selat-pay versions paid Gateway-capable upstreams directly, bypassing the router; that mode was removed so every call is quoted, recorded, and reconciled.
</Note>

### 4. Sign the authorization

For the Gateway-batched path, `selat-pay` builds an EIP-712 / [ERC-3009](/docs/primers/x402) `TransferWithAuthorization` in the `GatewayWalletBatched` domain (via Circle's `@circle-fin/x402-batching` `BatchEvmScheme`). Signing routes through a **Circle Agent Wallet** (user-controlled MPC) by default; because that wallet is a smart-contract account, `selat-pay` first resolves its owner EOA so the authorization's `from` matches the recovered signer. `--raw-key` signs locally with `SELAT_PRIVATE_KEY` for development and bypasses Circle MPC.

### 5. Retry, settle, and reconcile

The signed payload is base64-encoded into a `Payment-Signature` header and sent on the retried request (echoing `x-selat-quote-id` back when routing). The router verifies the payment and settles the upstream via the appropriate rail adapter, then returns the upstream body — see [SELAT Router](/docs/router).

<Note>
  Because the signed `Payment-Signature` leaves the machine before the outcome is known, the router may settle USDC even on a non-`2xx` upstream. `selat-pay` therefore records **every** submitted payment — settled or failed — to a local JSONL ledger (rail, protocol, chain, amount, `payTo`, HTTP status, outcome) so spend is always reconcilable. Inspect it with [`selat history`](/docs/selat-cli).
</Note>

<Tip>
  Paid calls require a `--max-amount` cap, enforced fail-closed: anything not satisfying `price <= cap` is rejected before signing.
</Tip>

## Payment protocols

A 402 challenge can be satisfied by different payment protocols and settlement rails. SELAT supports:

<CardGroup cols={1}>
  <Card title="x402" icon="bolt" href="/docs/primers/x402">
    Agents pay in on EVM via Circle Gateway. The router settles x402 exact on Solana (SPL) outbound. Solana is not a fund chain. You still sign only the Gateway-batched quote.
  </Card>

  <Card title="MPP on Tempo" icon="layer-group" href="/docs/primers/mpp-tempo">
    The MPP protocol, settled on Tempo.
  </Card>

  <Card title="Nanopayments via Circle Gateway" icon="coins" href="/docs/primers/nanopayments-gateway">
    Batched nanopayments backed by a unified USDC balance on Circle Gateway.
  </Card>
</CardGroup>

## Next

* [x402](/docs/primers/x402)
* [MPP on Tempo](/docs/primers/mpp-tempo)
* [Nanopayments powered by Circle Gateway](/docs/primers/nanopayments-gateway)
