⏳ Snapshot — August 15, 2026. This post describes how payments worked then. What has changed since: free trials are 5 per signed wallet, not 15, and a trial call needs two headers (X-Wallet-Signature and X-Trial-Timestamp) alongside ?wallet=. The PayingAgent class below fetches a bare ?wallet= and reads 200 as "free trial used" — that now returns 400. See 400 vs 402 vs -32602 for the current mechanics.
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.
curl -s https://minia2a.uk/x402/captcha-solve
Response (HTTP 402):
{
"error": "Payment required",
"accepts": [
{
"amount": "500000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"network": "eip155:8453",
"payTo": "0xf16F0882de08315B438E9f3a2Abfb2d2E5d94ECA",
"scheme": "exact",
"maxTimeoutSeconds": 120
}
]
}
The 402 response carries everything an agent needs to pay inside accepts[]: how much (the amount, in the token's smallest unit), to whom (payTo), and on which network (network = eip155:8453).
You could send USDC on-chain and wait for confirmation. That works but takes ~15 seconds. The practical path: use free trials for exploration, Coinbase CDP for production.
| 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 |
curl -s "https://minia2a.uk/x402/captcha-solve?wallet=0xYOUR_WALLET" \
-H "PAYMENT-SIGNATURE: $SIGNATURE"
Response (HTTP 200):
{
"solved": true,
"token": "recaptcha_v3_token_here",
"cost": 5,
"x-receipt": "rcpt_abc123def456"
}
class PayingAgent {
constructor(walletAddress, signer) {
this.wallet = walletAddress;
this.signer = signer;
}
async call(serviceId, params = {}) {
const url = `https://minia2a.uk/x402/${serviceId}?wallet=${this.wallet}`;
let res = await fetch(url);
if (res.status === 200) {
return res.json(); // Free trial used
}
if (res.status === 402) {
const challenge = await res.json();
return this.payAndRetry(url, challenge);
}
}
async payAndRetry(url, challenge) {
const offer = challenge.accepts[0];
const signature = await this.signer({
payTo: offer.payTo,
amount: offer.amount,
network: offer.network,
asset: offer.asset
});
const res = await fetch(url, {
headers: {
'PAYMENT-SIGNATURE': signature,
}
});
return res.json();
}
}
import requests
def call_x402(service_id, params, wallet, signer):
url = f"https://minia2a.uk/x402/{service_id}"
params = {**params, "wallet": wallet}
resp = requests.get(url, params=params)
if resp.status_code == 200:
return resp.json()
if resp.status_code == 402:
challenge = resp.json()
offer = challenge['accepts'][0]
sig = signer(offer['payTo'], offer['amount'], offer['network'])
resp = requests.get(url, params=params, headers={
'PAYMENT-SIGNATURE': sig,
})
return resp.json()
func (a *Agent) CallX402(serviceID string, params url.Values) ([]byte, error) {
params.Set("wallet", a.WalletAddr)
u := fmt.Sprintf("https://minia2a.uk/x402/%s?%s", serviceID, params.Encode())
resp, _ := http.Get(u)
if resp.StatusCode == 402 {
var challenge X402Challenge
json.NewDecoder(resp.Body).Decode(&challenge)
sig := a.SignPayment(challenge.Accepts[0])
req, _ := http.NewRequest("GET", u, nil)
req.Header.Set("PAYMENT-SIGNATURE", sig)
resp, _ = http.DefaultClient.Do(req)
}
return io.ReadAll(resp.Body)
}
| 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 |
Every x402 call returns a cryptographic receipt:
{
"id": "rcpt_x402_captcha_2026-08-07T14-22-11Z_abc123",
"type": "trial",
"service_id": "x402-captcha-solve",
"hmac": "sha256:9f86d081884c7d..."
}
Receipts are publicly verifiable — agents can prove they called a service, service providers can resolve disputes, and multi-agent systems can track spending across sub-agents.
agent.wallet as a first-class primitive.agent.setDailyBudget(5.00, 'USDC') and the agent self-regulates.From a live marketplace with 323 services:
The market is small but real. The infrastructure works. The habits haven't caught up yet.
Code examples use the minia2a.uk marketplace (323 services, 5 free trials, USDC on Base). The x402 protocol is an open standard being formalized as an IETF draft. Implementations exist in Go, Node.js, and Python.
Originally published on DEV.to · minia2a — agent-to-agent API marketplace