@x402/server
TypeScript SDK for API providers who want to receive x402 payments. Middleware for Express, Next.js, and other Node.js frameworks.
Installation
npm install @x402/server
# or
pnpm add @x402/server
# or
yarn add @x402/serverExpress.js
The SDK provides middleware that integrates seamlessly with Express:
import express from 'express';
import { createX402Middleware } from '@x402/server';
const app = express();
app.use(express.json());
const x402 = createX402Middleware({
gatewayUrl: 'https://xfour.xyz/api/gateway',
apiKey: process.env.X402_SERVER_KEY!,
payToAddress: process.env.ETHEREUM_ADDRESS!, // Your Ethereum wallet
network: 'mainnet',
});
// Protect specific routes
app.post('/api/ai/complete',
x402.requirePayment(0.05), // 0.05 MNEE per request
async (req, res) => {
// Only executes if payment verified!
// Payment info available in req.x402Payment
const result = await processAI(req.body);
res.json(result);
}
);
// Protect entire route groups
app.use('/api/premium', x402.middleware(0.10));
app.listen(3000);Configuration Options
| Option | Type | Required | Description |
|---|---|---|---|
| gatewayUrl | string | Yes | x402 Gateway URL |
| apiKey | string | Yes | Your provider API key |
| payToAddress | string | Yes | Your Ethereum wallet address (0x...) |
| network | 'sepolia' | 'mainnet' | No | Ethereum network (default: mainnet) |
| defaultPrice | number | No | Default price if not specified per-route |
| onPaymentVerified | function | No | Callback when payment verified |
| onPaymentRequired | function | No | Callback when 402 is sent |
Next.js API Routes
For Next.js App Router, manually handle the payment flow:
// app/api/ai/complete/route.ts
import { createX402Middleware } from '@x402/server';
import type { NextRequest } from 'next/server';
const x402 = createX402Middleware({
gatewayUrl: process.env.X402_GATEWAY_URL!,
apiKey: process.env.X402_SERVER_KEY!,
payToAddress: process.env.MNEE_ADDRESS!,
network: 'mainnet',
});
export async function POST(request: NextRequest) {
// Extract payment proof from headers
const proofHeader = request.headers.get('X-MOCK-PAID-INVOICE');
if (!proofHeader) {
// No proof - return 402 with invoice headers
const headers = x402.createInvoiceHeaders(
0.05, // amount
undefined, // invoiceId (auto-generated)
'AI Completion' // description
);
return new Response(
JSON.stringify({ error: 'Payment Required' }),
{
status: 402,
headers: {
'Content-Type': 'application/json',
...headers,
},
}
);
}
// Verify payment
const verification = await x402.verifyPayment(proofHeader);
if (!verification.verified) {
return new Response(
JSON.stringify({
error: 'Payment verification failed',
code: verification.errorCode
}),
{ status: 403 }
);
}
// Payment verified - process request
const body = await request.json();
const result = await processAI(body);
return Response.json(result);
}Pricing Strategies
Per-Endpoint Pricing
Set different prices for each endpoint:
app.post('/api/basic', x402.requirePayment(0.01), basicHandler);
app.post('/api/premium', x402.requirePayment(0.10), premiumHandler);
app.post('/api/enterprise', x402.requirePayment(1.00), enterpriseHandler);Dynamic Pricing
Calculate price based on request content:
app.post('/api/process', async (req, res, next) => {
// Calculate price based on request
const complexity = calculateComplexity(req.body);
const price = complexity * 0.01;
// Apply dynamic pricing
return x402.requirePayment(price)(req, res, next);
});Route Group Pricing
Apply pricing to entire route groups:
// Free tier
app.use('/api/free', freeRoutes);
// Paid tier
app.use('/api/paid', x402.middleware(0.05), paidRoutes);
// Premium tier
app.use('/api/premium', x402.middleware(0.20), premiumRoutes);API Methods
requirePayment(amount | config)
Returns middleware that requires payment:
// Simple usage with amount
app.post('/api/endpoint', x402.requirePayment(0.05), handler);
// With full config
app.post('/api/endpoint',
x402.requirePayment({
amount: 0.05,
invoiceId: 'custom-id', // optional
description: 'API Call', // optional
}),
handler
);verifyPayment(invoiceId)
Manually verify a payment (for non-middleware usage):
const result = await x402.verifyPayment(invoiceId);
if (result.verified) {
console.log('Payment verified!');
console.log('Amount:', result.amount);
console.log('Tx Hash:', result.txHash);
}createInvoiceHeaders(amount, invoiceId?, description?)
Generate x402 headers for manual 402 responses:
const headers = x402.createInvoiceHeaders(0.05, undefined, 'AI Completion');
// Returns:
// {
// 'X-402-Invoice-Id': 'inv_...',
// 'X-402-Amount': '0.05',
// 'X-402-Pay-To': '1ABC...',
// 'X-402-Network': 'mainnet',
// 'X-402-Description': 'AI Completion'
// }extractProof(headers)
Extract payment proof from request headers:
const invoiceId = x402.extractProof(request.headers);Request Augmentation
When payment is verified, the middleware adds payment info to the request:
app.post('/api/endpoint', x402.requirePayment(0.05), (req, res) => {
// Payment info is available
console.log(req.x402Payment);
// {
// verified: true,
// invoiceId: 'inv_...',
// paymentId: 'payment_...',
// amount: 0.05,
// paidAt: 1234567890,
// txHash: 'abc...'
// }
});Examples
With Payment Callbacks
const x402 = createX402Middleware({
gatewayUrl: process.env.X402_GATEWAY_URL!,
apiKey: process.env.X402_SERVER_KEY!,
payToAddress: process.env.MNEE_ADDRESS!,
// Log all payment verifications
onPaymentVerified: async (payment) => {
await analytics.track('payment_verified', {
invoiceId: payment.invoiceId,
amount: payment.amount,
});
},
// Log all 402 responses
onPaymentRequired: async (invoice) => {
await analytics.track('payment_required', {
invoiceId: invoice.invoiceId,
amount: invoice.amount,
});
},
});Error Handling
app.post('/api/endpoint',
x402.requirePayment(0.05),
async (req, res) => {
try {
const result = await processRequest(req.body);
res.json(result);
} catch (error) {
// Your error handling
res.status(500).json({ error: 'Processing failed' });
}
}
);
// Payment verification failures return 403 automaticallyTesting
For testing, use the Sepolia testnet:
const x402 = createX402Middleware({
gatewayUrl: 'http://localhost:3000/api/gateway',
apiKey: process.env.X402_SERVER_KEY_TEST!,
payToAddress: 'test-address',
network: 'sepolia', // Use Sepolia testnet for testing
});Environment Compatibility
This SDK works in Node.js 18+, Express.js 4.x, Next.js 13+ API Routes, and any Node.js web framework with standard req/res.