cd /news/ai-agents/we-gave-our-api-a-cash-register-then… · home › topics › ai-agents › article
[ARTICLE · art-169713] src=agentbadge.xyz ↗ pub= topic=ai-agents verified=true sentiment=· neutral

We Gave Our API a Cash Register. Then We Asked an AI to Rob It — x402 Gateway on Arc

An x402 payment gateway built on Arc by an unnamed development team charges per API request in USDC, with two pilot routes live behind a flag at $0.10 for a passport issuance and $0.02 for a premium FX feed. After 30 unit tests and 8 end-to-end tests passed, an Arc Studio adversarial AI audit returned a verdict of REQUEST CHANGES with 1 Critical, 6 High and 9 Medium findings, including a Critical flaw where payment settled on-chain but a database failure returned a 500 to the payer with no resource, no receipt and a spent nonce that made retry impossible. The team reports all 16 findings fixed with regression tests.

read6 min views1 publishedNov 14, 2026
We Gave Our API a Cash Register. Then We Asked an AI to Rob It — x402 Gateway on Arc
Image: Agentbadge (auto-discovered)

Agents calling APIs have no checkout page or API key signup — they have a wallet. We built an x402 payment gateway on Arc: request → 402 challenge → signed USDC payment → resource, in one round trip. Two pilot routes live behind a flag ($0.10 passport, $0.02 FX feed), legacy rails untouched. Then an adversarial AI audit found the hole our 34 green tests missed: payment settled on-chain, accounting crashed, payer got a 500 with no receipt and a spent nonce. 1 Critical + 6 High + 9 Medium — all fixed with regression tests.

Agents that call APIs have no checkout page, no credit card, and no API key signup — so we built an x402 payment gateway that charges per request in USDC on Arc. The flow is HTTP's forgotten 402 status finally doing its job: request → 402 challenge → signed payment → resource. Two pilot routes went live behind a flag: $0.10 for a passport issuance, $0.02 for a premium FX feed — while the legacy routes stay untouched. Then we pointed an adversarial AI audit at the money path, and it found the hole that would have taken real funds: payment settled on-chain, accounting crashed, payer got a 500 with no resource and no receipt — and the spent nonce made a retry impossible. One Critical, six High, nine Medium findings, all fixed with regression tests.

Why would a machine need a cash register? #

Because every other way of charging for an API assumes a human. Stripe checkout assumes a person with a card and a browser. API keys assume someone who registered an account first. An autonomous agent has none of that — it has a wallet. x402 is the pattern where HTTP status 402 Payment Required becomes real: the server answers a request not with a login page but with a price tag, and the client retries the same request carrying a cryptographic payment proof.

For a junior: think of a vending machine instead of a supermarket. No account, no cart, no checkout wizard. You walk up with exact change, the machine prices the item, takes the coin, and gives you the thing plus a receipt — all in one interaction. Our gateway is that vending machine for HTTP resources, built on the payment rails from the previous episodes.

How does the 402 loop work? #

In four layers, bottom to top. Everything the client sees is derived server-side — the price, the network, the recipient — so a client can never say "I paid" for a resource that wasn't charged.

Domain types live in the payments package; transport lives in the server; settlement stays in the existing seam.

  1. Registry — aPaidResource declaresid, method, path, priceUsd, network . Unregistered routes pass the gate untouched, so the gateway is strictly opt-in per route.
  2. Price resolution — a catalog-firstPriceResolver , falling back to the registry's declared price. Resolved USD is converted to USDC atomic units at the boundary.
  3. Service facade — builds the payment requirements, delegates verify+settle to the existing x402 seam (the same one the legacy routes use — we didn't reimplement settlement), appends aUsageRecord , and resolvesagentId from the payer's wallet binding — ornull when unbound.
  4. Middleware — the Hono gate. NoPAYMENT-SIGNATURE header → spec-compliant402 + PAYMENT-REQUIRED . Signature present → settle → record usage →PAYMENT-RESPONSE receipt header → serve the resource.

One round trip for the price tag, one for the goods. The receipt travels in the response header.

What did the adversarial audit break? #

After the pilots shipped — 30 unit tests + 8 end-to-end tests, all green — we ran an Arc Studio adversarial review. Verdict: REQUEST CHANGES — 1 Critical, 6 High, 9 Medium. The green tests had covered the happy path and the "payment rejected" path. The audit covered the third path: payment accepted, then something else breaks.

  • C-1 — paid but nothing received. Settlement succeeded on-chain, then a database hiccup in the usage-record write threw a bare 500. The payer's nonce was already spent, so a retry could never recover — no resource, no record, no receipt. Now: post-settle accounting is wrapped so a paid requestalways serves the resource and emitsPAYMENT-RESPONSE ; failures are logged as reconciliation records instead.
  • H-1 — the free HEAD request. Hono answersHEAD through theGET handler, but our route lookup matched methods exactly —HEAD /api/v1/fx/delta/premium skipped the gate entirely. Now HEAD is normalized to GET before lookup.
  • H-2 — client-controlled dedupe key.x-request-id anchored usage dedupe; a client could reuse it across different payments and silently suppress records. The anchor is now the settlement tx — cryptographically unique per payment.
  • H-3 — charge first, fail later. Settlement ran before the handler even existed in memory; a dead downstream engine meant a paid 503. ApreCheck now refuses unbootable requestsbefore the 402 challenge — you can't be charged for what can't be served.
  • H-5 — wrong attribution. The usage record wrote the registry's declared network instead of what actually settled. Now it recordssettle.sourceChain , and the advertised accepts are filtered to the resource's own network.
  • H-6 — a mount that leaked.app.route("/api/v1", passportRoutes) exposed every future passport route under the paid prefix. The pilot now mounts the single handler explicitly.

The audit found the gap between "payment succeeded" and "resource served" — the seam every money path is made of.

What's live and how do I try it? #

Behind X402_GATEWAY_ENABLED on Arc testnet — Arc USDC only in v1:

  • POST https://agentbadge.xyz/api/v1/passport/request —$0.10 , issues an agent passport (same handler as the legacy route)
  • GET https://agentbadge.xyz/api/v1/fx/delta/premium —$0.02 , premium FX-delta snapshot +payment: {txHash, network, amount, receiptId} in the body

The two pilot slots: same handlers as the legacy rails, now reachable by a machine carrying coins.

Registering a new paid resource is a registry entry, not a new code path: { id, method, path, priceUsd, network }. The middleware, challenge, settlement, usage record and receipt come free.

What are the honest limits? #

  • Pilots, not production. Two routes, flag-gated, Arc testnet. The legacy passport rail and the Celo FX gate are untouched on purpose — migration is additive, never a silent swap.
  • No live numbers yet. End-to-end is proven with the seam stubbed at the boundary (8 e2e tests). Real testnet txs through the gateway haven't run at press time — we say so rather than quote a receipt count we don't have.
  • Bearer payments. A valid signature pays; it isn't bound to a specific resource by the wire protocol. That's x402's design, and the mitigation lives in the requirements the server derives, not in the client's wallet.
  • One audit. Adversarial review we fixed and re-verified, not a formal verification. The regression tests — HEAD gating, zero-price, post-settle crash, engine-off refusal — are the artifact that outlives this article.

The deeper principle is the same one the reconciliation episode ended on: a chain payment isn't an event you receive, it's a claim you verify — and this episode adds the other half: once verified, everything after the money moves is customer service, and it must never cancel the sale.

── more in #ai-agents 4 stories · sorted by recency
── more on @x402 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/we-gave-our-api-a-ca…] indexed:0 read:6min 2026-11-14 · —