Cloud Gateway & MCPx402 (pay for a resource)

x402 — pay for a resource through the gateway

x402 is how a web resource charges per request: it answers 402 Payment Required with what it wants (asset, network, amount, recipient), the caller signs a transfer for exactly that and retries, the resource settles the transfer on chain and answers. With the gateway, the agent only asks for the resource; the paying is Regent’s, under the owner’s budget.

⚠️

Test networks only. This rail pays on Base Sepolia with test USDC. A 402 that asks for Base mainnet is recognised and refused (X402_MAINNET_DISABLED). Real money comes after the gate the roadmap names: a legal opinion and a production organization with a verified owner.

One call

GET /gw/x402/api.example.com/v1/quote?city=Astana
Authorization: Bearer <control key>
X-Agent-Id: <agent id>
X-Agent-Intent: price a courier for the Astana order

Name the resource as <host>/<path>; the gateway reaches it over https only. What comes back is the resource’s own answer, plus three headers from Regent:

HeaderMeaning
X-Regent-Decision-Idthe decision this payment ran under
X-Regent-Settlementverified (the transfer was read from the chain and the decision is closed), unverified (the resource reported a transaction the chain did not confirm yet; the decision stays open for reconciliation), none (the resource reported no settlement)
X-Regent-Transactionthe transfer’s transaction hash, when the resource reported one

A resource that answers without asking for payment is passed through as it is, with no decision: nothing moved.

What happens between the ask and the answer

The 402 names the figures

The gateway reads the offer from the 402 (both x402 versions): the amount in the asset’s atomic units, the asset, the network, the recipient (payTo). Only an exact offer in USDC on a registered network is accepted; anything else is refused by name (X402_UNSUPPORTED says what the resource offered). The agent’s own amount or payee facts are dropped: the rail’s word is the only one.

The gate decides

On the 402’s figures: the agent’s USDC mandate (per payment, per day, per month), the cap per seller (the counterparty is the resource’s host, payee_source: rail), the policy, the risk. A refusal reaches the agent with the gate’s code; the resource is not asked again. A payment above the owner’s threshold parks for a passkey approval like any other (ESCALATION_REQUIRED).

Sub-cent amounts count as a cent against the budget: a thousand $0.0001 calls cannot ride under a zero.

A signer signs exactly that

The connected wallet signs an EIP-3009 TransferWithAuthorization for the 402’s recipient and amount, with a fresh nonce and a validity of at most 300 seconds. What comes back is compared with what was decided; a different recipient or amount voids the hold before the retry (X402_SIGNED_MISMATCH).

Who signs is the one thing an organization chooses:

  • Your Privy wallet (wallet: privy on the tool). Your server wallet stays in your Privy app with your money. You register Regent’s authorization key as a signer on it, under a policy Privy enforces itself: eth_signTypedData_v4 only, USDC on the named chain, at most X per signature, optional recipients. After the gate allows a payment, the gateway asks Privy to sign the 402’s authorization, signing the request with Regent’s key. Privy’s policy is the backstop under our decision: a signature above its cap is refused by the wallet (X402_WALLET_POLICY_REFUSED) whatever the gate said, and Regent’s key alone moves nothing. See Set it up.
  • Regent’s demo wallet: Regent’s own test money, for named organizations, test networks only.

There is no field anywhere for a client’s private key. Other providers that can sign only after an outside approval (Turnkey, Rox Custody) follow the same interface; Coinbase CDP has no such hook today, so a CDP wallet is governed on the seller’s side (decide-by-wallet).

The paid retry

The same request again, now with the payment header (X-PAYMENT for v1, PAYMENT-SIGNATURE for v2). A resource that refuses the payment answers 402 again: the hold is voided and the agent gets X402_PAYMENT_REJECTED with the resource’s reason. Nothing moved.

The chain says what settled

The resource’s settlement header is a claim. The gateway reads the transaction’s receipt from the chain itself and looks for the USDC Transfer to the 402’s recipient for the 402’s amount from the signing wallet. Only on a match is the decision completed: the transaction hash becomes settlement_ref and the chain settlement_network in the signed receipt, so the payment can be checked later without Regent.

