This repository provides working examples and reference implementations for integrating x402-open into your projects. x402-open is a decentralized facilitator toolkit for the X402 protocol that enables micro-payments for API access using blockchain networks.
x402-open is an open-source decentralized implementation of the X402 protocol that allows you to:
- Run facilitator nodes - Support both EVM (Ethereum, Base, etc.) and SVM (Solana) networks
- Convert existing servers to nodes - Expose and endpoint for
verifyandsettlerequests on your server to remove reliance on centralized facilitators - Auto-registration - Nodes can self-register with gateways without manual configuration
- Framework integration - Works with Express.js and other popular Node.js frameworks
Install x402-open and required dependencies:
pnpm add x402-open express viem
# or
npm i x402-open express viemNote: express is a peer dependency of x402-open.
This example repository demonstrates various integration patterns for x402-open:
buyer.js- Ethereum/EVM buyer example usingx402-axiosbuyer_solana.js- Solana buyer exampleseller.js- Express server with payment middleware and co-located facilitator nodeseller_hono.js- Hono server examplegateway.js- HTTP gateway that routes requests across multiple facilitator nodesnodeA.js,nodeB.js,nodeC.js- Standalone facilitator nodes with auto-registrationdocker-compose.yml- Multi-node deployment setupnginx/nginx.conf- Load balancer configuration
- Node.js 18+
- pnpm (or npm)
- Docker (for multi-node deployment)
- Private keys for facilitator nodes (EVM and/or Solana)
Note: There is one public gateway available at https://facilitator.x402open.org that you can use for production deployments.
pnpm installCreate a .env file with the following variables:
PRIVATE_KEY- Ethereum private key for facilitator (EVM networks)SOLANA_PRIVATE_KEY- Solana private key (optional, for Solana support)PAYER_PRIVATE_KEY- Private key for buyer scriptsGATEWAY_URLS- Comma-separated list of gateway URLs for auto-registration (optional)NODE_BASE_URL- Base URL for this node (for auto-registration)
This demonstrates a server that handles payments and runs its own facilitator:
node seller.jsThe server will:
- Start a facilitator node on
/facilitatorendpoint - Protect routes using
x402-expresspayment middleware - Handle payment verification and settlement
You can extend seller.js with methods defined in nodeA, nodeB or nodeC such as gateway auto-registration
Run a facilitator node that can be used by other services:
node nodeA.jsThis node will:
- Start on
http://localhost:4101/facilitator - Support EVM (Base Sepolia) and Solana (Devnet) networks
- Auto-register with configured gateways
- Expose endpoints:
GET /facilitator/supported,POST /facilitator/verify,POST /facilitator/settle
Run a gateway that routes requests across multiple facilitator nodes:
node gateway.jsThe gateway will:
- Aggregate supported networks from all registered nodes
- Route
verifyrequests to random nodes - Ensure
settlerequests go to the same node asverify(sticky routing)
- Start a seller server:
node seller.js- In another terminal, run the buyer:
node buyer.js
# or for Solana
node buyer_solana.jsThis demonstrates the complete payment flow where the buyer pays to access the /weather endpoint.
For a full network setup with multiple nodes and gateways:
docker compose build
docker compose up -dRun a facilitator node alongside your API server. See seller.js for a complete example:
import express from "express";
import { paymentMiddleware } from "x402-express";
import { Facilitator, createExpressAdapter } from "x402-open";
import { baseSepolia } from "viem/chains";
const app = express();
app.use(express.json());
// Create and mount facilitator node
const facilitator = new Facilitator({
evmPrivateKey: process.env.PRIVATE_KEY,
evmNetworks: [baseSepolia],
// Optional: Add Solana support
// svmPrivateKey: process.env.SOLANA_PRIVATE_KEY,
// svmNetworks: ["solana-devnet"],
});
// Exposes: GET /facilitator/supported, POST /facilitator/verify, POST /facilitator/settle
createExpressAdapter(facilitator, app, "/facilitator");
// Add payment middleware pointing to local facilitator
app.use(paymentMiddleware(
"YOUR_WALLET_ADDRESS",
{
"GET /weather": {
price: "$0.0001",
network: "base-sepolia" // or "solana-devnet"
}
},
{
url: "http://localhost:4021/facilitator"
}
));
app.get("/weather", (req, res) => {
res.json({ weather: "sunny", temperature: 70 });
});
app.listen(4021, () => console.log("Server on http://localhost:4021"));Point your payment middleware to an external facilitator or gateway:
import { paymentMiddleware } from "x402-express";
app.use(paymentMiddleware(
"YOUR_WALLET_ADDRESS",
{
"GET /api/data": {
price: "$0.01",
network: "base-sepolia" // or "solana-devnet"
}
},
{
url: "https://facilitator.x402open.org/facilitator" // Public gateway
}
));Note: For local development, use http://localhost:8080/facilitator (your local gateway) or http://localhost:4021/facilitator (co-located node). For production, use the public facilitator at https://facilitator.x402open.org.
Run a facilitator node that other services can use. See nodeA.js for a complete example:
import express from "express";
import { Facilitator, createExpressAdapter, startGatewayRegistration } from "x402-open";
import { baseSepolia } from "viem/chains";
const app = express();
app.use(express.json());
const facilitator = new Facilitator({
evmPrivateKey: process.env.PRIVATE_KEY,
evmNetworks: [baseSepolia],
svmNetworks: ["solana-devnet"], // Optional Solana support
});
createExpressAdapter(facilitator, app, "/facilitator");
// Auto-register with gateway(s)
startGatewayRegistration({
gatewayUrls: ["http://localhost:8080/facilitator"],
nodeBaseUrl: "http://localhost:4101/facilitator",
kindsProvider: async () => {
const res = await fetch("http://localhost:4101/facilitator/supported");
const j = await res.json();
return j?.kinds ?? [];
},
debug: true,
});
app.listen(4101, () => console.log("Facilitator node on http://localhost:4101"));Create a gateway that routes requests across multiple facilitator nodes. See gateway.js for a complete example:
import express from "express";
import { createHttpGatewayAdapter } from "x402-open";
const app = express();
app.use(express.json());
createHttpGatewayAdapter(app, {
basePath: "/facilitator",
debug: true,
});
app.listen(8080, () => console.log("Gateway on http://localhost:8080"));Use the payment interceptor with your HTTP client. See buyer.js for a complete example:
import { withPaymentInterceptor } from "x402-axios";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";
import axios from "axios";
// Create wallet client
const account = privateKeyToAccount(process.env.PAYER_PRIVATE_KEY);
const client = createWalletClient({
account,
transport: http(),
chain: baseSepolia,
});
// Create Axios instance with payment handling
const api = withPaymentInterceptor(axios.create(), client);
// Make request to paid endpoint
const response = await api.get("/weather");
console.log(response.data);For Solana, use the Solana-specific buyer example (buyer_solana.js).
The Facilitator class supports both EVM and Solana networks:
const facilitator = new Facilitator({
// EVM support (Ethereum, Base, etc.)
evmPrivateKey: process.env.PRIVATE_KEY,
evmNetworks: [baseSepolia], // or any viem chain
// SVM (Solana) support (optional)
svmPrivateKey: process.env.SOLANA_PRIVATE_KEY,
svmNetworks: ["solana-devnet"], // or "solana-mainnet"
});GET /facilitator/supported- Returns supported payment schemes and networksPOST /facilitator/verify- Verifies a payment payloadPOST /facilitator/settle- Settles a verified payment
The HTTP gateway provides:
- Random node selection for
verifyrequests - Sticky routing for
settlerequests (same node asverifyby payer/header) - Network aggregation - Combines supported networks from all nodes
- Auto-registration - Nodes can self-register without manual config
- Fallback handling - Routes to alternative nodes on errors
Nodes can automatically register with one or more gateways:
import { startGatewayRegistration } from "x402-open";
const stop = startGatewayRegistration({
gatewayUrls: ["http://localhost:8080/facilitator"],
nodeBaseUrl: "http://localhost:4101/facilitator",
kindsProvider: async () => {
const res = await fetch("http://localhost:4101/facilitator/supported");
const j = await res.json();
return j?.kinds ?? [];
},
debug: true,
});
// Call stop() to stop heartbeatsNodes send periodic heartbeats; gateways expire entries after ~2 minutes of inactivity.
x402-open integrates with popular Node.js frameworks:
- Express.js -
x402-express(seeseller.jsexample) - Hono -
x402-hono(seeseller_hono.jsexample) - Axios client -
x402-axios(seebuyer.jsexample) - Fetch API -
x402-fetchfor native fetch with payment handling
- EVM Networks - Ethereum, Base Sepolia (testnet), and other EVM-compatible chains
- Solana - Devnet and Mainnet
Check the x402-open GitHub repository for the latest supported networks.
When integrating x402-open into your project:
- Install
x402-openand required dependencies (express,viem) - Set up environment variables (
PRIVATE_KEY, optionalSOLANA_PRIVATE_KEY) - Create a
Facilitatorinstance with your network configuration - Mount facilitator endpoints using
createExpressAdapter - (Optional) Set up auto-registration with gateway(s)
- Add payment middleware to your API routes using
x402-expressorx402-hono - Configure route pricing and network requirements
- Test with buyer clients using
x402-axiosorx402-fetch
- x402-open GitHub Repository - Source code and full documentation
- X402 Protocol Documentation - Protocol specification and details