x402-gateway-template is a growing JavaScript project in the AI payments / x402 ecosystem. It currently has 94 GitHub stars and 15 forks.
A production-ready, self-hosted payment gateway that implements the x402 protocol — HTTP-native micropayments for APIs. Accept stablecoin payments (USDC) per-request with no API keys, no subscriptions, and no intermediaries.
Fork this repo, configure your backend, and start accepting crypto micropayments in minutes.
x402 uses the HTTP 402 Payment Required status code to create a machine-readable payment flow:
1. Agent/client calls your API
2. Gateway returns 402 with payment requirements (chain, amount, token)
3. Agent signs a USDC transfer authorization
4. Agent retries with signed payment in header
5. Gateway verifies signature, settles on-chain, proxies to your backend
6. Client gets the API response + payment receipt
No wallets to integrate. No payment pages. Just HTTP headers.
payment-identifier extension for safe retries without double-charging/accepted endpoint with full pricing, schemas, and network info/.well-known/x402 discovery document# Clone the template
git clone https://github.com/YOUR_USERNAME/x402-gateway-template.git
cd x402-gateway-template
# Install dependencies
npm install
# Configure
cp .env.example .env
# Edit .env with your values (see Configuration section)
# Run locally
npm run dev
# Test
curl http://localhost:8080/health
curl http://localhost:8080/accepted
Client/Agent request
→ x402 Gateway (this service)
→ Verify payment signature (EIP-712 / SVM)
→ Settle on-chain (USDC transfer)
→ Proxy to your backend API (with internal auth)
→ Return response + payment receipt header
┌─────────────────────────────────────────────────┐
│ x402 Gateway │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Payment │→ │ On-chain │→ │ Backend Proxy │ │
│ │ Verify │ │ Settle │ │ (your API) │ │
│ └──────────┘ └──────────┘ └───────────────┘ │
│ │ │ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Redis │ │ RPC │ │
│ │ (nonces) │ │ (chains) │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────┘
Edit src/config/routes.js to define your paid API endpoints:
export const ROUTE_CONFIG = {
// Each key becomes a route prefix: /v1/{key}/*
myapi: {
path: '/v1/myapi/*',
backendName: 'My API',
get backendUrl() { return process.env.MY_BACKEND_URL; },
backendApiKeyEnv: 'MY_BACKEND_API_KEY',
backendApiKeyHeader: 'x-api-key', // Header name your backend expects
get price() { return process.env.MY_PRICE || '$0.01'; },
get priceAtomic() { return process.env.MY_PRICE_ATOMIC || '10000'; }, // 0.01 USDC in 6-decimal units
get payTo() { return process.env.MY_PAY_TO_ADDRESS || process.env.PAY_TO_ADDRESS; },
get payToSol() { return process.env.MY_PAY_TO_ADDRESS_SOL; },
description: 'Description of your API for agent discovery',
mimeType: 'application/json',
},
};
| Variable | Description |
|---|---|
SETTLEMENT_PRIVATE_KEY |
Private key (0x hex) for the gas-paying settlement wallet |
PAY_TO_ADDRESS |
Default EVM wallet that receives USDC payments |
BASE_RPC_URL |
At least one RPC URL (Base recommended for low fees) |
| Variable | Description |
|---|---|
MY_BACKEND_URL |
Your backend API base URL |
MY_BACKEND_API_KEY |
Internal API key for your backend |
| Variable | Chain | Required Gas Token |
|---|---|---|
BASE_RPC_URL |
Base | ETH (~$5) |
ETHEREUM_RPC_URL |
Ethereum | ETH (~$20-50) |
ARBITRUM_RPC_URL |
Arbitrum | ETH (~$5) |
OPTIMISM_RPC_URL |
Optimism | ETH (~$5) |
POLYGON_RPC_URL |
Polygon | POL (~$2) |
AVALANCHE_RPC_URL |
Avalanche | AVAX (~$2) |
UNICHAIN_RPC_URL |
Unichain | ETH (~$2) |
LINEA_RPC_URL |
Linea | ETH (~$2) |
MEGAETH_RPC_URL |
MegaETH | N/A (facilitator pays) |
SONIC_RPC_URL |
Sonic | S (~$2) |
HYPEREVM_RPC_URL |
HyperEVM | HYPE (~$15-20) |
INK_RPC_URL |
Ink | ETH (~$2) |
MONAD_RPC_URL |
Monad | MON (~$2) |
ABSTRACT_RPC_URL |
Abstract | None (gas sponsored via paymaster) |
SOLANA_RPC_URL |
Solana | SOL (~$2) |
| Variable | Description |
|---|---|
SOLANA_FACILITATOR_PRIVATE_KEY |
Base58 private key for Solana fee payer |
MY_PAY_TO_ADDRESS_SOL |
Solana wallet to receive USDC payments |
| Variable | Description |
|---|---|
UPSTASH_REDIS_REST_URL |
Upstash Redis REST URL |
UPSTASH_REDIS_REST_TOKEN |
Upstash Redis REST token |
Tip: Upstash has a generous free tier. Any Redis with REST API works.
| Variable | Description |
|---|---|
PORT |
Server port (default: 8080) |
MY_PRICE |
Display price (e.g., "$0.05") |
MY_PRICE_ATOMIC |
Price in token atomic units (e.g., "50000" for $0.05 USDC) |
The settlement wallet only pays gas to submit transferWithAuthorization on-chain. It never holds or receives stablecoins — payments flow directly from the payer to your payTo address.
Payer → (USDC) → Your payTo wallet ← receives payment
Settlement wallet → (gas) → on-chain ← only pays gas fees
Fund it with small amounts of native gas tokens on each chain you enable.
src/config/routes.jssrc/index.js:// Paid route
app.all('/v1/myapi/{*path}', x402PaymentMiddleware('myapi'), async (req, res) => {
const subpath = getSubpath(req.params);
const route = ROUTE_CONFIG.myapi;
await proxyToBackend({
req, res,
targetBase: route.backendUrl,
targetPath: '/api/' + subpath,
apiKey: process.env[route.backendApiKeyEnv],
apiKeyHeader: route.backendApiKeyHeader,
});
});
// Free route (no middleware)
app.get('/v1/myapi/health', async (req, res) => {
// Proxy directly without payment
});
Map user-friendly paths to your backend's actual routes:
const PATH_ALIASES = {
'analyze': 'internal-analyze-endpoint',
'report': 'generate-full-report',
};
const resolvedSubpath = PATH_ALIASES[subpath] || subpath;
src/config/routes.js:const MY_CHAIN = {
vm: 'evm',
caip2: 'eip155:CHAIN_ID',
chainId: CHAIN_ID,
rpcEnvVar: 'MY_CHAIN_RPC_URL',
token: usdc('0xUSDC_CONTRACT_ADDRESS'),
};
ALL_NETWORKS.envsrc/middleware/x402.jsFor chains where USDC doesn't support EIP-3009 yet:
const MY_CHAIN = {
vm: 'evm',
caip2: 'eip155:CHAIN_ID',
chainId: CHAIN_ID,
rpcEnvVar: 'MY_CHAIN_RPC_URL',
facilitator: {
url: 'https://facilitator-api.example.com/v1',
apiKeyEnv: 'FACILITATOR_API_KEY',
networkName: 'mychain', // If facilitator uses short names
facilitatorContract: '0x...', // Facilitator's contract address
x402Version: 1, // Facilitator's x402 version
},
token: {
address: '0x...',
name: 'Token Name',
version: '1',
decimals: 18,
},
};
Solana support uses the @x402/svm facilitator pattern where:
Requirements:
SOLANA_FACILITATOR_PRIVATE_KEY — Base58 private keySOLANA_RPC_URL — Solana RPC endpoint *_PAY_TO_ADDRESS_SOL — Solana wallet per routedocker build -t x402-gateway .
docker run -p 8080:8080 --env-file .env x402-gateway
See docs/deploy-gcp.md for full Cloud Run deployment with Secret Manager.
# Quick deploy
gcloud run deploy x402-gateway \
--source . \
--region us-east1 \
--allow-unauthenticated \
--set-env-vars "BASE_RPC_URL=https://..." \
--set-secrets "SETTLEMENT_PRIVATE_KEY=x402-settlement-key:latest"
See docs/deploy-aws.md.
See docs/deploy-paas.md.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health |
Free | Gateway health + backend status |
| GET | /accepted |
Free | Agent discovery — pricing, networks, schemas |
| GET | /.well-known/x402 |
Free | x402 discovery document |
| ALL | /v1/{route}/* |
Paid | Your protected API routes |
Agents call GET /accepted to discover your API before making paid requests:
curl https://your-gateway.com/accepted
Returns supported networks, pricing, and input/output schemas for each route. Compatible with Bazaar agent discovery protocol.
Any wallet that supports the x402 protocol works:
| Wallet | Description |
|---|---|
| @x402/fetch | Official SDK — drop-in fetch replacement |
| OpenClaw / Lobster | Agent framework with built-in x402 |
| AgentWallet (frames.ag) | x402 endpoint for agents |
| Vincent | MPC wallet with policy controls |
| Sponge | x402_fetch one-liner integration |
import { x402Fetch } from '@x402/fetch';
const res = await x402Fetch('https://your-gateway.com/v1/myapi/endpoint', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
wallet // any x402-compatible wallet
});
const data = await res.json();
├── src/
│ ├── index.js # Express app, route registration
│ ├── proxy.js # Backend proxy (injects internal auth)
│ ├── middleware/
│ │ └── x402.js # Payment verification + settlement
│ ├── config/
│ │ └── routes.js # Route definitions + network registry
│ └── utils/
│ └── redis.js # Nonce tracking + idempotency cache
├── public/
│ └── index.html # Landing page (optional)
├── docs/
│ ├── deploy-gcp.md # GCP Cloud Run guide
│ ├── deploy-aws.md # AWS ECS/Fargate guide
│ └── deploy-paas.md # Railway/Fly.io/Render guide
├── Dockerfile
├── cloudbuild.yaml # GCP Cloud Build config
├── .env.example
└── package.json
The gateway includes an optional credit system that compensates payers when their request settles on-chain but the backend returns an error. Instead of refunding on-chain (which costs gas), the gateway issues credits that can be redeemed on subsequent requests.
X-x402-Credit: consumed headerNo on-chain refund, no extra gas, no special tokens. The agent retries identically and it just works.
Set ENABLE_CREDIT_SYSTEM=true in your .env. The system ships disabled by default.
Global defaults are in CREDIT_DEFAULTS in routes.js. Override per-route:
myapi: {
// ... other route config ...
creditOnStatusCodes: [500, 502, 503, 504], // Which backend errors earn credits
maxCreditsPerPayer: 10, // Cap per payer per route
creditTtl: 86400, // 24 hours
},
Set creditOnStatusCodes: [] to disable credits for a specific route.
maxCreditsPerPayer prevents unlimited accumulation from a degraded backendMIT - fork it, ship it, make money with it.
The agent-native LLM router for autonomous agents. 55+ models (8 free), <1ms local routing, USDC payments on Base & Solana via x402.
A payments protocol for the internet. Built on HTTP.
A local-first AI agent with persistent memory, emotional intelligence, and a peer-to-peer skills economy.
The trust layer for agent-to-agent commerce — natural-language mandates, ERC-7710 delegated permissions, x402 payments, escrow, and dispute resolution as one open, catch-all Agent Skill / Claude Code plugin.
Self-healing infrastructure for AI agent payments. 90.3% auto-recovery.
The AI agent with a wallet — spends USDC autonomously to get real work done. Apache-2.0, TypeScript.