DEV Community

Solo Earn
Solo Earn

Posted on Originally published at x402-seller-kit.soloearn.workers.dev

How do I add x402 payments to an Express / Next.js API?

Quick answer: on Express, wrap routes with paymentMiddleware from @x402/express. On Next.js, use paymentProxy for page routes (or many routes at once) and withX402 for API route handlers — withX402 settles only after a successful response (status < 400). Start on Base Sepolia with the x402.org facilitator; for mainnet switch to eip155:8453 and a production facilitator. Full walkthrough: Quickstart for Sellers.

Minimal Express (Base Sepolia)

// npm i express @x402/express@2.28.0 @x402/core@2.28.0 @x402/evm@2.28.0
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";

const app = express();
const facilitatorClient = new HTTPFacilitatorClient({
  url: "https://x402.org/facilitator", // testnet only
});
app.use(
  paymentMiddleware(
    {
      "GET /weather": {
        accepts: [{
          scheme: "exact",
          price: "$0.001",
          network: "eip155:84532",
          payTo: "0xYourEvmAddress",
        }],
        description: "Weather data",
        mimeType: "application/json",
      },
    },
    new x402ResourceServer(facilitatorClient)
      .register("eip155:*", new ExactEvmScheme()), // covers Sepolia + mainnet
  ),
);
app.get("/weather", (req, res) => {
  res.send({ report: { weather: "sunny", temperature: 70 } });
});
app.listen(4021);
Enter fullscreen mode Exit fullscreen mode

On 15 Oct 2026, with @x402/express 2.28.0, an unpaid curl http://localhost:4021/weather returned HTTP 402 with a PAYMENT-REQUIRED header (x402Version 2, exact on eip155:84532, amount 1000 atomic USDC). We did not complete a paid retry in that smoke test.

Next.js: paymentProxy vs withX402

Per the official quickstart: withX402 only settles after status < 400 (recommended for API routes). paymentProxy is better for page routes; on API routes it can charge failed responses. The RoutesConfig path key for withX402 must match the served path exactly (including any basePath) or protection is skipped with a warning.

Mainnet: three edits, not two

Do not reuse https://x402.org/facilitator on mainnet; the quickstart says it is for testnet only. On @x402/core 2.28.0 you need three edits. If the server still has .register("eip155:84532", …), as the official Express quickstart shows, changing only the facilitator URL and network makes paymentMiddleware fail at startup and the process exits:

RouteConfigurationError: x402 Route Configuration Errors:
  - Route "GET /weather": No scheme implementation registered for "exact" on network "eip155:8453"
Enter fullscreen mode Exit fullscreen mode
  1. Facilitator → a production facilitator (list).
  2. Network → network: "eip155:8453" (Base mainnet).
  3. Register → .register("eip155:8453", new ExactEvmScheme()) or .register("eip155:*", new ExactEvmScheme()). The snippet above already uses eip155:*, so if you copied it you only need steps 1 and 2.

Canonical guide (with Next.js snippets, FAQ, checker links): https://x402-seller-kit.soloearn.workers.dev/guides/add-x402-express-nextjs

Top comments (0)