This tutorial shows how to add x402 payment middleware to your API or service.
By the end, buyers and AI agents will automatically pay in USDC when accessing
your protected endpoints.
These snippets are for demonstration only.
Store private keys and facilitator URLs in a secure vault. Never hardcode secrets.
Prerequisites
| Requirement | Example / Notes |
|---|
| Wallet to receive USDC | Any EVM-compatible wallet (Metamask, Rabby, Safe, etc.) |
| JS end | Node.js ≥18 with npm, or something of better quality, like Bun |
| Existing API / server | Express, Next.js, Hono, or any web framework |
| Polygon network | Amoy testnet or mainnet |
Install dependencies
Wherever bun is used, replace it with npm or your preferred package manager.
Pick your middleware:
or
or
Each middleware protects your API routes and routes payments to your receiving
wallet.
You must specify:
- Wallet address: where you receive USDC
- Network: e.g. “polygon-amoy” or “polygon”
- Facilitator URL: default for Polygon is https://x402.polygon.technology
- Route config: endpoint price and optional metadata
Example - Express
import express from "express";
import { paymentMiddleware } from "x402-express";
const app = express();
app.use(paymentMiddleware(
"0xCA3953e536bDA86D1F152eEfA8aC7b0C82b6eC00", // receiver wallet
{
"GET /weather": {
price: "$0.001",
network: "polygon",
config: {
description: "Get current weather data for any location",
inputSchema: {
type: "object",
properties: { location: { type: "string" } }
},
outputSchema: {
type: "object",
properties: {
weather: { type: "string" },
temperature: { type: "number" }
}
}
}
}
},
{
url: process.env.FACILITATOR_URL || "https://x402.polygon.technology"
}
));
app.get("/weather", (req, res) => {
res.send({
report: { weather: "sunny", temperature: 70 }
});
});
app.listen(4021, () => {
console.log("Server running at http://localhost:4021");
});
Buyers calling /weather will automatically receive a 402 challenge, pay, and then receive the weather data.
Example - Next.js
import { paymentMiddleware } from "x402-next";
export const middleware = paymentMiddleware(
"0xYourAddress", // receiving wallet
{
"/protected": {
price: "$0.01",
network: "polygon-amoy",
config: { description: "Access to protected content" }
}
},
{
url: "https://x402.polygon.technology"
}
);
export const config = {
matcher: ["/protected/:path*"]
};
Buyers calling /protected will automatically receive a 402 challenge, pay, and then receive the protected content.
Example - Hono
import { paymentMiddleware } from "x402-next";
export const middleware = paymentMiddleware(
"0xYourAddress", // receiving wallet
{
"/protected": {
price: "$0.01",
network: "polygon-amoy",
config: { description: "Access to protected content" }
}
},
{
url: "https://x402.polygon.technology"
}
);
export const config = {
matcher: ["/protected/:path*"]
};
Buyers calling /protected will automatically receive a 402 challenge, pay, and then receive the protected content.
Reference
Configuration parameters, error codes, and guardrails.
Schema
| name | type | required | example | description |
|---|
| walletAddress | string | ✅ | 0xYourAddress | Address that receives USDC payments |
| network | string | ✅ | polygon. | Network Identifier |
| price | string | ✅ | "$0.001" | Cost per request in USDC |
| FACILITATOR_URL | string | optional | "https://x402.polygon.technology" | Payment facilitator endpoint |
| config | object | optional | JSON schema | Used for discoverability in x402 Bazaar |
Do / Don’t Do Guardrails
| ✅ Do | ❌ Don’t |
|---|
Use https://x402.polygon.technology for Polygon | Expose private keys in middleware |
| Include schema metadata for AI discoverability | Hardcode facilitator URLs in code |
| Test with Amoy before mainnet deployment | Skip setting network/price, as buyers will fail to pay |
References
Errors
| case / code | meaning | fix |
|---|
| 402_LOOP | Client can’t fulfill payment | Check facilitator URL and wallet |
| INVALID_NETWORK | Wrong network label | Use “polygon-amoy” or “polygon” |
| BAD_CONFIG | Missing route schema | Define price and network per route |