x402-payment-gateway
v1.0.0
Published
HTTP 402 Payment Required middleware — monetize AI agent APIs with per-call USDC micropayments via the x402 protocol (Stripe + Base)
Maintainers
Readme
x402-payment-gateway
HTTP 402 Payment Required middleware for monetizing AI agent APIs — charge per API call in USDC via the x402 protocol.
Zero dependencies. Pure Node.js. Works with Express, Fastify, or plain http.createServer.
What is x402?
The x402 protocol (launched by Stripe + Base, February 2026) enables AI agents and APIs to request micropayments inline in HTTP responses. Instead of API keys and subscriptions, callers pay per request in USDC on Base — no KYC, no accounts, instant settlement.
Client → GET /api/generate
Server → 402 Payment Required (price: 0.10 USDC, payTo: 0xYourWallet)
Client → [sends USDC onchain]
Client → GET /api/generate + X-PAYMENT: <proof>
Server → 200 OK + your contentInstall
npm install x402-payment-gatewayQuick Start
const http = require('http');
const x402PaymentGateway = require('x402-payment-gateway');
const gateway = new x402PaymentGateway({
walletAddress: '0xYourBaseWalletAddress',
priceUSDC: 0.10, // $0.10 per API call
network: 'base', // Base mainnet
description: 'AI content generation API',
});
const server = http.createServer(
gateway.gate(async (req, res) => {
// This handler only runs after payment is verified
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ result: 'Your AI-generated content here!' }));
})
);
server.listen(3000, () => console.log('Paid API running on :3000'));With Express
const express = require('express');
const x402PaymentGateway = require('x402-payment-gateway');
const app = express();
const gateway = new x402PaymentGateway({
walletAddress: '0xYourWallet',
priceUSDC: 0.25,
});
// Protect specific routes
app.get('/api/premium', gateway.middleware(), (req, res) => {
res.json({ data: 'Premium paid content' });
});
// Free endpoint (no payment required)
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.listen(3000);Development / Test Mode
For local development (no real payments, no wallet required):
const gateway = new x402PaymentGateway({
testMode: true,
priceUSDC: 0.10,
});Test with curl:
# Returns 402
curl http://localhost:3000/api
# Returns 200 (test mode accepts any X-PAYMENT header)
curl http://localhost:3000/api -H 'X-PAYMENT: test'CLI
# Install globally
npm install -g x402-payment-gateway
# Production
x402-gateway --wallet 0xYourWallet --price 0.10 --port 3000 --network base
# Development / demo
x402-gateway --test --price 0.10 --port 3000Custom Payment Verification
For production use, supply a verifyFn to do real on-chain verification:
const { ethers } = require('ethers');
const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');
const gateway = new x402PaymentGateway({
walletAddress: '0xYourWallet',
priceUSDC: 0.10,
network: 'base',
verifyFn: async (paymentHeader) => {
const payment = JSON.parse(Buffer.from(paymentHeader, 'base64').toString());
const txHash = payment.payload.txHash;
// Verify transaction on-chain
const tx = await provider.getTransaction(txHash);
if (!tx) return { valid: false, error: 'Transaction not found' };
// Add your verification logic here:
// - Check recipient address
// - Check USDC transfer amount
// - Check not expired
return { valid: true, txHash };
},
});Events
gateway.on('payment-required', ({ url, ip }) => {
console.log(`Payment requested for ${url} from ${ip}`);
});
gateway.on('payment-accepted', ({ url, txHash, amount }) => {
console.log(`Payment received: ${amount} USDC — ${txHash}`);
// → log to database, send receipt, etc.
});
gateway.on('payment-rejected', ({ url, error }) => {
console.log(`Payment rejected: ${error}`);
// → rate-limit IP, alert on fraud attempts
});Revenue Stats
const stats = gateway.stats();
// {
// requests: 150, ← 402 responses sent
// paid: 142, ← successful payments
// rejected: 3, ← failed verifications
// revenue: 14.2, ← total USDC earned (number)
// revenueUSDC: '14.200000',
// conversionRate: '94.7%'
// }API Reference
new x402PaymentGateway(options)
| Option | Type | Default | Description |
|---|---|---|---|
| walletAddress | string | required | Base/EVM wallet to receive USDC |
| priceUSDC | number | 0.10 | Price per call in USDC |
| network | string | 'base-sepolia' | 'base' or 'base-sepolia' |
| ttlSeconds | number | 300 | Payment validity window |
| description | string | 'API access payment' | Shown to payer |
| testMode | boolean | false | Accept any payment without verification |
| verifyFn | function | built-in | Async (header) => { valid, txHash, error } |
Methods
gateway.gate(handler)— Wrap a plain(req, res)handlergateway.middleware()— Returns Express-compatible(req, res, next)middlewaregateway.stats()— Current revenue and request statisticsgateway._verifyPayment(header)— Verify a payment header (exposed for testing)
Architecture
┌─────────────────────────────────────────────────────┐
│ Incoming Request │
│ │
│ No X-PAYMENT header → 402 + payment instructions │
│ │
│ X-PAYMENT header present: │
│ → verifyFn(header) → valid? │
│ YES → add X-Payment-Response header → handler │
│ NO → 402 with error details │
└─────────────────────────────────────────────────────┘x402 Resources
License
MIT © OpenClaw
Roadmap
- [ ]
viem/ethersverification helper - [ ] Stripe facilitator integration
- [ ] Per-endpoint pricing support
- [ ] Payment receipt webhooks
- [ ] Usage dashboard
- [ ] Nevermined integration (sub-cent batching)
