Last updated: June 2026
XPay (XPayLabs) seller test server for the x402 protocol — an open HTTP 402 payment standard for USDC micropayments on EVM chains. Built with Express + @x402/express middleware. Use this to test XPayLabs-x402 (buyer SDK) or any x402-compatible client without setting up a production seller infrastructure.
An Express-based test server that implements the x402 HTTP 402 Payment Required protocol on the seller side. It protects API endpoints behind USDC payments, returning a 402 status with payment requirements on the first request and serving data after the client signs and submits a valid PAYMENT-SIGNATURE header. Works with both exact (fixed-price) and upto (usage-based) payment schemes.
| Scenario | Without XPay seller server | With XPay seller server |
|---|---|---|
| Testing buyer SDK | Need a production x402 API | Run locally in 30 seconds |
| Learning x402 protocol | Read docs only | Interactive 402 handshake |
| CI/CD integration | External API dependency | Self-contained test endpoint |
| Scheme experimentation | Limited to what APIs offer | Both exact and upto out of the box |
- Exact payment (
/weather) — fixed $0.001, test theexactscheme (EIP-3009) - Usage-based payment (
/api/generate) — up to $0.10, random usage viauptoscheme +setSettlementOverrides(Permit2) - Free endpoint (
/public) — no payment required - Returns real transaction hash —
PAYMENT-RESPONSEheader decoded by buyer SDK intopaymentId - Configurable network — switch between Base Sepolia (testnet) and Base Mainnet
- Full x402 handshake — 402 → sign → retry → 200 flow
- Health check (
/health) — verify server status
git clone <repo-url>
cd XPayLabs-x402-seller
npm installcp .env.example .envEdit .env:
# Your EVM wallet address to receive USDC payments
EVM_ADDRESS=0xYourEvmWalletAddress
# Facilitator URL (testnet: https://x402.org/facilitator)
FACILITATOR_URL=https://x402.org/facilitator
# Network CAIP-2 identifier (Base Sepolia)
NETWORK=eip155:84532
# Port (default 4021)
PORT=4021npm run devServer starts at http://localhost:4021.
# Free endpoint — no payment
curl http://localhost:4021/public
# Protected endpoint — first request returns 402,
# client must sign and retry with PAYMENT-SIGNATURE header
curl http://localhost:4021/weather
# Health check
curl http://localhost:4021/healthTest with the XPay buyer SDK:
cd XPayLabs-x402
npx tsx test/integration.test.ts| Endpoint | Scheme | Price | Network | Description |
|---|---|---|---|---|
GET /weather |
exact |
$0.001 | Base Sepolia | Mock weather data (sunny, 70°F) |
GET /api/generate |
upto |
$0.10 max | Base Sepolia | Mock AI generation with random usage |
GET /public |
— | Free | — | Public endpoint, no payment |
GET /health |
— | — | — | Server health status |
Client XPay seller server Facilitator
│ │ │
│──── GET /weather ──────────→ │ │
│ │ │
│←─── 402 PAYMENT-REQUIRED ────│ │
│ (price, network, payTo) │ │
│ │ │
│ Sign locally (EIP-3009) │ │
│ (private key never sent) │ │
│ │ │
│──── GET + PAYMENT-SIGNATURE →│───── verify & settle ──────→│
│ │←───────── tx hash ──────────│
│←─── 200 + PAYMENT-RESPONSE ──│ │
│ (transaction in header) │ │
Steps:
- Client requests the protected
/weatherendpoint - Server responds with 402 Payment Required +
PAYMENT-REQUIREDheader containing price, network, and payTo address - Client signs the payment locally using EIP-3009 (private key stays in process)
- Client retries with
PAYMENT-SIGNATUREheader containing the cryptographic proof - Server verifies the signature via the facilitator and settles on-chain
- Server returns 200 + response data with
PAYMENT-RESPONSEheader containing the transaction hash
To test on Base Mainnet with real USDC, update .env:
EVM_ADDRESS=0xYourRealWalletAddress
FACILITATOR_URL=https://api.cdp.coinbase.com/platform/v2/x402
NETWORK=eip155:8453Warning: Mainnet transactions use real USDC and gas fees. Test thoroughly on testnet first.
| Command | Description |
|---|---|
npm run dev |
Start dev server with hot reload (tsx watch) |
npm start |
Start production server |
npm run build |
Compile TypeScript to dist/ |
npm run typecheck |
TypeScript type checking (tsc --noEmit) |
| Variable | Default | Required | Description |
|---|---|---|---|
EVM_ADDRESS |
— | Yes | Your EVM wallet to receive USDC payments |
FACILITATOR_URL |
https://x402.org/facilitator |
No | x402 facilitator endpoint |
NETWORK |
eip155:84532 |
No | CAIP-2 network identifier |
PORT |
4021 |
No | HTTP server port |
For testnet, no. Get free Base Sepolia USDC from the CDP Faucet. For mainnet, you need real USDC.
Yes. The testnet facilitator (https://x402.org/facilitator) submits real on-chain transactions on Base Sepolia. The PAYMENT-RESPONSE header contains the transaction hash, which the XPay buyer SDK decodes into paymentId. Transactions are verifiable on Base Sepolia Explorer.
- Exact — Fixed price. Buyer pays exactly $0.001. Uses EIP-3009 (gas sponsored by facilitator).
- Upto — Usage-based. Buyer authorizes up to $0.10, seller charges actual usage via
setSettlementOverrides. Uses Permit2.
Yes. Edit src/index.ts and add route configs to the paymentMiddleware() call following the existing pattern. See the x402 Express middleware docs for details.
- Runtime: Node.js >= 18
- Framework: Express 4.21
- x402: @x402/express, @x402/core, @x402/evm
- Language: TypeScript 5.6
- Dev runner: tsx (TypeScript execution)
GitHub: yan253319066/XPayLabs-x402-seller Gitee (mirror): XPayLabs/XPayLabs-x402-seller
MIT