x402 integration guide
Deploy agent micropayments on Radius using the x402 payment protocol. Add middleware to your HTTP server and start accepting per-request stablecoin payments from AI agents today.
What is x402?
x402 is an open payment protocol that embeds stablecoin payments directly into HTTP request-response flows. It revives the HTTP 402 "Payment Required" status code to enable machine-native payments — no checkout pages, no card numbers, no human in the loop.
The flow:
- Agent sends a request to your API or content endpoint
- Your server returns HTTP 402 with payment requirements (price, accepted token, facilitator URL)
- Agent signs a payment and resubmits the request with a
PAYMENT-SIGNATUREheader containing the base64-encoded signed payload - Your server forwards the payment to a facilitator — the facilitator calls
POST /verifyto validate the signature, thenPOST /settleto execute the on-chain transfer - Your server delivers the resource once settlement confirms
Facilitators are hosted services that handle verification and on-chain settlement on your behalf. You point your middleware at a facilitator URL and call two endpoints: /verify and /settle. You don't run settlement infrastructure yourself.
x402 is an open standard co-founded by Coinbase and Cloudflare. It builds on the long history of HTTP 402, a status code reserved since 1997 for "future use" that is finally being put to work ~30 years later.
For more on x402: x402.org
Migrating from x402 v1? The v2 protocol introduces CAIP-2 network identifiers, new HTTP headers (
PAYMENT-SIGNATUREreplacesX-PAYMENT), and restructured SDK packages. See the Migration guide: v1 to v2 for a complete walkthrough covering buyers, sellers, header changes, and package mappings.
Why Radius as the settlement layer for x402
x402 works on any supported network. The choice of settlement layer determines your cost, speed, and scale ceiling.
| Base (default) | Radius | |
|---|---|---|
| Max TPS | ~3,500 | 2.8M+ tested, linearly scalable |
| Cost per transaction | ~0.001–0.01 SBC | ~0.00001 SBC |
| Finality | ~2s | ~500ms |
| Gas fees | Variable (low, but exist) | Fixed, near-zero, paid in stablecoins |
| Native token required | Yes (ETH for gas) | No |
At current x402 volumes (~600K daily transactions), Base works fine. As agent payment volume scales, the settlement layer becomes the bottleneck. Radius is designed for the scale where other infrastructure runs out of capacity.
Faster settlement with eth_sendRawTransactionSync
Radius supports eth_sendRawTransactionSync (EIP-7966), a method that combines transaction submission and receipt retrieval into a single RPC call. Standard eth_sendRawTransaction returns a transaction hash immediately and requires the caller to poll for the receipt — adding at least one extra round-trip on the critical path. eth_sendRawTransactionSync eliminates that entirely.
For x402, settlement is on the critical path of every paid HTTP request. A facilitator that uses eth_sendRawTransactionSync against Radius can return a confirmed txHash to your middleware in a single call, reducing POST /settle latency by approximately 50% compared to the standard async pattern.
→ Settlement layer comparison — full comparison of all settlement alternatives
What you can build
Per-request API monetization
Add x402 middleware to any HTTP endpoint. Agents pay per API call, per data retrieval, or per query. Your existing service logic doesn't change — the middleware handles payment negotiation before the request reaches your application code.
Use cases: data feeds, inference endpoints, translation services, geocoding, search APIs, premium content access.
Streaming payments
For services with continuous consumption — video streaming, real-time data feeds, GPU compute, LLM token generation — x402 on Radius supports per-segment or per-second payment flows. The agent authorizes an initial payment, and subsequent segments charge automatically as they're consumed.
Facilitators on Radius support HLS streaming, where each segment of a video or data stream triggers an automatic micropayment. This pattern extends to any continuous service: an agent consuming a real-time market data feed pays per second of access, or an agent using GPU compute pays per second of processing time.
Pay-per-crawl content gating
Serve content to AI crawlers for a per-page fee instead of blocking them entirely. Return a 402 response to agent traffic with your price; agents that pay get access, agents that don't get blocked. You monetize crawler traffic without losing distribution.
→ Monetize for the agentic internet — business context, monetization models, and deployment considerations
Architecture
┌──────────────┐ HTTP 402 + requirements ┌──────────────────┐
│ │ ◄───────────────────────────── │ │
│ Agent │ │ Your Server │
│ (buyer) │ ──────────────────────────────►│ + x402 │
│ │ request + PAYMENT-SIGNATURE │ middleware │
└──────────────┘ └────────┬─────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
GET /supported POST /verify POST /settle
│ │ │
└──────────────┼──────────────┘
│
┌──────▼───────┐
│ Facilitator │
│ (hosted) │
└──────┬───────┘
│
│ on-chain settlement
▼
┌──────────────┐
│ Radius │
│ Network │
└──────────────┘
Your server adds x402 middleware that intercepts incoming requests and returns 402 responses with payment requirements for monetized endpoints.
The facilitator is a hosted service that verifies payment signatures (POST /verify) and settles transactions on the Radius network (POST /settle). You query GET /supported to discover which networks, tokens, and protocol versions the facilitator handles.
The facilitator pays gas fees on your behalf. There is no cost to you or the paying agent beyond the transaction amount itself. This works because Radius's fixed gas fees are near-zero (~0.00001 SBC per transaction).
Facilitators supporting Radius
Three facilitators support Radius today. Choose based on your deployment target (mainnet vs testnet) and protocol version requirements.
Radius (recommended)
| URL (mainnet) | https://facilitator.radiustech.xyz |
| URL (testnet) | https://facilitator.testnet.radiustech.xyz |
| Networks | Radius mainnet (eip155:723487), Radius testnet (eip155:72344) |
| Token | SBC via Permit2 with EIP-2612 gas sponsoring |
| Protocol | x402 v2 |
| Operator | Radius (first-party) |
The Radius facilitator uses Permit2-based settlement with gas sponsoring. Settlement is atomic (one on-chain call), and the facilitator sponsors all gas costs. The assetTransferMethod in your 402 response must be "permit2", not "erc2612". Integrators do not need to know the facilitator's internal wallet addresses — payers sign against the canonical x402ExactPermit2Proxy (0x402085c248EeA27D92E8b30b2C58ed07f9E20001).
Stablecoin.xyz
| URL | https://x402.stablecoin.xyz |
| Networks | Radius mainnet (chain ID 723487), Radius testnet (chain ID 72344), Base, Solana |
| Token | SBC via EIP-2612 permit |
| Protocol | x402 v1 + v2 |
| Cost | Free for developers (facilitator absorbs gas) |
Production-ready third-party facilitator supporting both Radius mainnet and testnet.
Middlebit by Braile
| URL | https://middlebit.com |
| Networks | Radius mainnet (chain ID 723487), Base |
| Protocol | x402 (uses stablecoin.xyz under the hood) |
| Type | Middleware layer — adds routing, analytics, and multi-facilitator support |
Higher-level middleware that wraps facilitator calls with additional features. Uses stablecoin.xyz for Radius settlement.
Integration pattern
This section shows the core x402 server-side integration pattern. The examples use a Cloudflare Worker, but the pattern applies to any HTTP server.
Network constants
Mainnet:
Chain ID: 723487
CAIP-2: eip155:723487
RPC: https://rpc.radiustech.xyz
Testnet:
Chain ID: 72344
CAIP-2: eip155:72344
RPC: https://rpc.testnet.radiustech.xyz
SBC token: 0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb (6 decimals)
Configuration
The X402Config interface is the central abstraction for x402 middleware:
interface X402Config {
asset: string; // SBC token address
network: string; // CAIP-2 chain ID, e.g. "eip155:723487"
payTo: string; // Merchant wallet address (receives payments)
facilitatorUrl: string; // Facilitator base URL
amount: string; // Raw token units (6 decimals). "100" = 0.0001 SBC
facilitatorApiKey?: string; // Optional API key if facilitator requires one
}Example configuration for Radius mainnet:
const config: X402Config = {
asset: "0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb",
network: "eip155:723487",
payTo: "{{MERCHANT_WALLET_ADDRESS}}",
facilitatorUrl: "https://facilitator.radiustech.xyz",
amount: "100", // 0.0001 SBC per request
};Building 402 requirements
When a request arrives without a valid PAYMENT-SIGNATURE header, return HTTP 402 with a base64-encoded PAYMENT-REQUIRED header:
function buildPaymentRequired(config: X402Config, requestUrl: string) {
return {
x402Version: 2,
error: "PAYMENT-SIGNATURE header is required",
resource: {
url: requestUrl,
description: "Access to protected resource",
mimeType: "application/json",
},
accepts: [
{
scheme: "exact",
network: config.network,
amount: config.amount,
asset: config.asset,
payTo: config.payTo,
maxTimeoutSeconds: 300,
extra: {
// Use "erc2612" instead if using Stablecoin.xyz
assetTransferMethod: "permit2",
name: "Stable Coin",
version: "1",
},
},
],
};
}
function return402(config: X402Config, requestUrl: string): Response {
const paymentRequired = buildPaymentRequired(config, requestUrl);
return new Response("{}", {
status: 402,
headers: {
"Content-Type": "application/json",
"PAYMENT-REQUIRED": btoa(JSON.stringify(paymentRequired)),
},
});
}The verify → settle flow
The processPayment() function handles the full payment lifecycle. It returns a typed outcome so your handler can branch on every possible state:
type PaymentOutcome =
| { status: "no-payment" }
| { status: "invalid-header"; error: string }
| { status: "verify-failed"; error: string }
| { status: "settle-failed"; error: string }
| { status: "settled"; transaction: string; payer: string; network: string };
async function processPayment(
request: Request,
config: X402Config
): Promise<PaymentOutcome> {
// 1. Check for PAYMENT-SIGNATURE header
const paymentHeader = request.headers.get("PAYMENT-SIGNATURE");
if (!paymentHeader) {
return { status: "no-payment" };
}
// 2. Decode base64 payment payload
let paymentPayload: any;
try {
paymentPayload = JSON.parse(atob(paymentHeader));
} catch {
return { status: "invalid-header", error: "Failed to decode PAYMENT-SIGNATURE header" };
}
const paymentRequirements = {
scheme: "exact",
network: config.network,
amount: config.amount,
asset: config.asset,
payTo: config.payTo,
maxTimeoutSeconds: 300,
extra: { name: "Stable Coin", version: "1" },
};
const body = {
x402Version: 2,
paymentPayload,
paymentRequirements,
};
const headers: Record<string, string> = {
"Content-Type": "application/json",
};
if (config.facilitatorApiKey) {
headers["x-api-key"] = config.facilitatorApiKey;
}
// 3. Verify payment with facilitator
const verifyRes = await fetch(`${config.facilitatorUrl}/verify`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!verifyRes.ok) {
const err = await verifyRes.text();
return { status: "verify-failed", error: err };
}
// 4. Settle payment on-chain
const settleRes = await fetch(`${config.facilitatorUrl}/settle`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!settleRes.ok) {
const err = await settleRes.text();
return { status: "settle-failed", error: err };
}
const settleData = await settleRes.json();
return {
status: "settled",
transaction: settleData.transaction,
payer: settleData.payer,
network: settleData.network,
};
}Complete Cloudflare Worker example
This example creates a paid API endpoint that charges 0.0001 SBC per request on Radius mainnet:
// worker.ts — Cloudflare Worker with x402 payment gating
interface Env {
MERCHANT_WALLET: string;
FACILITATOR_API_KEY?: string;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const config: X402Config = {
asset: "0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb",
network: "eip155:723487",
payTo: env.MERCHANT_WALLET,
facilitatorUrl: "https://facilitator.radiustech.xyz",
amount: "100", // 0.0001 SBC (6 decimals)
facilitatorApiKey: env.FACILITATOR_API_KEY,
};
const outcome = await processPayment(request, config);
switch (outcome.status) {
case "no-payment":
return return402(config, request.url);
case "invalid-header":
return new Response(
JSON.stringify({ error: "Invalid payment header", detail: outcome.error }),
{ status: 400, headers: { "Content-Type": "application/json" } }
);
case "verify-failed":
return new Response(
JSON.stringify({ error: "Payment verification failed", detail: outcome.error }),
{ status: 402, headers: { "Content-Type": "application/json" } }
);
case "settle-failed":
return new Response(
JSON.stringify({ error: "Payment settlement failed", detail: outcome.error }),
{ status: 502, headers: { "Content-Type": "application/json" } }
);
case "settled":
// Payment confirmed — deliver the resource
const paymentResponse = {
success: true,
transaction: outcome.transaction,
network: outcome.network,
payer: outcome.payer,
};
return new Response(
JSON.stringify({ data: { message: "Paid content delivered" } }),
{
status: 200,
headers: {
"Content-Type": "application/json",
"PAYMENT-RESPONSE": btoa(JSON.stringify(paymentResponse)),
},
}
);
}
},
};Facilitator discovery
Before integrating, query a facilitator's GET /supported endpoint to confirm it handles your target network, token, and protocol version.
Request
GET https://facilitator.radiustech.xyz/supported
Response
The response lists every supported payment kind (network + scheme + version), protocol extensions, and the facilitator's signer addresses:
{
"kinds": [
{
"x402Version": 2,
"scheme": "exact",
"network": "eip155:723487",
"extra": {
"assetTransferMethod": "permit2",
"name": "Stable Coin",
"version": "1"
}
}
],
"extensions": ["eip2612GasSponsoring"],
"signers": {}
}Each entry in kinds describes one supported payment flow. Check for your target network (CAIP-2 format) and x402Version. The assetTransferMethod is "permit2" for the Radius facilitator or "erc2612" for Stablecoin.xyz — your 402 response must match. The "eip2612GasSponsoring" extension means the facilitator handles the one-time Permit2 approval gaslessly if the payer hasn't already approved the Permit2 contract.
The mainnet and testnet Radius facilitators are separate services. The testnet facilitator (https://facilitator.testnet.radiustech.xyz/supported) returns an equivalent response with "network": "eip155:72344".
Use this to validate your configuration
async function validateFacilitator(
facilitatorUrl: string,
network: string,
x402Version: number = 2
): Promise<boolean> {
const res = await fetch(`${facilitatorUrl}/supported`);
if (!res.ok) return false;
const data = await res.json();
return data.kinds.some(
(k: any) => k.network === network && k.x402Version === x402Version
);
}Call this at startup or deploy time to confirm your facilitator supports Radius before serving traffic.
Start now
x402 facilitators supporting Radius are live today on both mainnet and testnet. Get started:
→ Radius facilitator — first-party, Permit2 + gas sponsoring (recommended) → Stablecoin.xyz facilitator — supports Radius mainnet + testnet via EIP-2612 → Middlebit by Braile — middleware layer for multi-chain x402 → Radius testnet dashboard — set up your account and fund your wallet → x402 integration — integration patterns, settlement strategies, and code examples → x402.org — protocol specification and ecosystem directory
→ Why Radius for agent payments — the full thesis → The agentic payment stack — where x402 and Radius fit in the architecture → Monetize for the agentic internet — business case and monetization models