x402pricingagentspost-mortem
The shelf price must equal the till price: fixing silent price drift in an x402 API catalog
Money Reactor · 2026-10-22 · 22 pay-per-call endpoints, x402 v1/v2, USDC on Base
Money Reactor is a live x402-native API suite: no signup, no API keys — an agent sends an HTTP request, gets a 402 with a payment-required envelope, pays in USDC on Base, retries with the proof and gets the answer. This post is the post-mortem of a bug that almost certainly cost us paying agents for days, because it is invisible in every dashboard: the price in the discovery catalog and the price in the 402 challenge were not the same number.
1. What drift looks like in practice
Our discovery catalog (served at /.well-known/x402.json, mirrored into CDP Bazaar and other indexes) listed mass-market endpoints at $0.001–$0.003. But the 402 challenge was built from a different, hardcoded layer — an old pricing table pasted into the discovery-building code. So an agent that read the catalog, decided the call was worth $0.001, then received a $0.005 challenge, did what any rational buyer does: aborted the transaction silently. No error telemetry reaches the seller on abort; the funnel just shows challenges without attempts. We watched 800+ challenges a day with zero payment attempts and the only honest explanation was price mismatch between what the agent agreed to and what we asked for.
2. The architecture rule that kills drift
The fix is not "remember to update both places". The fix is to make the second place not exist. Every price now lives in one place as an integer in micro-USDC units, and both the catalog builder and the 402 envelope builder derive from the same constants:
const PRICE_WEATHER = 2000; // micro-USDC = $0.002
acceptsV2(micro(PRICE_WEATHER)) // challenge: "2000" = $0.002
discoveryEntry(PRICE_WEATHER) // catalog: "$0.002"
One source of truth, one unit (micro-USDC integers — never floats), two projections. A price change is a one-line diff, and the catalog and the challenge cannot disagree by construction. If you are building an x402 seller today, steal this rule: the shelf price is the till price, enforced by code, not by discipline.
3. The trust ladder (why 13 endpoints are $0.001)
We also reset the price architecture to a trust ladder, because a new pay-per-call seller has no reputation and must buy its first reviews with cheap calls:
| Tier | Price | Endpoints |
|---|---|---|
| Impulse tier | $0.001 | bounties radar, honeypot check, repo verdict, crypto-price, usd-price, fear-greed, crypto-news, erc20-balance, base-gas, btc-halving, time, uuid, block-number |
| Workhorse tier | $0.002–$0.003 | weather, ai-chat, coin-convert, market-pulse, url-to-text, wallet-profile |
| Premium tier | $0.01–$0.05 | token-verdict (rug-check), starter-kit, dossier |
Every entry in the catalog now carries a "Use when…" sentence — the phrase agents (and Bazaar ranking) actually match against. When you list on machine-readable marketplaces, write the use-when first and the marketing never.
4. Verify it yourself in one request
No signup, no key. Pick any endpoint from the catalog, call it, read the 402 — the amount you see is the amount you pay, exactly what the catalog promised:
curl -s https://money-reactor.makar52nn2016.workers.dev/api/weather?city=London
# 402 + PAYMENT-REQUIRED header: amount "2000" (micro-USDC) = $0.002 = catalog price
https://money-reactor.makar52nn2016.workers.dev/mcp · live stats: /api/statusMore seller notes: buyer cookbook · how to verify an x402 seller · traction report with on-chain receipts