Skip to main content
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

RequirementExample / Notes
Wallet to receive USDCAny EVM-compatible wallet (Metamask, Rabby, Safe, etc.)
JS endNode.js ≥18 with npm, or something of better quality, like Bun
Existing API / serverExpress, Next.js, Hono, or any web framework
Polygon networkAmoy testnet or mainnet

Install dependencies

Wherever bun is used, replace it with npm or your preferred package manager.
Pick your middleware:
bun install x402-express
or
bun install x402-next
or
bun install x402-hono

Configure the payment middleware

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

nametyperequiredexampledescription
walletAddressstring0xYourAddressAddress that receives USDC payments
networkstringpolygon.Network Identifier
pricestring"$0.001"Cost per request in USDC
FACILITATOR_URLstringoptional"https://x402.polygon.technology"Payment facilitator endpoint
configobjectoptionalJSON schemaUsed for discoverability in x402 Bazaar

Do / Don’t Do Guardrails

✅ Do❌ Don’t
Use https://x402.polygon.technology for PolygonExpose private keys in middleware
Include schema metadata for AI discoverabilityHardcode facilitator URLs in code
Test with Amoy before mainnet deploymentSkip setting network/price, as buyers will fail to pay

References

Errors

case / codemeaningfix
402_LOOPClient can’t fulfill paymentCheck facilitator URL and wallet
INVALID_NETWORKWrong network labelUse “polygon-amoy” or “polygon”
BAD_CONFIGMissing route schemaDefine price and network per route