This server allows developers to test their x402 clients against a live x402 Server, and get their money back.
x402-echo-merchant is an early-stage TypeScript project in the AI payments / x402 ecosystem. It currently has 5 GitHub stars and 6 forks.
A modern, developer-focused pay-per-use API demo server for the x402 protocol. Supports both x402 V1 and V2 protocols with CAIP-2 network format. Instantly test x402 payments, see live paywall enforcement, and get a rizzler GIF reward after payment—plus a full refund!
eip155:8453) and V2 headers (PAYMENT-SIGNATURE, PAYMENT-RESPONSE)/api/base/paid-content)Install dependencies:
npm install
# or
yarn install
Set up environment variables:
.env.example to .env and fill in required values (see below)Run the dev server:
npm run dev
# or
yarn dev
NEXT_PUBLIC_SITE_URL - Base URL of the server (used by the web app)
FACILITATOR_URL - URL of the x402 facilitator service (e.g. https://facilitator.payai.network)
EVM_RECEIVE_PAYMENTS_ADDRESS - EVM address to receive payments to
SVM_RECEIVE_PAYMENTS_ADDRESS - Solana address to receive payments to
EVM_PRIVATE_KEY - EVM private key used to send refunds (hex string starting with 0x)
SVM_PRIVATE_KEY - Solana private key used to send refunds
BASE_RPC_URL - Base Mainnet RPC URL (https)
BASE_SEPOLIA_RPC_URL - Base Sepolia RPC URL (https)
AVALANCHE_RPC_URL - Avalanche Mainnet RPC URL (https)
AVALANCHE_FUJI_RPC_URL - Avalanche Fuji Testnet RPC URL (https)
SEI_RPC_URL - Sei Mainnet RPC URL (https)
SEI_TESTNET_RPC_URL - Sei Testnet RPC URL (https)
POLYGON_RPC_URL - Polygon Mainnet RPC URL (https)
POLYGON_AMOY_RPC_URL - Polygon Amoy Testnet RPC URL (https)
SOLANA_RPC_URL - Solana Mainnet RPC URL (https)
SOLANA_DEVNET_RPC_URL - Solana Devnet RPC URL (https)
SOLANA_WS_URL - (optional) Solana Mainnet WebSocket URL (wss)
SOLANA_DEVNET_WS_URL - (optional) Solana Devnet WebSocket URL (wss)
XLAYER_RPC_URL - xLayer Mainnet RPC URL (https)
XLAYER_TESTNET_RPC_URL - xLayer Testnet RPC URL (https)
Pin @payai/x402, @payai/x402-evm, @payai/x402-next, @payai/facilitator, @payai/x402-svm, and @payai/x402-extensions to the same minor version as the facilitator you run against (see payai-x402-facilitator’s apps/api/package.json). Mismatched versions can break verify/settle or extension handling.
EVM routes default to EIP-3009 USDC. To opt into Permit2 (testnet demos or tokens without EIP-3009), extend RouteConfig in src/lib/x402-helpers.ts on each route:
| Field | Purpose |
|---|---|
assetTransferMethod?: 'eip3009' | 'permit2' |
Sets extra.assetTransferMethod on PaymentRequirements. Omit or use eip3009 for the legacy USDC path. |
permit2GasSponsoring?: 'none' | 'eip2612' | 'erc20' | 'both' |
Merges top-level PaymentRequired.extensions using @payai/x402-extensions only if GET /supported on FACILITATOR_URL lists the matching keys (eip2612GasSponsoring, erc20ApprovalGasSponsoring). |
permit2UserHint?: string |
Optional user-facing paywall line (e.g. one-time approval / gas coverage) without exposing raw protocol names. |
The Base Sepolia route (sepoliaConfig in src/middleware.ts) demonstrates permit2 + both gas-sponsoring declarations for integration testing.
Non-USDC or custom tokens need correct metadata (ERC20TokenAmount / EIP-712 domain) per SDK rules; wrong metadata will fail signing or settlement.
Apache V2
To add a new network (example: sei) across the Echo Merchant UI, middleware, and API:
Make sure that you npm install the x402 package version that contains the new network.
Frontend link on homepage
src/app/page.tsxMAINNET_ENDPOINTS or TESTNET_ENDPOINTS:{ label: 'Sei Mainnet', url: ${API_URL}/api/sei/paid-content }Middleware route & config
src/proxy.tsconst seiConfig = { price: '$0.01', network: 'sei', config: { description: '...' } }if (pathname.startsWith('/api/sei/')) { return paymentMiddleware(payToEVM, { '/api/sei/paid-content': seiConfig }, facilitatorConfig)(request); }API route file
src/app/api/<network>/paid-content/route.ts with a basic GET that returns { ok: true }.Paywall app (wallet flow)
src/paywall/src/Providers.tsx and src/paywall/src/PaywallApp.tsxviem/chains and add CAIP-2 map entries (e.g. 'eip155:1329': sei).Explorer links
src/lib/utils.ts if you want explorer links for the new network in the rizzler page:getExplorerForNetwork and renderRizzlerHtml to include the new network.Environment variables
<NETWORK>_RPC_URL to a private custom RPC from Alchemy if possible, otherwise find a suitable RPC for the network and add it here. <NETWORK> is to be replaced by the network name.FACILITATOR_URL pointing to your facilitator (which must support the network).EVM_RECEIVE_PAYMENTS_ADDRESS is set for EVM networks.SVM_RECEIVE_PAYMENTS_ADDRESS.Refund flow
src/refund.ts and update the EVM signer factory:viem/chains (e.g., sei).network === '<network>' branch in getSigner that returns a createWalletClient with the chain and process.env.<NETWORK>_RPC_URL.NETWORK_TO_CAIP2, SupportedEVMNetworks, and USDC_ADDRESSES in src/lib/x402-helpers.ts.<NETWORK>_RPC_URL in your .env (same value used by getSigner).Test
/api/<network>/paid-content in a browser.A good way to test is by running the facilitator locally and using it to do an end-to-end test with the echo merchant. Make sure to read its README.md for how to set up a new network on the facilitator.