x402 machine payments
Pay per request with USDC from a wallet. No signup, no email, no card — built for bots and agents.
x402 lets a wallet buy gateway access directly. Sign one USDC transfer, get an RPC URL back, start calling. There is no account to create, no email to verify, and no card on file.
It exists for callers that cannot sign up: autonomous agents, trading bots, one-off data scrapers. If you have a browser and a credit card, the normal plans are cheaper.
Availability depends on the operator enabling it. Check
GET /v1/x402/info — if it returns "enabled": false, x402 is not
live on this deployment.
The endpoint speaks standard x402 v2 with the
exact scheme, so any conforming client works. If you already use
@x402/fetch or similar, point it at /v1/x402/deposit and skip the
manual signing below.
The short version
Point any x402-aware client at the RPC endpoint and forget the rest:
Anonymous calls are served until they pass the free allowance. After
that the endpoint answers 402 with the price, the client pays, and the
same request is answered — no second endpoint, nothing to read first.
The paid response carries the key it just bought:
Use that URL for everything afterwards. It is already paid for and skips the payment path entirely, which any long-running caller should do.
Capacity is granted the moment the transfer is broadcast, not when it confirms — an RPC caller cannot sit through a block. We only broadcast after simulating, so the transfer is near-certain; if one ever reverts, the compute units are taken back.
How it works
- Read the menu.
GET /v1/x402/infotells you the price, the minimum deposit, which chains are served, and how much capacity is still available. - Sign a transfer. An EIP-3009
transferWithAuthorizationfor USDC, payable to the address in the challenge. You sign it; you do not send it, and you never pay gas. - Post it in the
PAYMENT-SIGNATUREheader as base64 of the standardPaymentPayload. We verify the signature, simulate the transfer, and hand it to a facilitator to broadcast. - Get your URL. Once the transfer confirms, your wallet has a
balance in compute units and a gateway key. Poll the payment id
until it reports
confirmed.
Capacity is granted only after the money lands on-chain. Nothing is extended on credit, which is also why there is no invoice, no refund flow, and nothing to reconcile later.
Pricing
One rate for everything, charged in compute units. A cheap read costs a
few CU; a wide eth_getLogs costs hundreds. The exact per-method
weights are the same ones documented under rate limits.
GET /v1/x402/info returns the live rate as priceUnitsPerMcu, in USDC
base units per 1,000,000 CU (1.00 USDC per 1M CU at the time of writing,
about $0.000024 for a typical request).
Every wallet also gets a free allowance each calendar month (UTC),
freeCuPerMonth in /info (1,000,000 CU today). Metering uses it before
it draws on your paid balance.
Your deposit also decides your rate limit. Bigger deposits buy higher
tiers, because a higher request rate needs a larger balance behind it —
we cap what any one wallet can burn before metering catches up. The
tiers array in /info lists each tier's requests-per-second and the
deposit it requires.
Tiers are also capped by how much capacity is left on the chain you
want. If a tier is sold out, the deposit still lands and you get the
highest tier that fits. availableRps in /info tells you before you
sign.
Quick start
TypeScript
Python
Checking your balance
Top up by running the deposit flow again with the same wallet. The URL does not change, the balance and tier just go up.
Attributing a wallet to one of your apps
If you run the bot yourself, you can have its traffic show up under one of your dashboard apps instead of only in your wallet's own usage. Send one of that app's API keys with the deposit:
The app key already proves you own the app, so there is no second signature to make. Deposit again with a different app's key and the wallet moves with it.
Attribution only. The wallet still pays from its own prepaid balance, and none of it counts against the app owner's plan allowance.
Once attributed, the wallet shows up under x402 wallets in the dashboard: balance remaining, burn rate, which methods cost the most, and whether it is hitting its tier ceiling.
Attaching a wallet that already deposited
If the wallet has been paying already, you do not need to deposit again just to label it. Go to x402 wallets in the dashboard, paste the address and pick the app.
With a browser wallet (MetaMask, Rabby, and anything else that injects an EIP-1193 provider) press Sign message and approve — you will see the exact text before you do.
If the key lives in a script or on a hardware wallet, open Sign it
yourself instead, copy the message, and sign it with anything that does
personal_sign. From this repo:
This is the one place a wallet signature is genuinely required: the deposit carried no app credential, so nothing else can prove the wallet is yours. The signature is valid for ten minutes and grants no spending power — it only attaches a label.
A wrong or expired key costs you the attribution, not the deposit — the account is simply created unattached.
Seeing where your balance went
methods is sorted by CU, heaviest first, so the top row is whatever is
costing you the most. spentUnits is the same figure in USDC base units
if you would rather not reason in compute units.
Two fields worth watching:
rateLimitedclimbing means you are hitting your tier's requests-per-second ceiling. Deposit more to move up a tier rather than retrying into the same wall.cacheHitsare requests we served without touching an upstream. They still cost compute units; they are just faster.
Every request costs at least 1 CU, even methods the weight table prices at zero. Otherwise a single minimum deposit would buy unlimited service.
Running out, and topping up by itself
A wallet that runs dry does not need anyone to notice. Requests on a
drained key come back as 402 carrying fresh terms, so the same client
that paid the first time pays again and carries on. With an x402-aware
client that is the whole of it — no alerting, no cron, nobody woken up.
The top-up quote is what that wallet last paid, not the minimum. A bot running on 5 USDC top-ups is asked for 5 again, so it does not drain and re-negotiate every few minutes.
The 402 for a drained wallet carries an extra block a client can use to tell a top-up from a first purchase:
Conforming clients ignore it and just pay the amount in accepts.
Underneath, the key is moved to a 1 rps budget rather than switched off, so a plain client that does not understand 402 still limps along instead of failing outright.
If you would rather top up before running dry, poll
/v1/x402/account/<wallet> and deposit when balanceCu drops below
whatever margin suits your workload.
An empty wallet that stops calling entirely is closed after 72 hours and its key revoked.
If your key leaks
Sign a rotation message with the same wallet:
The message to sign is:
issuedAt must be within 5 minutes of the server's clock. The old key
stops working immediately.
Errors
| Code | Meaning |
|---|---|
disabled | x402 is not enabled on this deployment. |
not_configured | Enabled but the payment chain is not set up. Operator problem, not yours. |
domain_mismatch | The authorization pays someone other than the address in the challenge. |
signature_invalid | Signature does not match from, or was signed for a different chain or token. |
nonce_unknown | Reserved. Nonces are client-generated; replay is caught on-chain. |
nonce_replay | The token contract has already consumed this authorization. |
amount_too_small | Below minDepositUnits. The response repeats the current minimum. |
simulation_failed | The transfer would revert. Usually an under-funded wallet. Costs you nothing. |
capacity_full | No tier has room on the chains you asked for. |
wallet_blocked | The operator blocked this address. |
Gas
You never pay gas. The signed transfer is broadcast for you — normally by the network's x402 facilitator, which covers the gas itself, and by our own relayer if that facilitator is unreachable. Either way your wallet only ever spends the USDC in the authorization.
Limits
WebSocket endpoints are not available through x402 — connection-time billing is a different model. Use a normal API key for those.