Fastify middleware integration for the x402 Payment Protocol. This package provides payment middleware for adding x402 payment requirements to your Fastify applications.
pnpm install @x402/fastifyimport Fastify from "fastify";
import { paymentMiddleware, x402ResourceServer } from "@x402/fastify";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";
const app = Fastify();
const facilitatorClient = new HTTPFacilitatorClient({ url: "https://facilitator.x402.org" });
const resourceServer = new x402ResourceServer(facilitatorClient)
.register("eip155:84532", new ExactEvmScheme());
// Apply the payment middleware with your configuration
paymentMiddleware(
app,
{
"GET /protected-route": {
accepts: {
scheme: "exact",
price: "$0.10",
network: "eip155:84532",
payTo: "0xYourAddress",
},
description: "Access to premium content",
},
},
resourceServer,
);
// Implement your protected route
app.get("/protected-route", async () => {
return { message: "This content is behind a paywall" };
});
app.listen({ port: 3000 });The paymentMiddleware function accepts the following parameters:
paymentMiddleware(
app: FastifyInstance,
routes: RoutesConfig,
server: x402ResourceServer,
paywallConfig?: PaywallConfig,
paywall?: PaywallProvider,
syncFacilitatorOnStart?: boolean
)app(required): The Fastify instance to register hooks onroutes(required): Route configurations for protected endpointsserver(required): Pre-configured x402ResourceServer instancepaywallConfig(optional): Configuration for the built-in paywall UIpaywall(optional): Custom paywall providersyncFacilitatorOnStart(optional): Whether to sync with facilitator on startup (defaults to true)
The FastifyAdapter class implements the HTTPAdapter interface from @x402/core, providing Fastify-specific request handling:
class FastifyAdapter implements HTTPAdapter {
getHeader(name: string): string | undefined;
getMethod(): string;
getPath(): string;
getUrl(): string;
getAcceptHeader(): string;
getUserAgent(): string;
}function paymentMiddleware(
app: FastifyInstance,
routes: RoutesConfig,
server: x402ResourceServer,
paywallConfig?: PaywallConfig,
paywall?: PaywallProvider,
syncFacilitatorOnStart?: boolean,
): void;Registers Fastify hooks (onRequest and onSend) that:
- Use the provided x402ResourceServer for payment processing
- Check if the incoming request matches a protected route
- Validate payment headers if required
- Return payment instructions (402 status) if payment is missing or invalid
- Process the request if payment is valid
- Handle settlement after successful response
Routes are passed as the second parameter to paymentMiddleware:
const routes: RoutesConfig = {
"GET /api/protected": {
accepts: {
scheme: "exact",
price: "$0.10",
network: "eip155:84532",
payTo: "0xYourAddress",
maxTimeoutSeconds: 60,
},
description: "Premium API access",
},
};
paymentMiddleware(app, routes, resourceServer);The middleware automatically displays a paywall UI when browsers request protected endpoints.
Option 1: Full Paywall UI (Recommended)
Install the optional @x402/paywall package for a complete wallet connection and payment UI:
pnpm add @x402/paywallThen configure it:
const paywallConfig: PaywallConfig = {
appName: "Your App Name",
appLogo: "/path/to/logo.svg",
testnet: true,
};
paymentMiddleware(app, routes, resourceServer, paywallConfig);Option 2: Basic Paywall (No Installation)
Without @x402/paywall installed, the middleware returns a basic HTML page with payment instructions.
Option 3: Custom Paywall Provider
Provide your own paywall provider:
paymentMiddleware(app, routes, resourceServer, paywallConfig, customPaywallProvider);paymentMiddleware(
app,
{
"GET /api/premium/*": {
accepts: {
scheme: "exact",
price: "$1.00",
network: "eip155:8453",
payTo: "0xYourAddress",
},
description: "Premium API access",
},
"GET /api/data": {
accepts: {
scheme: "exact",
price: "$0.50",
network: "eip155:84532",
payTo: "0xYourAddress",
maxTimeoutSeconds: 120,
},
description: "Data endpoint access",
},
},
resourceServer,
);paymentMiddleware(
app,
{
"GET /weather": {
accepts: [
{
scheme: "exact",
price: "$0.001",
network: "eip155:84532",
payTo: evmAddress,
},
{
scheme: "exact",
price: "$0.001",
network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
payTo: svmAddress,
},
],
description: "Weather data",
mimeType: "application/json",
},
},
new x402ResourceServer(facilitatorClient)
.register("eip155:84532", new ExactEvmScheme())
.register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme()),
);If you need to use a custom facilitator server, configure it when creating the x402ResourceServer:
import { HTTPFacilitatorClient } from "@x402/core/server";
import { x402ResourceServer } from "@x402/fastify";
import { ExactEvmScheme } from "@x402/evm/exact/server";
const customFacilitator = new HTTPFacilitatorClient({
url: "https://your-facilitator.com",
createAuthHeaders: async () => ({
verify: { Authorization: "Bearer your-token" },
settle: { Authorization: "Bearer your-token" },
}),
});
const resourceServer = new x402ResourceServer(customFacilitator)
.register("eip155:84532", new ExactEvmScheme());
paymentMiddleware(app, routes, resourceServer, paywallConfig);