The facilitator is the rail (verify + settle). The paid weather route is a separate example seller. Public builder: Capt. Riker (@BatchRail).
facilitator.batchrail.io/weather — that path does not exist.eip155:84532. No API key. Cache /supported (not every request).
| exact | batch-settlement | |
|---|---|---|
| v2 price field | amount | amount (not v1 maxAmountRequired) |
| USDC reaches payTo | on that request’s POST /settle | after your claim job, then settle |
| ChannelManager | not required | required — the rail does not auto-enrol payTo |
Read receiverAuthorizer from live /supported. Do not hardcode it. Batch serves after verify, before the voucher is on-chain — claim on a timer and if a buyer starts withdrawal.
Live example seller — no repo clone required:
A normal browser gets HTTP 402 (expected). An x402 client pays with Base Sepolia test USDC (this demo uses batch-settlement), retries, and receives a small JSON payload. The seller uses the rail at facilitator.batchrail.io.
FACILITATOR_URL=https://facilitator.batchrail.io EVM_ADDRESS=0xYourReceiveAddressOnBaseSepolia
You never need BatchRail private keys. EVM_ADDRESS is your pay-to wallet.
| Path | Meaning |
|---|---|
| /health | Service up |
| /stats | Public usage counters |
| /supported | Base Sepolia schemes only |
POST /verify | Verify payment |
POST /settle | Relay on-chain actions |
429: { "error": "rate_limit_exceeded" } + Retry-After: 60. Limit 120/min/IP. /health and /stats are excluded.
import express from "express";
import { paymentMiddlewareFromHTTP, x402ResourceServer } from "@x402/express";
import { HTTPFacilitatorClient } from "@x402/core/server";
import { BatchSettlementEvmScheme } from "@x402/evm/batch-settlement/server";
const NETWORK = "eip155:84532"; // Base Sepolia testnet
const payTo = process.env.EVM_ADDRESS;
const facilitatorClient = new HTTPFacilitatorClient({
url: process.env.FACILITATOR_URL ?? "https://facilitator.batchrail.io",
});
const batchScheme = new BatchSettlementEvmScheme(payTo);
const resourceServer = new x402ResourceServer(facilitatorClient)
.register(NETWORK, batchScheme);
const app = express();
app.get(
"/weather",
paymentMiddlewareFromHTTP(
{
accept: [{
scheme: "batch-settlement",
network: NETWORK,
payTo,
amount: "10000",
resource: "https://your-host.example/weather",
description: "Test weather (Base Sepolia)",
mimeType: "application/json",
}],
},
resourceServer
),
(_req, res) => res.json({ ok: true, note: "paid on testnet" })
);
app.listen(4021);
Batch still needs your ChannelManager. For exact-only, use scheme: "exact" — no manager. Full examples: github.com/BatchRail/core.
Same facilitator rail. One paid tool endpoint on Base Sepolia:
FACILITATOR_URL=https://facilitator.batchrail.io EVM_ADDRESS=0xYourAddress NETWORK=eip155:84532 // testnet only // On tool call: // 1) 402 + scheme + network + payTo + amount // 2) verify/settle via FACILITATOR_URL // 3) run tool, return result // batch-settlement still needs your claim job
USDC (Base Sepolia): 0x036CbD53842c5426634e7929541eC2318f3dCF7e
Questions → @BatchRail (Capt. Riker).