Documentation Index
Fetch the complete documentation index at: https://docs.x402x.ai/llms.txt
Use this file to discover all available pages before exploring further.
What you need to do
- Obtain recipient address (EIP-7702)
- Create PaymentRequirements
- Parse client
X-Payment, verify and settle
- Return the resource or a standard 402 accordingly
Prerequisites
- Seller recipient address: go to
app.x402x.ai to create and obtain (EIP-7702 deployed address)
- Token:
- USD1 (BSC):
0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d
- Install dependencies (server):
bun add x402x-server@beta x402x-facilitator@beta express viem
Core flow (server)
Generic
Express middleware
Hono middleware
Create server.ts, core logic:const client = createPublicClient({ chain: bsc, transport: http() });
const facilitator = new Facilitator({
recipientAddress: RECIPIENT_ADDRESS,
waitUntil: "confirmed",
});
const server = new X402Server({ client, facilitator });
await server.initialize(["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"]);
const requirements = await server.createRequirements({
asset: "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d", // USD1
maxAmountRequired: parseEther("0.01").toString(), // 0.01 USD1 (18 decimals)
description: "Premium API",
resource: req.url,
});
const result = await server.process(req.headers["x-payment"] as string, requirements);
if (!result.success) {
// Parse/verify failed: return standard 402; handle other errors as needed
return res.status(result.status).json(result.response);
}
return res.json({ data, payer: result.data.payer, txHash: result.data.txHash });
View full server code (Generic)
import express from "express";
import { config } from "dotenv";
import { X402Server } from "x402x-server";
import { Facilitator } from "x402x-facilitator";
import { createPublicClient, http } from "viem";
import { parseEther } from "viem";
import { bsc } from "viem/chains";
config();
const app = express();
app.use(express.json());
const PORT = 3939;
const RECIPIENT_ADDRESS=0xSellerRecipientAddress;
async function main() {
// Create viem client
const client = createPublicClient({
chain: bsc,
transport: http(),
});
// Create facilitator
const facilitator = new Facilitator({
recipientAddress: RECIPIENT_ADDRESS,
waitUntil: "confirmed",
});
// Create server
const server = new X402Server({ client, facilitator });
// Pre-detect supported payment types for current token
await server.initialize(["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"]);
// Paid API
app.post("/api/data", async (req, res) => {
try {
// Create payment requirements (you can dynamically adjust amount/description/resource)
const requirements = await server.createRequirements({
asset: "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d", // USD1
maxAmountRequired: parseEther("0.01").toString(), // 0.01 USD1
description: "API access",
resource: `http://localhost:${PORT}/api/data`,
});
// Process the payment
const result = await server.process(
req.headers["x-payment"] as string,
requirements
);
if (!result.success) {
return res.status(result.status).json(result.response);
}
// Payment succeeded, return data and optionally log reconciliation info
res.json({
message: "Success!",
data: "This is premium content",
payer: result.data.payer,
txHash: result.data.txHash,
});
} catch (error) {
console.error("Error:", error);
res.status(500).json({
error: "Internal server error",
message: error instanceof Error ? error.message : "Unknown error",
});
}
});
app.listen(PORT, () => {
console.log(`✅ Server running on http://localhost:${PORT}`);
});
}
main();
Create server.ts, core logic:const client = createPublicClient({
chain: bsc,
transport: http(),
});
const facilitator = new Facilitator({
recipientAddress: RECIPIENT_ADDRESS,
});
const server = new X402Server({ client, facilitator });
await server.initialize(["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"]);
const paymentMiddleware = createExpressMiddleware({
server,
getToken: () => "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d",
getAmount: () => parseEther("0.01").toString(),
getConfig: () => ({
description: "Premium API access",
mimeType: "application/json",
}),
});
app.post("/api/data", paymentMiddleware, (req, res) => {
const { payer, txHash } = req.x402!;
res.json({
success: true,
data: "Premium content",
payer,
txHash,
});
});
View full server code (Express middleware)
import express from "express";
import { config } from "dotenv";
import { X402Server, createExpressMiddleware } from "x402x-server";
import { Facilitator } from "x402x-facilitator";
import { createPublicClient, http, parseEther } from "viem";
import { bsc } from "viem/chains";
config();
const app = express();
app.use(express.json());
const PORT = 3939;
async function main() {
const client = createPublicClient({
chain: bsc,
transport: http(),
});
const facilitator = new Facilitator({
recipientAddress: RECIPIENT_ADDRESS,
});
const server = new X402Server({ client, facilitator });
await server.initialize(["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"]);
const paymentMiddleware = createExpressMiddleware({
server,
getToken: () => "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d",
getAmount: () => parseEther("0.01").toString(),
getConfig: () => ({
description: "Premium API access",
mimeType: "application/json",
}),
});
app.get("/health", (_, res) => {
res.json({ status: "ok" });
});
app.post("/api/data", paymentMiddleware, (req, res) => {
const { payer, txHash } = req.x402!;
res.json({
success: true,
data: "Premium content",
payer,
txHash,
});
});
app.listen(PORT, () => {
console.log(`✅ Server running on http://localhost:${PORT}`);
});
}
main();
Create server.ts, core logic:const client = createPublicClient({
chain: bsc,
transport: http(),
});
const facilitator = new Facilitator({
recipientAddress: RECIPIENT_ADDRESS,
});
const server = new X402Server({ client, facilitator });
await server.initialize(["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"]);
const paymentMiddleware = createHonoMiddleware({
server,
getToken: () => "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d",
getAmount: () => parseEther("0.01").toString(),
getConfig: () => ({
description: "Premium API access",
mimeType: "application/json",
}),
});
app.post("/api/data", paymentMiddleware, (c) => {
const { payer, txHash } = c.get("x402");
return c.json({
success: true,
data: "Premium content",
payer,
txHash,
});
});
View full server code (Hono middleware)
import { config } from "dotenv";
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { createHonoMiddleware, X402Server } from "x402x-server";
import { Facilitator } from "x402x-facilitator";
import { createPublicClient, http, parseEther } from "viem";
import { bsc } from "viem/chains";
config();
// Define Hono env types
type Env = {
Variables: {
x402: {
payer: string;
txHash: string;
};
};
};
const ASSET_ADDRESS = '0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d';
const PORT = 3939;
async function main() {
const app = new Hono<Env>();
const client = createPublicClient({
chain: bsc,
transport: http(),
});
const facilitator = new Facilitator({
recipientAddress: RECIPIENT_ADDRESS,
});
const server = new X402Server({ client, facilitator });
await server.initialize([ASSET_ADDRESS]);
const paymentMiddleware = createHonoMiddleware({
server,
getToken: () => ASSET_ADDRESS,
getAmount: () => parseEther("0.01").toString(),
getConfig: () => ({
description: "Premium API access",
mimeType: "application/json",
}),
});
app.get("/health", (c) => {
return c.json({ status: "ok" });
});
app.post("/api/data", paymentMiddleware, (c) => {
const { payer, txHash } = c.get("x402");
return c.json({
success: true,
data: "Premium content",
payer,
txHash,
});
});
serve({
fetch: app.fetch,
port: PORT,
});
console.log(`Server running on port ${PORT}`);
}
main();
Recommended practices
- Warm-up detection cache: call
server.initialize(tokens) on startup to reduce first-request latency
- Fast mode: disable auto detection when the payment type is known (
autoDetect: false)
- Reuse fixed prices: cache and reuse
requirements for fixed-price endpoints to reduce creation overhead
- Error layering: parse/verify → return 402; settle → return 500 and log
Common integration patterns
- Fixed-price API: create and cache
requirements at app startup, reuse on requests
- Dynamic pricing API: compute
maxAmountRequired and description from request context
// Fixed-price reuse example (on startup)
const cachedRequirements = await server.createRequirements({
asset: "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d",
maxAmountRequired: parseEther("1").toString(),
description: "Premium API (fixed price)",
resource: "http://localhost:3000/api/data",
mimeType: "application/json",
maxTimeoutSeconds: 3600,
network: "bsc",
});
// Reuse cachedRequirements when handling requests
const result = await server.process(req.headers["x-payment"] as string, cachedRequirements);
Error handling and responses
- Parse/verify failed: return standard 402 directly (
result.status and result.response)
- Settlement failed or internal exception: return 500 and log details (including
payer/txHash if available)
Server SDK
API and middleware
Facilitator
Verification and settlement
Payment Requirements
Field spec
402 Response Format
Standard 402