X402

x402 Quickstart for Sellers

How to use x402 as a seller

Integrate x402 into your API or service to accept on-chain payments in USDC. Buyers or AI agents can automatically pay when accessing your protected endpoints.

You will achieve:

  • Protect endpoints behind a 402 paywall
  • Receive USDC payments on Polygon
  • Publish discoverable, pay-per-use APIs

Security notice

These snippets are for demonstration only.
Store private keys and facilitator URLs in a secure vault — never hardcode secrets.

Overview

x402 brings native crypto payments to APIs using the HTTP 402 Payment Required status. When a buyer hits a protected route, the x402 middleware:

  1. Returns a 402 response describing price and network metadata
  2. Waits for payment through a facilitator (e.g. https://facilitator.x402.rs)
  3. Confirms payment and releases the response automatically

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

For reference examples:

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 Amoy — https://facilitator.x402.rs
  • Route config: endpoint price and optional metadata

For Amoy testnet onboarding, contact Polygon DevRel in our telegram.

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-amoy",
      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://facilitator.x402.rs"
  }
));

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://facilitator.x402.rs"
  }
);

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://facilitator.x402.rs"
  }
);

export const config = {
  matcher: ["/protected/:path*"]
};

Buyers calling /protected will automatically receive a 402 challenge, pay, and then receive the protected content.

Extras

Debugging, sanity checks, and guardrails.

Schema

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

Do / Don't Do Guardrails

✅ Do❌ Don't
Use https://facilitator.x402.rs for Polygon testnetExpose private keys in middleware
Include schema metadata for AI discoverabilityHardcode facilitator URLs in code
Test with Amoy before mainnet deploymentSkip setting network/price — 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