Guides
Use the Roundhouse facilitator
Settle x402 payments on Base mainnet, whether you are paying or charging, with payers who hold no ETH.
A facilitator is the service that verifies an x402 payment payload and submits the settlement transaction on-chain. It is the piece that makes x402 gasless for the payer: the payer signs an EIP-3009 authorization, the facilitator broadcasts it and pays the gas.
Roundhouse runs a first-party one, on Base mainnet, free to point at.
https://x402.roundhouse.studioWhy you might want ours: the public x402.org/facilitator is EVM testnet only — it serves
base-sepolia and has no Base mainnet facilitator at all. A mainnet-priced resource can never
settle through it, whatever the payload looks like.
Check what it serves, first#
Not decoration. A facilitator that does not serve your chain answers 500 with
No facilitator registered for scheme: exact and network: <x>, which reads like a broken payment
and is a configuration problem.
curl -s https://x402.roundhouse.studio/supported{
"kinds": [
{ "x402Version": 1, "scheme": "exact", "network": "eip155:8453", "extra": { "feePayer": "0x…" } }
],
"signers": { "eip155:*": ["0x…"] }
}GET / returns a plain-language service descriptor — endpoints, monitored chains, and which
dependencies are configured. It is the quickest health check there is.
As a client: you are paying#
An off-the-shelf x402 client needs no facilitator configuration at all — the resource server names its own. You only reach for one directly when you want a supported-kinds list up front, or a settlement receipt of your own.
import { wrapFetchWithPayment } from 'x402-fetch';
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const fetchWithPayment = wrapFetchWithPayment(fetch, account);
const res = await fetchWithPayment('https://www.roundhouse.studio/api/v0/test/x402');Fund the wallet with a little USDC on Base. It needs no ETH — the facilitator submits the transaction and pays the gas.
Note
GET /v0/test/x402 costs $0.01 and hands back an API key with a higher POST /v0/sql rate
limit, so the cent is not wasted. It is the cheapest end-to-end proof that your wallet, your
client and the settlement path all work.
As a seller: you are charging#
Point your paywall's facilitator URL at Roundhouse and speak the standard x402 wire format.
X402_FACILITATOR_URL="https://x402.roundhouse.studio"
X402_FACILITATOR_FORMAT="standard"Outside this repo, set whatever your x402 middleware calls its facilitator URL. The endpoints are the standard ones:
| Endpoint | Purpose |
|---|---|
GET / | Service descriptor — endpoints, chains, configured dependencies |
GET /supported | Payment kinds, signers and fee payers per chain |
POST /verify | Verify a payment payload against your requirements |
POST /settle | Settle a verified payment on-chain from the facilitator wallet |
GET /test/x402 | The facilitator's own paywalled test resource, for checking it in isolation |
Request bodies are { x402Version, paymentPayload, paymentRequirements }. paymentRequirements
must be exactly what you published — the facilitator compares the signed payload against them,
so a single changed field reads back as "signature does not authorize this transfer".
The one mistake everybody makes#
paymentPayload is an object, not the base64 X-PAYMENT header value. Base64 is only how the
payment travels over HTTP; on a /verify or /settle call it must be the decoded envelope:
{
"x402Version": 1,
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"signature": "0x…",
"authorization": {
"from": "0x…",
"to": "0x…",
"value": "10000",
"validAfter": "…",
"validBefore": "…",
"nonce": "0x…"
}
}
},
"paymentRequirements": { "…": "exactly what you published" }
}Hand it the base64 string instead and a conformant facilitator answers 500
No facilitator registered for x402 version: undefined — it reads x402Version off that object,
and a string has no fields.
Two more things that fail the same way and are worth ruling out before you debug a signature:
- Addresses must be EIP-55 checksummed before anything hashes them. viem validates checksums
inside
hashTypedData, so a lowercased address fails at the facilitator as "signature does not authorize this transfer" — which cannot be fixed by re-signing. - Read the price from the live 402, never from a cached figure. The operator can change it, and a stale quote fails verification.
What running through ours gets you#
- Your payers need no gas. USDC only, no native token, no top-up step in your onboarding.
- You find out which endpoint earned it. A settlement we relay carries the resource that was
paid for. Read off the chain alone it is a bare USDC transfer to your wallet, so forty endpoints
behind one
payTocollapse into one line — through ours, each endpoint has its own revenue, price and traffic. - You learn who your customers are. Payers resolve to identities where identities exist, and the endpoint each one bought is attached — so repeat buyers, what they spend and which service brings them back are answerable questions rather than a list of addresses.
- Your service is named across the index, not inferred: a named route on the flow graph instead of "route unknown", and a merchant page listing your endpoints rather than an unattributed wallet. (Named, not ranked — Roundhouse publishes no leaderboards.)
- Failures are visible. Every verify and settle attempt is captured, successful or not — so a payment that never landed on-chain is still diagnosable. A chain indexer can never do that, because there is nothing on the chain to index.
See it working#
Every settlement relayed by this facilitator is public, like every other:
/facilitators/roundhouse— its own record: volume relayed, who it settles for, and how steady it has been./facilitators— the same figures for every facilitator we can attribute, so "ours" is a comparison you can check rather than a claim.
Using Roundhouse, set me up to charge for an API over x402 on Base mainnet, settling through the
Roundhouse facilitator at https://x402.roundhouse.studio. Show me the 402 challenge my
endpoint should return, and the verify and settle calls I need to make. Then check the
facilitator is serving my network with GET /supported before we start.Next steps#
- Your first x402 payment — pay a cent, with every header shown.
- Charge for your API — the seller side end to end.
- Pay an agent without gas — the same EIP-3009 mechanism, used to forward USDC rather than to buy something.