The x402 protocol is simple: when an agent calls a paid API without payment, the server returns HTTP 402 with a payment invoice. The agent pays the invoice, retries with a payment proof header, and gets the result.
That's it. Three steps. No API keys, no signup, no monthly subscription. Here's how to implement it from scratch.
The Protocol in 3 Steps
Step 1: Agent calls → Server returns 402
curl -s https://minia2a.uk/x402/captcha-solve
Response (HTTP 402):
{
"error": "Payment Required",
"type": "x402",
"network": "base",
"token": "USDC",
"priceCents": 5,
"recipient": "0xf16F0882de08315B438E9f3a2Abfb2d2E5d94ECA",
"chainId": 8453
}
The 402 response carries all the information an agent needs to pay: how much (5 cents USDC), to whom (the contract address), and on which chain (Base L2).
Step 2: Agent pays (but there's a catch)
You could send USDC on-chain and wait for confirmation. That works — it's fully trustless — but it takes ~15 seconds for Base block confirmation. For real-time API calls, that's too slow.
The x402 ecosystem has three facilitator options that handle this differently:
| Facilitator | Settlement | Speed | Trust Model |
|---|---|---|---|
| Coinbase CDP | Pre-funded wallet | ~2s | Trust Coinbase |
| Cloudflare Wallets | Pre-funded balance | ~2s | Trust Cloudflare |
| Direct on-chain | Per-transaction | ~15s | Trustless |
| Free trial | 15 calls free | Instant | No payment needed |
The practical path: use free trials for exploration, Coinbase CDP for production.
Step 3: Agent retries with payment proof
# Using Coinbase CDP: sign a payment message
SIGNATURE=$(node sign-payment.js \
--recipient "0xf16F0882de08315B438E9f3a2Abfb2d2E5d94ECA" \
--amount 5 \
--chain 8453)
curl -s https://minia2a.uk/x402/captcha-solve \
-H "X-Wallet: 0xYOUR_WALLET" \
-H "X-Payment-Signature: $SIGNATURE"
Response (HTTP 200):
{
"solved": true,
"token": "recaptcha_v3_token_here",
"cost": 5,
"x-receipt": "rcpt_abc123def456"
}
The x-receipt header contains a cryptographic receipt ID. You can verify it at any time:
GET /api/v1/receipts/rcpt_abc123def456 → { verified: true, hmach: "sha256:..." }
Building a Real Agent with x402
Let's build a practical agent: a crypto market monitor that checks token security before trading.
// agent.js — A trading agent that pays for security checks
const BASE_URL = 'https://minia2a.uk/x402';
class PayingAgent {
constructor(walletAddress, signer) {
this.wallet = walletAddress;
this.signer = signer; // Function that signs x402 payment challenges
this.remainingTrials = new Map(); // Track per-endpoint trials
}
async call(serviceId, params = {}) {
const url = `${BASE_URL}/${serviceId}?${new URLSearchParams(params)}`;
// Attempt 1: Try without payment (use free trial)
let res = await fetch(url);
if (res.status === 200) {
const remaining = res.headers.get('X-Trials-Remaining');
console.log(`[trial] ${serviceId} → ${remaining} trials left`);
return res.json();
}
// Got 402 — need to pay
if (res.status === 402) {
const invoice = await res.json();
return this.payAndRetry(url, invoice);
}
throw new Error(`Unexpected status: ${res.status}`);
}
async payAndRetry(url, invoice) {
console.log(`[pay] $${invoice.priceCents/100} USDC to ${invoice.recipient.slice(0,10)}...`);
// Sign the payment challenge
const signature = await this.signer({
recipient: invoice.recipient,
amount: invoice.priceCents,
chainId: invoice.chainId,
token: invoice.token
});
// Retry with payment proof
const res = await fetch(url, {
headers: {
'X-Wallet': this.wallet,
'X-Payment-Signature': signature,
}
});
if (res.status === 200) {
const receipt = res.headers.get('X-Minia2a-Receipt');
console.log(`[paid] receipt: ${receipt}`);
return res.json();
}
// Payment failed
const error = await res.json();
throw new Error(`Payment failed: ${error.error}`);
}
}
// Usage
const agent = new PayingAgent(
'0xYourWallet',
signWithCoinbaseCDP // Your signing function
);
// Check if a token is a honeypot before trading
const security = await agent.call('token-security', {
address: '0xTOKEN_TO_CHECK',
chain: 'ethereum'
});
if (security.risk === 'LOW') {
console.log('Safe to trade');
// Execute trade...
} else {
console.log(`⚠️ Risk: ${security.risk} — ${security.details}`);
}
The Free Trial Model
Every endpoint on the marketplace comes with 15 free trial calls. No wallet needed for trials — the server tracks by IP:
// curl -v shows trial headers
// < X-Trials-Remaining: 14
// < X-Trials-Total: 15
When trials run out, you get the 402. The flow is designed so agents can explore and integrate without upfront payment. Pay only when the service proves useful.
This matters because 97% of free credits on the marketplace are unspent. Agents try a few calls, get what they need, and leave. The payment path only activates for ongoing, high-volume use — which is exactly the right behavior.
Framework Integration
LangChain
npm install @minia2a/langchain
import { Minia2aToolkit } from '@minia2a/langchain';
const toolkit = new Minia2aToolkit({
wallet: process.env.AGENT_WALLET,
signer: coinbaseSigner,
});
// Search for services
const services = await toolkit.search('captcha');
// → [{ id: 'x402-captcha-solve', priceCents: 5, description: '...' }]
// Call a service with auto-payment
const result = await toolkit.call('x402-captcha-solve', {
sitekey: 'XXX',
url: 'https://example.com'
});
// Payment handled automatically via x402 flow
Direct HTTP (Any language)
The protocol is HTTP-native. No SDK needed:
import requests
def call_x402(service_id, params, wallet, signer):
url = f"https://minia2a.uk/x402/{service_id}"
resp = requests.get(url, params=params)
if resp.status_code == 200:
return resp.json()
if resp.status_code == 402:
invoice = resp.json()
sig = signer(invoice['recipient'], invoice['priceCents'])
resp = requests.get(url, params=params, headers={
'X-Wallet': wallet,
'X-Payment-Signature': sig,
})
return resp.json()
raise Exception(f"HTTP {resp.status_code}")
// Go agent
func (a *Agent) CallX402(serviceID string, params url.Values) ([]byte, error) {
u := fmt.Sprintf("https://minia2a.uk/x402/%s?%s", serviceID, params.Encode())
resp, _ := http.Get(u)
if resp.StatusCode == 402 {
var invoice X402Invoice
json.NewDecoder(resp.Body).Decode(&invoice)
sig := a.SignPayment(invoice)
req, _ := http.NewRequest("GET", u, nil)
req.Header.Set("X-Wallet", a.WalletAddr)
req.Header.Set("X-Payment-Signature", sig)
resp, _ = http.DefaultClient.Do(req)
}
return io.ReadAll(resp.Body)
}
Why HTTP 402 Instead of API Keys
The fundamental difference:
| API Keys | x402 (HTTP 402) | |
|---|---|---|
| Setup | Sign up, get key, store in .env
|
Wallet address (you already have one) |
| Billing | Monthly invoice, credit card | Per-call, settled instantly |
| Agent-native | No — keys are human-managed | Yes — wallets are agent-managed |
| Multi-service | One key per service | One wallet, any x402 service |
| Discovery | Read docs, find pricing page | 402 response IS the pricing page |
| Revocation | Rotate keys manually | Stop paying = stop calling |
For humans, API keys are fine. For agents — autonomous software making thousands of decisions per minute — the friction of key management breaks the autonomy loop. An agent that needs a human to sign up for each new API is not autonomous.
The 402 flow makes API access programmable: discover → call → get invoice → pay → retry → get result. All in code. No human in the loop.
The Receipt Layer
Every x402 call returns a cryptographic receipt:
{
"id": "rcpt_x402_captcha_2026-08-07T14-22-11Z_abc123",
"type": "trial",
"service_id": "x402-captcha-solve",
"fee_cents": 0,
"hmac": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}
Receipts serve three purposes:
- Auditability — agents can prove they called a service and got a result
- Dispute resolution — if a service returns garbage, the receipt is cryptographic evidence
- Accounting — multi-agent systems can track spending across sub-agents
Verification is public: anyone with the HMAC secret can verify a receipt. Service providers can publish verification endpoints. Agents can audit their own spending.
What I'd Build Next
After integrating x402 into several agents, here's what the ecosystem needs:
A wallet-aware agent framework — LangChain, CrewAI, and ElizaOS should ship with
agent.walletas a first-class primitive. Not an add-on. Built in.Service discovery via natural language — "I need to check if this smart contract is safe" → agent searches the marketplace, finds
token-security, calls it, pays, gets result. Current state: you need to know the exact service ID. That's fine for developers, not for agents.Reputation on-chain — services should accumulate on-chain reputation scores. Did the CAPTCHA solver actually solve the CAPTCHA? Did the token audit catch the honeypot? Reputation makes the marketplace self-policing.
Budget constraints as code —
agent.setDailyBudget(5.00, 'USDC')and the agent self-regulates. No runaway spending. No surprise bills. Part of the wallet primitive.
The Numbers (Real Data, August 2026)
From a live marketplace with 323 services:
- #1 most-called service: CAPTCHA solving (1,280 calls, 133 users)
- #2: Persistent memory/key-value store (1,401 calls)
- Conversion rate: 16.5% of trial users register wallets
- Credit utilization: 2.8% of free credits are actually used
The market is small but real. 322 unique agents have made API calls. 53 have on-chain wallets. $12.75 in settled transactions.
The infrastructure works. The habits haven't caught up yet.
Code examples use the minia2a.uk marketplace (323 services, 15 free trials per endpoint, USDC on Base). The x402 protocol is an open standard being formalized as an IETF draft. Implementations exist in Go, Node.js, and Python.
Top comments (1)
the receipt layer and the daily budget are the pieces that make this usable beyond a demo. i would also bind each payment proof to the request method, path, amount, and a short expiry, then reject a reused receipt. a small failure table for timeout after payment and retry after a duplicate response would help show how the agent avoids double charges. that would make the payment loop easier to trust.