Docs

undo402 is a gateway in front of x402 endpoints on Robinhood Chain. Sellers stake USDG. When a buyer pays through the gateway and the seller fails to deliver, the buyer is refunded from that stake.

Nothing about x402 changes for you. You call a different URL, and you get a receipt ID back.

For buyers

  1. Find the seller in the directory and copy its gateway URL.
  2. Call that URL exactly as you would call the seller. Pay the 402 the usual way.
  3. Keep the X-BOND-RECEIPT header. X-BOND-RECEIPT-URL is a ready-made link to track the payment.
# before GET https://api.example.xyz/holders?token=0x… # after: same request, covered GET https://<this site>/s/holder-data/holders?token=0x…

The gateway only shows you payment options the bond covers: scheme exact, USDG on Robinhood Chain, the seller's registered address, at or under the registered price. A payment to any other address is stopped before it reaches the seller.

For agents

Three ways in, from no setup to full control.

1. Remote MCP, nothing to install

Add this URL to any MCP client that supports Streamable HTTP. The agent can find covered APIs, read their record and follow receipts. It cannot pay; for that use 2 or 3.

https://<this site>/mcp

2. Local MCP that pays

Runs on your machine with a wallet you give it and hard spending limits. Tools: find_apis, call_api, track_payment, wallet_status.

{ "mcpServers": { "undo402": { "command": "npx", "args": ["-y", "-p", "undo402", "undo402-mcp"], "env": { "UNDO402_GATEWAY": "https://<this site>", "UNDO402_PRIVATE_KEY": "0x…", "UNDO402_MAX_PER_CALL_USD": "0.05", "UNDO402_MAX_TOTAL_USD": "1" } } } }

Use a wallet that holds only what the agent may spend. By default it only pays gateway URLs, so every paid call is covered.

3. SDK in your own code

import { createClient, usd } from "undo402"; const client = createClient({ account: process.env.AGENT_KEY, // 0x private key or a viem account maxPerCall: usd(0.05), maxTotal: usd(5), allowedPrefixes: ["https://<this site>/s/"], // only pay covered calls }); const { response, paid, receipt } = await client.fetch("https://<this site>/s/{seller}/…"); // receipt.url tracks the call and any refund

Allowlist feed

Without MCP or the SDK, read the allowlist and only pay hosts on it. It lists endpoints that passed their recent liveness checks and hold a live bond. Refresh it every few minutes.

GET /api/directory/allowlist { "network": "eip155:4663", "asset": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "endpoints": [ { "id": "holder-data", "url": "https://<this site>/s/holder-data", "price": "500000", "payTo": "0x…", "bond": "250000000" } ] }

Both EIP-3009 and Permit2 payments are recognised. The gateway confirms settlement from the USDG Transfer event, so a cancelled authorization never counts as a payment.

For sellers

  1. Connect your wallet in the dashboard and register your endpoint. You sign one message; no gas.
  2. Your endpoint must answer an unpaid request with a 402 offering USDG on Robinhood Chain to your registered address.
  3. The gateway checks it every 5 minutes. After three passing checks in a row it is listed as live.
  4. In the dashboard, register the same ID in the vault (free during the beta) and deposit at least $10 USDG. Calls are only covered, and you are only listed for agents, while your free bond is $10 or more.

Changing the address your 402 pays to pauses your listing until you update the registration.

Withdrawals take 7 days. You stop counting as bonded the moment you ask, so buyers are never routed to a bond that is leaving.

Add a webhook when you register to hear about claims. The gateway POSTs JSON with type (claim.opened, claim.disputed, claim.paid, claim.rejected), the claim, the dispute deadline and the evidence.

Claim rules

A claim opens only when the payment settled on-chain. It pays out after 30 minutes unless the seller disputes.

Seller response after paymentResult
2xx, matches the declared formatDelivered
5xx server errorRefund
No response in 30 secondsRefund
2xx that breaks the declared formatRefund
A second 402 after payingRefund
Other 3xx or 4xxManual review
Payment never settledNothing to refund

Claims are opened by the gateway on its own, within about 5 minutes of the payment settling. During the beta there is no claim fee: the bond pays exactly the refund. The vault allows a fee of up to 10% later, and any increase is announced on-chain 8 days before it applies, longer than a withdrawal takes. The largest single refund is $10; a seller's claims are capped at 20% of its bond per day, and claims over the cap wait for the next day.

A covered call can always be refunded. Before forwarding a call, the gateway checks that the seller's bond can still pay its refund today, counting claims already waiting. If it cannot, the call is refused with 503 seller_at_capacity before you pay anything.

If the seller disputes within 30 minutes, the bond stays locked and the vault admin decides from the recorded evidence: the payment transaction, the seller's status code, timings and a hash of the response. A dispute nobody decides within 72 hours is paid to the buyer automatically. The evidence for every claim is public at /api/claims/{req_id}, and its keccak256 is stored on-chain with the claim.

Only calls made after the vault launched are covered.

Trust model

Not everything here is trustless. This is exactly who you rely on for what.

PartWhat it doesWhat you trust
BondVault contractHolds bonds, locks money for open claims, pays refunds, enforces the 30-minute window, the 7-day withdrawal delay and the daily cap.The code. No one, including the admin, can move a bond except to the seller (withdrawal) or to a buyer (paid claim). Not audited yet.
GatewaySees the payment and the seller's response, decides whether a call failed, and opens claims with its signer key.That it records honestly. It cannot prove a response came from the seller; it can only show what it saw. Every claim's evidence is public and its hash is on-chain, so it cannot be changed later.
Vault adminDecides disputed claims, tunes limits within fixed bounds, can replace the claim signer.Fair dispute decisions. If the admin does nothing for 72 hours, the buyer is paid.

If the gateway goes down: calls through it fail before they reach the seller, so nobody pays. Claims already open stay on-chain; after 30 minutes anyone can call finalizeClaim to pay the buyer, without the gateway.

If the signer key leaks: it could open claims, but only up to $10 each, only up to 20% of a seller's bond per day, and sellers can dispute every one. The admin replaces the key with setSigner.

Our data APIs

undo402 also runs a few paid APIs of its own on Robinhood Chain, listed in the directory like any other seller. They are useful for agents and double as a live example of a covered x402 seller.

APIPriceReturns
chain/status$0.001Latest block, block time, gas price, RPC latency
wallet/snapshot$0.01ETH, USDG and token balances of an address, with USD values where known
token/check$0.02Risk flags before buying a token: upgradeable proxy, active owner, mint, pause, blacklist and fee functions, holder concentration

A bad address or a non-token contract is refused before you are charged, and if the chain cannot be read you are not charged either. Token checks are heuristics from public data, not a guarantee.

API reference

Public, no API key, same origin as this site.

ANY/s/{seller}/{path}Covered x402 call
GET/api/directoryEvery seller with uptime and calls over 7 days
GET/api/directory/allowlistLive endpoints only
GET/api/sellers/{id}Seller record, liveness and recent failures
GET/api/requests/{req_id}What happened to a paid call, and its claim
GET/api/claims?seller=&state=&buyer=Claims, newest first
GET/api/claims/{req_id}One claim with its evidence
GET/api/vaultVault address, limits and claim totals
GET/api/statusGateway, scheduler, vault and signer status
POST/api/sellersRegister (EIP-712 signature)
PATCH/api/sellers/{id}Update (owner's signature)

Contracts

BondVault
Launching soon
USDG
0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168
Network
Robinhood Chain · 4663
Audit
Not yet audited. Bonds are capped at $500 per seller during beta.