x402 Machine Payments
HTTP 402 as a payment rail — software pays USDC for what it uses, at nanopayments scale.
Most of the internet's customers are software. x402 makes HTTP-native
payments real: a machine requests a paid resource, the server answers
402 Payment Required with machine-readable terms, the client pays and
retries, and gets its data. No accounts, no API keys, no invoices.
The 402 challenge
Call POST /api/quote identifying as an external agent
(x-corridor-client: external-agent) without paying:
curl -s -X POST https://transvia.xyz/api/quote \
-H "content-type: application/json" \
-H "x-corridor-client: external-agent" \
-d '{"corridor":"USD-EUR","amountUsdc":100}'The response is 402 Payment Required with the terms:
{
"x402Version": 1,
"error": "X-PAYMENT header is required for agent access",
"accepts": [
{
"scheme": "exact",
"network": "arc-testnet",
"maxAmountRequired": "10000",
"resource": "https://transvia.xyz/api/quote",
"description": "Transvia FX quote (60s TTL)",
"mimeType": "application/json",
"payTo": "0x…treasury",
"asset": "USDC",
"maxTimeoutSeconds": 30,
"extra": { "name": "USD Coin", "version": "2" }
}
]
}Price: 0.01 USDC per quote on Arc Testnet. maxAmountRequired is in
6-decimal USDC units — "10000" is 0.01 USDC.
The whole protocol as a UML sequence diagram:
UML sequence diagram — the x402 handshake (402 → pay → 200)
Agent Resource (Transvia API)
│ │
│──GET /api/quote (no payment)───────────────▶│
│ │ 402 challenge:
│◀────────────────────────────────────────────│ scheme exact · arc-testnet
│ │ maxAmountRequired 10000
│ signs EIP-3009 TransferWithAuthorization │
│ (offchain signature — no tx, no gas) │
│ │
│──retry with x-payment header───────────────▶│
│ │ verify: recover EIP-712
│ │ signer, match payer
│◀────────────────────────────────────────────│ 200 OK + quote bodyThe paid retry
Build the payment: an EIP-3009 TransferWithAuthorization — the USDC holder
signs "pay up to 0.01 USDC to the treasury" offchain — JSON-encoded,
base64-wrapped, and sent as the x-payment header. Retry the same request
with the header. The x402 verifier recovers the EIP-712 signer, matches it
to the declared payer, and returns 200 with the quote. Verification is
cryptographic on both the simulated and live rails — a single flipped byte
in the signature is rejected.
Honesty note: the signature is fully verified on every request; settling
that authorization onchain via a USDC transferWithAuthorization call is
the documented next step (a facilitator service). Transvia never claims
funds moved onchain for machine quote payments.
Nanopayments scale
x402 is not only for agents buying quotes for themselves. Transvia's own automation agent runs on the same rail — and its economics only work because payments can be tiny:
| What the agent buys | Cost |
|---|---|
| FX feed refresh while transfers are in flight | $0.000001 |
| Fee-split batch booking at settlement | $0.000001 |
A million FX feed updates cost one dollar. That is the point: resources get metered per call, and software buys exactly what it needs. How these purchases are decided and logged is in Automation Agents.
Replay the handshake live
POST /api/x402/demo replays the protocol steps against the live API — the
real 402 challenge from the quote endpoint, a real EIP-3009 signature built
by the rail's internal agent wallet, and the paid retry:
curl -s -X POST https://transvia.xyz/api/x402/demo{
"steps": [
{ "step": 1, "label": "Agent → Transvia /api/quote (no payment)", "status": 402 },
{ "step": 2, "label": "Agent builds X-PAYMENT header (real EIP-3009 signature)", "status": "local" },
{ "step": 3, "label": "Agent retries with X-PAYMENT → /api/quote", "status": 200 }
],
"ok": true
}Each step also carries the full response bodies (trimmed here). ok: false
with a skipped step 3 means no operator key is configured — the demo says
so instead of fabricating a payer. Every payment the API verifies lands in
the machine-economy ledger at GET /api/agent/payments.
A full agent handshake snippet is in Examples.