x402 lets a program pay for an HTTP resource without an account, an API key or a checkout page. The server answers 402 Payment Required with machine-readable payment terms, the client signs a USDC transfer authorization, sends the same request again with that signature, and receives the resource once a facilitator has settled the payment on-chain.
This guide walks through one real exchange with this site, which sells its packs over x402 on Base mainnet. Every header and field below comes from the live server, so you can reproduce each step with curl before writing any agent code.
The four steps
- The agent requests the resource:
GET /api/v1/pack/{pack_id}. - The server answers
402with aPAYMENT-REQUIREDheader describing what it accepts. - The agent signs an EIP-3009
TransferWithAuthorizationfor the exact amount and retries the request with aPAYMENT-SIGNATUREheader. - The server has the payment verified and settled by a facilitator, then answers
200with the file and aPAYMENT-RESPONSEheader carrying the settlement result.
The payer never sends a transaction itself and needs no ETH for gas: the facilitator submits the signed authorization.
Step 1 and 2: read the payment terms
Ask for a paid pack without paying:
curl -si https://theautonomousstack.xyz/api/v1/pack/agent-a11y-v1 | head -5
The status is HTTP/2 402 and the terms travel in the payment-required header as base64-encoded JSON. Decode it:
curl -si https://theautonomousstack.xyz/api/v1/pack/agent-a11y-v1 \
| grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' \
| base64 -d | python3 -m json.tool
You get (description shortened):
{
"x402Version": 2,
"error": "Payment required",
"resource": {
"url": "/api/v1/pack/agent-a11y-v1",
"description": "Agent A11y Pack v2.0. Offline-first WCAG accessibility auditor...",
"mimeType": "application/zip"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "3000000",
"payTo": "0x8634Fd2f105F3274627f5eF4F785fE0C0aA55D14",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}
]
}
What each field tells the agent:
| Field | Meaning |
|---|---|
scheme: exact |
Pay exactly amount, no more, no less. |
network: eip155:8453 |
Base mainnet, written as a CAIP-2 chain id. |
asset |
The token contract: native USDC on Base. |
amount |
In the token's smallest unit. USDC has 6 decimals, so 3000000 is 3.00 USDC. |
payTo |
The address that receives the funds. |
maxTimeoutSeconds |
How long the signed authorization may stay valid. |
extra.name, extra.version |
The EIP-712 domain of the token contract, needed to sign. |
accepts is a list. A server can offer several networks or assets; the agent picks one it can pay.
Step 3: sign the authorization
USDC implements EIP-3009, which lets a holder sign a transfer that someone else submits. The agent signs a typed message (EIP-712) with:
- Domain:
nameandversionfromextra,chainId8453,verifyingContract=asset. - Message:
from(the agent wallet),to(=payTo),value(=amount),validAfter,validBefore(now + at mostmaxTimeoutSeconds), and a random 32-bytenonce.
The signature and the authorization fields are wrapped in a payment payload together with the requirement the agent chose, base64-encoded, and sent back on the same URL:
GET /api/v1/pack/agent-a11y-v1
PAYMENT-SIGNATURE: <base64 payment payload>
Do not hand-roll this encoding in production. The official x402 libraries (Python, TypeScript, Go) in the x402 repository build the payload, sign it with your wallet and retry the request for you. Use them, and keep your own code focused on the decision to pay.
Step 4: receive the file and keep the receipt
If the facilitator verifies the signature and settles the transfer, the server answers 200 OK with application/zip and a PAYMENT-RESPONSE header. That header holds the settlement result, including the transaction hash. Store it with the order: it is the proof that this download was paid, and the only record your agent will have if a delivery is disputed.
If settlement fails, no file is served and nothing is charged.
Rules an agent should apply before signing
A paying agent is a program that spends money on its own. These checks are cheap and they matter more than the signing code:
- Check the terms against what you expected. Network, asset address,
payToandamountmust match a list you control. Reject a 402 that asks for a different token or a different chain, even if it is cheaper. - Cap the spend. Keep a per-request maximum and a daily budget in the agent, outside the model. A model should never be the component that decides the limit.
- Keep validity short. Set
validBeforeclose to now. A leaked signature then expires quickly. - Use a fresh random nonce every time. EIP-3009 rejects a reused nonce, which is what prevents replay.
- Use a dedicated wallet holding only what the agent may spend.
- Log every 402, every signature and every settlement, with the resource URL. You need this to reconcile later.
Finding things to buy
An agent cannot pay for what it cannot find. This site exposes its catalog in several machine-readable forms:
GET /api/v1/packsandGET /api/v1/packs/{pack_id}: JSON metadata, file list, price in USDC, network and asset.GET /api/v1/discover: a JSON-LD description of the catalog./openapi.jsonfor the API and/llms.txtfor language models.
Try the flow without paying
The Free Sample Agent is served without payment at GET /api/v1/free/agent-sample-free-v1, so you can test download, unzip and install before wiring a wallet. It is a small but real pack with the same structure as the paid ones.
If you sell over x402
The seller side has its own bookkeeping problem: a settlement header is not yet a reconciled invoice. Three packs work on that evidence, all with a deterministic core and no model needed:
- Agent Payment Reconciliation Pack matches receipts to invoices and flags wrong assets, underpayments, duplicate transaction hashes and receipts that match no invoice. It never moves money.
- Agent Usage Meter turns tool-call logs into billable totals before anything is charged, and lists duplicates and calls without an authorization.
- Agent Escrow Release decides whether held funds may be released from signed delivery evidence, and leaves the final release to a human.
Limits worth knowing
- x402 settles in seconds, but it is still an on-chain transfer: it is final. Refunds are a separate payment.
- The payer needs USDC on the right network. Holding USDC on another chain does not help.
- A facilitator outage blocks payments for every seller that uses it. On this site, a payment is refused without any debit while the facilitator is unreachable.
Where to start
- Run the two
curlcommands above and read the decoded terms. - Download the free sample to test the rest of your pipeline.
- Add the pre-signing checks to your agent, then let an official x402 client do the signing.