Overview
ouroborai uses the x402 protocol to gate access to agent routes. x402 extends HTTP with a native payment layer built on the402 Payment Required status code. Every request to /agent/* costs $0.01 USDC on Arbitrum One.
This approach removes the need for API key management on agent routes. Instead of signing up for an account and provisioning credentials, you pay per request using an on-chain USDC transfer authorization.
USDC on Arbitrum uses 6 decimal places. The default price of $0.01 is represented as
10000 in raw USDC units.How it works
When a client makes a request to any/agent/* endpoint without a valid payment, the server responds with HTTP 402 and a JSON body describing what payment is required. The client constructs a signed EIP-3009 transferWithAuthorization payload, attaches it as a base64-encoded X-PAYMENT header, and retries the request.
Request without payment
The client sends a request to an agent endpoint. The server returns
402 Payment Required with a JSON body describing the accepted payment schemes, asset, amount, and recipient.Construct payment payload
The client reads the
402 response, builds an EIP-3009 transferWithAuthorization message for the specified USDC amount, and signs it with their wallet.Retry with X-PAYMENT header
The client re-sends the original request with the signed payment encoded as a base64 JSON string in the
X-PAYMENT header.402 response format
When you call an agent endpoint without a payment header, the server returns this structure:| Field | Description |
|---|---|
scheme | Payment scheme. Currently only exact is supported. |
network | Target chain. Always arbitrum for this server. |
maxAmountRequired | Price in raw USDC units (6 decimals). 10000 = $0.01. |
payTo | The recipient wallet address for payment. |
asset | USDC contract address on Arbitrum One. |
extra.name / extra.version | EIP-712 domain parameters for USDC’s transferWithAuthorization. |
Payment payload construction
TheX-PAYMENT header contains a base64-encoded JSON object with the signed EIP-3009 authorization:
Replay prevention
Every payment includes a uniquenonce (bytes32). The server atomically claims each nonce to prevent the same payment from being used twice.
Redis (production)
Redis (production)
When
REDIS_URL is set, nonces are stored using the SET NX EX pattern:NXensures the key is only set if it does not already exist (atomic claim).EX 86400sets a 24-hour TTL so stale nonces are automatically cleaned up.
SET returns null (key already existed), the payment is rejected as a replay.In-memory (development)
In-memory (development)
When no Redis connection is available, nonces are tracked in a local
Set. This works for single-instance development but does not survive restarts and cannot be shared across multiple server instances.Revenue tracking
Every verified payment is recorded for per-facilitator revenue accounting. The payer address is extracted from the payment authorization and stored alongside the amount and request path. Revenue data is available through the admin dashboard:GET /admin/revenue— total revenue, unique payers, recent paymentsGET /admin/revenue/history?days=30— daily breakdown
arb:revenue:* keys with 90-day TTL) and falls back to in-memory counters otherwise.
Development mode
For local development, set theSKIP_PAYMENT environment variable to bypass payment verification entirely:
"dev" and all agent routes are accessible without an X-PAYMENT header.
Verification details
The server validates the following before accepting a payment:- Scheme and network — must be
exactandarbitrum - Recipient — the
toaddress must match the configuredPAY_TO_ADDRESS - Amount — the
valuemust be greater than or equal to the required amount (default10000) - Sender — the
fromaddress must be present - Nonce — the nonce must not have been previously claimed
- Signature — the EIP-712 typed data signature must be valid for the USDC
transferWithAuthorizationdomain on Arbitrum (chain ID42161)
402 with {"error": "Invalid or insufficient payment"}.