Skip to main content
x402 is an open payment protocol from Coinbase that revives the HTTP 402 status code. The server answers a request with 402 Payment Required and a payment challenge; the client signs a payment payload that satisfies the challenge and resends it in an HTTP header; the server verifies and settles before returning the resource. The protocol is now stewarded under the Linux Foundation. x402’s production scheme is exact — pay a specific amount of a specific asset (typically USDC). Inbound to SELAT is USDC on EVM via Circle Gateway. The settlement mechanics differ by ecosystem: EVM chains use off-chain EIP-712 signatures over an ERC-3009 authorization, while Solana uses a signed SPL Token transfer.
x402 is one of the two paid-rail protocols SELAT can use; the other is MPP on Tempo. A Gateway-capable upstream defaults to x402 (same-rail passthrough); otherwise MPP is the default and x402 is opt-in (preferProtocol: "x402" / --prefer-x402).

The x402 challenge

A SELAT/x402 402 challenge is a JSON object with an x402Version and an accepts[] array. Each accept entry describes one way to pay: The payer takes asset, payTo, and the EIP-712 verifyingContract from the live challenge rather than a static table, so a per-chain address list is never hardcoded.
Prices are token base units. USDC has 6 decimals, so divide by 1,000,000 for the USD amount — the payer falls back amount ?? maxAmountRequired to support both x402 v1 and v2 challenges.
SELAT detects x402 from a probe in two forms:
  • A base64-encoded JSON payment-required: response header.
  • A www-authenticate: X402 requirements="<base64 PaymentRequired JSON>" header (used by some services alongside the body header).
(MPP, by contrast, is detected from a www-authenticate: Payment ... challenge.)

Base (EVM)

On Base and other EVM chains, x402 payments are signed off-chain with EIP-712 typed data and settled in USDC. The signed object is an ERC-3009 TransferWithAuthorization:
USDC implements transferWithAuthorization natively, so a facilitator can submit the signed authorization on-chain — the payer needs no gas. SELAT signs exactly this shape (see GATEWAY_AUTH_TYPES in the payer).

Signer paths

The SDK and CLI support three signer models — see the Signers reference:

Circle Agent Wallet

The default. Signing goes through the Circle CLI (circle wallet sign typed-data), keeping keys in Circle’s MPC and out of the application process.

Raw private key

Dev only. --raw-key / SELAT_PRIVATE_KEY signs in-process via viem, bypassing Circle MPC.

Remote signer

For an HSM, KMS, or external wallet service that signs the typed data over a callback.
Circle Agent Wallets are smart-contract accounts (SCA). For a Gateway-batched payment, the authorization’s from must be the owner EOA that the SCA signature recovers to — not the SCA address. SELAT resolves this by signing a throwaway authorization in the exact GatewayWalletBatched EIP-712 domain and recovering the signer.

Same-rail passthrough vs cross-protocol routing

Every paid call goes through the SELAT Router via its /proxy?target= endpoint — including upstreams that themselves accept Gateway-batched x402. (Earlier selat-pay versions paid Gateway-capable upstreams directly, bypassing the router; that mode was removed so every call is quoted, recorded, and reconciled.) What the upstream’s accepts list controls is the outbound protocol: when it contains an exact entry on the expected eip155:<chainId> network whose extra.name is GatewayWalletBatched, the router settles the upstream leg as a same-rail Gateway passthrough (routed-x402, no cross-protocol translation); otherwise it translates to MPP or x402 exact on the outbound leg (EIP-3009 on EVM, TransferChecked on Solana). The payment payload is built by the SDK and sent base64-encoded in a payment-signature header, always signed in the one GatewayWalletBatched shape against the router’s own 402 quote.
Cross-protocol calls (Gateway in → MPP/erc-3009 out) carry the router’s flat, transparent ~5% markup. Same-rail Gateway passthrough is currently quoted at par (0%) — that is the operator’s live behavior, not a protocol guarantee. The per-call 402 quote is always authoritative; inspect it with --probe-only.
You fund on 7 EVM chains via Circle Gateway and the router settles merchants on Circle Gateway, Base, Tempo, or Solana — see Chains for the full inbound/outbound split. Every deposit is gasless; Base also supports selat fund --method eco fast deposits (a ~30-second credit, settling into Gateway on Polygon).

Solana

Agents pay in on EVM via Circle Gateway. The router settles x402 exact on Solana (SPL) outbound. Solana is not a fund chain. x402 defines an SVM exact scheme: an account-based SPL Token transfer, not an EIP-712 authorization. Coinbase’s reference implementation and the @x402/svm package implement that path — a signed Solana transaction that transfers USDC (an SPL Token) to the accept’s payTo.
You still sign only the Gateway-batched quote.

When to prefer x402 vs MPP

  • x402 is the open Coinbase standard. A Gateway-capable upstream defaults to routed-x402 — same-rail Gateway passthrough with no cross-protocol translation, currently quoted at par by the router.
  • MPP is SELAT’s default for upstreams without a Gateway-batched accept, and settles on Tempo.
  • Route precedence in the payer: a free upstream is served as a logged passthrough (routed-free); a Gateway-capable upstream defaults to routed-x402; otherwise MPP wins (routed-mpp), falling back to routed-x402 when only non-Gateway x402 is offered. --prefer-x402 and --prefer-mpp override the default; they are mutually exclusive.
  • Pass preferProtocol: "x402" (SDK) or --prefer-x402 (CLI) to opt out of the MPP default.

Next