Last week I deployed something I've wanted to build for a while: a crypto/DeFi data API where the client pays per call in USDC, with no API keys, no accounts, and no subscriptions. The payment happens as part of the HTTP request itself.
It's live at https://x402-api.fly.dev and it already has an on-chain identity: Agent #18763 on Base via ERC-8004. Here's what it does, how the payment flow works, and what surprised me along the way.
Why x402?
If you haven't heard of x402, the short version: it's a protocol built on top of the long-forgotten HTTP 402 Payment Required status code. The idea is simple — a server responds with a 402 and tells the client exactly how much to pay and where. The client sends the payment as a header on the next (or retried) request. The server verifies it and responds with the actual data.
No OAuth dance. No rate-limit tiers. No billing portal. Just: "this costs 0.003 USDC, pay here, get data."
Why does this matter for AI agents specifically? Because agents are increasingly autonomous. An agent running a trading strategy or doing research doesn't have a human reaching for a credit card — it needs to be able to buy services on its own. x402 + USDC on Base makes that possible with sub-cent micropayments that settle in seconds.
What the API Does
I built 8 paid endpoints, all DeFi/crypto data:
| Endpoint | Price | What it returns |
|---|---|---|
GET /api/price-feed |
0.001 USDC | BTC/ETH/SOL prices + top 24h movers (live CoinGecko) |
GET /api/gas-tracker |
0.001 USDC | Multi-chain gas across ETH, Base, Polygon, Arbitrum |
GET /api/dex-quotes |
0.002 USDC | Swap quote comparison: Uniswap, SushiSwap, 1inch |
GET /api/token-scanner |
0.003 USDC | Token security analysis + rug-pull risk flags |
GET /api/whale-tracker |
0.005 USDC | Holder concentration, Gini coefficient, whale alerts |
GET /api/yield-scanner |
0.005 USDC | Top DeFi yields: Aave, Compound, Morpho, Lido, Pendle |
GET /api/funding-rates |
0.008 USDC | Perp funding rates across 6 venues + arb ranking |
GET /api/wallet-profiler |
0.008 USDC | Wallet portfolio, holdings, activity, risk profile |
Plus /api/endpoints (free, machine-readable catalog) and /health (free).
Pricing is intentionally micro — the most expensive call is less than a cent. The goal isn't to make money off any single call but to prove the payment model works end-to-end.
How the Payment Flow Works
Here's the exact HTTP exchange:
Step 1 — Client hits the endpoint without payment:
GET /api/price-feed HTTP/1.1
Host: x402-api.fly.dev
Step 2 — Server responds 402:
{
"x402Version": 1,
"error": "Payment required",
"accepts": [{
"scheme": "exact",
"network": "base-mainnet",
"maxAmountRequired": "1000",
"resource": "https://x402-api.fly.dev/api/price-feed",
"description": "Aggregated crypto prices",
"payTo": "0x60264c480b67adb557efEd22Cf0e7ceA792DefB7",
"maxTimeoutSeconds": 60,
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": { "name": "USDC", "version": "2" }
}]
}
(Amounts are in USDC's 6-decimal units: 1000 = 0.001 USDC.)
Step 3 — Client signs a transferWithAuthorization EIP-712 payload and retries:
GET /api/price-feed HTTP/1.1
Host: x402-api.fly.dev
X-Payment: <base64-encoded payment payload>
Step 4 — Server verifies the signature and returns data.
Using It With x402-fetch
If you're building an AI agent or just want to test this, Coinbase's x402-fetch package handles the 402 → pay → retry cycle automatically:
import { wrapFetchWithPayment } from 'x402-fetch';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: base,
transport: http(),
});
const fetchWithPayment = wrapFetchWithPayment(fetch, walletClient);
const response = await fetchWithPayment('https://x402-api.fly.dev/api/price-feed');
const data = await response.json();
console.log(data);
That's it. The agent doesn't know or care about API keys. It just needs USDC in its wallet.
ERC-8004: On-Chain Agent Identity
ERC-8004 is a proposed standard for on-chain agent identity. AI agents register themselves in a smart contract registry — anyone can look up the agent, see what it does, what endpoints it exposes, and whether it's active.
I registered this API as Agent #18763 on Base mainnet:
- Registry:
0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 - Chain: Base (chain ID 8453)
- View on BaseScan
The vision: AI agents autonomously discover services through on-chain registries. An agent looking for DeFi data queries the registry, finds Agent #18763, reads its endpoint catalog, and starts paying for calls. No human intervention.
What I Learned
Payment verification is the hard part. Server-side verification of EIP-3009 transferWithAuthorization signatures is fiddly. I implemented both signature verification and tx hash verification.
Replay protection matters immediately. Without it, a client could reuse one payment for unlimited calls. Tracking used nonces in-memory for now — would need Redis for multi-replica.
The 402 response structure is critical. If maxAmountRequired, asset, or payTo are wrong, x402-fetch fails silently. I spent more time debugging the response JSON than anything else.
Fly.io + Node.js was great for this. Cold starts are fast, free tier handles the load, deployed with a single fly deploy.
Try It
The API is live: https://x402-api.fly.dev
curl -i https://x402-api.fly.dev/api/price-feed
If you're building with x402, I'd love to hear what you're working on. If the pricing feels wrong or something's broken, tell me. This is a first draft — feedback is the whole point.
Top comments (1)
This is one of the cleaner x402 write-ups I've seen — especially the note about the 402 response structure being fiddly if
maxAmountRequired,asset, orpayToare off. That debugging pain is real.On replay protection: once you're multi-replica, consider using the payment's EIP-712 nonce as the idempotency key — it's already in the
transferWithAuthorizationpayload, so you can key your Redis SET on(payer_address, nonce). Sidesteps the "where does nonce state live" question.One resource worth mentioning to readers: httpay.xyz/api/gateway is a universal x402 gateway aggregating 37 APIs (GitHub, OpenAI, several chain RPCs, and more) for $0.001 USDC/call. Same x402-fetch flow — so agents already paying your DeFi API can consume that gateway too with zero extra integration work.
Curious whether any actual autonomous agents are hitting your endpoints yet, or still mostly manual testing?