Try it in a sandbox

A new organization starts in a sandbox and already has the x402 tool, limited to Regent’s own demo resources, paid for by Regent’s demo wallet on Base Sepolia: your agent needs no wallet and no USDC to see the whole path.

  1. Ask the owner for a USDC budget for the agent: the gate decides x402 payments in USDC, so a USD budget does not cover them. Over MCP the agent calls request_budget with currency: "USDC"; in the console, Grant → currency USDC. The owner approves it.

  2. Call a demo resource through the gateway:

    GET /gw/x402/api.regentprotocol.org/v1/x402-demo/echo
    GET /gw/x402/api.regentprotocol.org/v1/x402-demo/weather?latitude=51.1&longitude=71.4

    echo costs 0.001 USDC and answers with the transaction that paid for it; weather costs 0.01 USDC and answers with the current weather (Open-Meteo). Both settle through the public facilitator on Base Sepolia; the money goes back to the demo wallet, so the sandbox is self-funding.

  3. Read the receipt (receipt over MCP, or Activity in the console): settlement_ref is the transaction hash, settlement_network is base-sepolia.

The demo wallet pays at most 1 USDC a day per organization (X402_DEMO_DAILY_CAP when it is used up) and a global amount for everyone; a payment that would exceed it is refused and nothing is signed. To pay elsewhere than the demo hosts, or with your own money, connect your own wallet below.

Set it up

  1. The tool. An owner adds the rail to the organization’s catalog as a catalog extra: PUT /v1/organizations/<org>/control/catalog-extras/x402 with {"spec": {"type": "x402", "requires_mandate": true, "allowed_hosts": ["api.example.com"]}}. allowed_hosts (optional) limits where agents may pay; a host and its subdomains.

  2. The budget. A USDC mandate for the agent, approved by the owner. Without one the gate refuses (MANDATE_NOT_FOUND).

  3. The wallet. In the console, Connect → Gateway → Your wallet, through Privy: paste the App ID and App Secret of your Privy app (the free plan is enough) and a cap per payment, then Connect wallet. Regent creates, in your app, a server wallet on Base Sepolia with its signer key under a policy Privy enforces itself (USDC only, at most the cap per payment), vaults the credential, and points the x402 tool at the wallet. Fund the address it shows with test USDC (Circle’s faucet). Your app secret stays the wallet’s master; Regent’s key signs only within the policy and cannot change it, the signers or export the key. Disconnect forgets the credential and points the tool back at the demo wallet; the wallet stays in your app.

    By API, the same screen is POST /v1/organizations/<org>/gateway/privy with {"app_id", "app_secret", "cap_usdc"}; Regent’s public key is served at https://gw.regentprotocol.org/.well-known/x402-signer.json for anyone wiring it by hand.

Refusal codes

CodeWhen
X402_HTTPS_ONLY, X402_BAD_RESOURCE, X402_HOST_NOT_ALLOWEDthe resource name
X402_UNREADABLE, X402_UNSUPPORTED, X402_MAINNET_DISABLEDthe 402 cannot be paid here
MANDATE_LIMIT_EXCEEDED, PER_COUNTERPARTY, POLICY_DENIED, ESCALATION_REQUIREDthe gate’s answer
X402_NO_WALLET, X402_SIGNER_UNAVAILABLE, X402_SIGNED_MISMATCHno signature; the hold is released
X402_WALLET_POLICY_REFUSED, X402_WALLET_AUTH_REFUSED, X402_WALLET_UNSUPPORTEDthe wallet provider refused (its policy, Regent’s key not registered, an unknown provider); the hold is released
X402_PAYMENT_REJECTEDthe resource refused the signed payment; the hold is released
X402_RESOURCE_ERRORthe resource failed after a verified payment; the decision is closed on the chain’s figures
X402_OBSERVE_MODEan organization in observe mode decides but never pays