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

> Published: 2026-11-14 | Author: AgentBadge Team | Canonical: https://agentbadge.xyz/blog/arc-c50-x402-gateway

## 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. 

![Flowchart of the gateway's four layers: a PaidResource registry resolves a route into a resource and price; a PriceResolver can override the catalog price; the X402PaymentService builds requirements and delegates verification and settlement to the existing seam; the Hono middleware either answers a 402 challenge or lets a settled request through and records a UsageRecord](/images/blog/arc-c50-x402-gateway-d2.webp)

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

1.  **Registry** — a PaidResource declares id, method, path, priceUsd, network. Unregistered routes pass the gate untouched, so the gateway is strictly opt-in per route. 

2.  **Price resolution** — a catalog-first PriceResolver, 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 a UsageRecord, and resolves agentId from the payer's wallet binding — or null when unbound. 

4.  **Middleware** — the Hono gate. No PAYMENT-SIGNATURE header → spec-compliant 402 + PAYMENT-REQUIRED. Signature present → settle → record usage → PAYMENT-RESPONSE receipt header → serve the resource. 

![Sequence diagram of one paid request: agent GETs /api/v1/fx/delta/premium without a signature and gets 402 + PAYMENT-REQUIRED with server-derived accepts; the agent signs an EIP-3009 authorization and retries with PAYMENT-SIGNATURE; the seam verifies and settles on Arc; usage and payer binding are recorded; the handler returns 200 + PAYMENT-RESPONSE + payment{} in the body](/images/blog/arc-c50-x402-gateway-d1.webp)

* 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 request *always* serves the resource and emits PAYMENT-RESPONSE; failures are logged as reconciliation records instead. 

-  **H-1 — the free HEAD request.** Hono answers HEAD through the GET 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. A preCheck now refuses unbootable requests *before* 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 records settle.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. 

![A magnifying glass hovering over a glowing pipeline joint between a settled block and a usage record block, the joint burning red where the audit found the unguarded post-settle code path](/images/blog/arc-c50-x402-gateway-audit.webp)

* 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 

![Two vending-machine slots on a dark panel — $0.10 dispensing a passport card, $0.02 dispensing an FX chart card, with a TESTNET ribbon in the corner](/images/blog/arc-c50-x402-gateway-pilots.webp)

* 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.* 

## For AI Agents

 Machine-readable summary: this gateway gates /{method,path} pairs by a PaidResource registry, issues HTTP 402 + PAYMENT-REQUIRED (official @x402/core/http helpers) with server-derived accepts[], verifies+settles via the shared x402 seam, and returns PAYMENT-RESPONSE + a JSON payment{} receipt field. Priced pilots on Arc testnet: POST /api/v1/passport/request ($0.10 USDC), GET /api/v1/fx/delta/premium ($0.02 USDC). Dedupe anchor = settlement tx; agentId resolves from payer wallet binding (null when unbound). 

 If you're human and still here: the registry file is 40 lines, the middleware is 120, and the audit report is public in the repo docs. Steal the pattern — the C-1 fix alone is worth the read. 

* Stack: @agentbadge/payments (pure TS domain) + @x402/core official header helpers, Bun + Hono, existing x402-settle-seam for verify/settle, Arc testnet USDC (eip155:5042002). 30 unit + 8 e2e tests green; audit findings + triage table in docs/EPICS/223-x402-payment-gateway/reviews/x402-gateway-REVIEW.md. *

---

## For AI Agents

- Companion guide: https://agentbadge.xyz/agent-guide/articles/arc-c50-x402-gateway
- Knowledge Index: https://agentbadge.xyz/agent-guide/
- LLM entry point: https://agentbadge.xyz/llms.txt
- Engineering services: https://agentbadge.xyz/agent-guide/team/services
