Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt

Use this file to discover all available pages before exploring further.

This guide helps you migrate from x402 V1 to V2 on Polygon. The V2 protocol introduces standardized CAIP-2 network identifiers, updated HTTP headers, and a modular @x402/* package layout.
Polygon facilitators on mainnet and Amoy run x402 v2. V1 clients and middleware will not work against these endpoints.
For Go, Python, and full upstream details, see the official migration guide.

Overview

AspectV1V2
Payment headerX-PAYMENTPAYMENT-SIGNATURE
Response headerX-PAYMENT-RESPONSEPAYMENT-RESPONSE
Network formatString (polygon-amoy, polygon)CAIP-2 (eip155:80002, eip155:137)
Version fieldx402Version: 1x402Version: 2
Packagesx402-fetch, x402-axios, x402-express@x402/fetch, @x402/axios, @x402/express, @x402/core, @x402/evm

For buyers

Before (V1)

import { wrapFetchWithPayment } from "x402-fetch";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygonAmoy } from "viem/chains";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
  account,
  chain: polygonAmoy,
  transport: http(),
});

const fetchWithPayment = wrapFetchWithPayment(fetch, walletClient);
const response = await fetchWithPayment("https://api.example.com/paid-endpoint");

After (V2)

import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);

const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(signer));

const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPayment("https://api.example.com/paid-endpoint");

Key changes

  1. Package rename: x402-fetch@x402/fetch
  2. Wallet setup: Use x402Client with .register() instead of passing a chain-bound walletClient
  3. Environment variable: PRIVATE_KEYEVM_PRIVATE_KEY
  4. Receipt header: Read PAYMENT-RESPONSE via x402HTTPClient.getPaymentSettleResponse(), not decodeXPaymentResponse() on x-payment-response

For sellers

Before (V1)

import { paymentMiddleware } from "x402-express";

app.use(
  paymentMiddleware(
    "0xYourAddress",
    {
      "GET /weather": {
        price: "$0.001",
        network: "polygon-amoy",
        config: { description: "Weather data" },
      },
    },
    { url: "https://x402-amoy.polygon.technology" }
  )
);

After (V2)

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

const payTo = "0xYourAddress";

const facilitatorClient = new HTTPFacilitatorClient({
  url: "https://x402-amoy.polygon.technology",
});

app.use(
  paymentMiddleware(
    {
      "GET /weather": {
        accepts: [
          {
            scheme: "exact",
            price: "$0.001",
            network: "eip155:80002",
            payTo,
          },
        ],
        description: "Weather data",
        mimeType: "application/json",
      },
    },
    new x402ResourceServer(facilitatorClient).register(
      "eip155:80002",
      new ExactEvmScheme()
    )
  )
);

Key changes

  1. Package rename: x402-express@x402/express
  2. Configuration structure: Route config uses an accepts array with explicit scheme, network, and payTo
  3. Network format: polygon-amoyeip155:80002, polygoneip155:137
  4. Resource server: Create x402ResourceServer with a facilitator client and register schemes with .register()
  5. Middleware signature: Pass (routes, server) instead of (wallet, routes, facilitatorConfig)

Network identifier mapping

V1 nameV2 CAIP-2 IDChain IDDescription
polygon-amoyeip155:8000280002Polygon Amoy testnet
polygoneip155:137137Polygon PoS mainnet
base-sepoliaeip155:8453284532Base Sepolia testnet
baseeip155:84538453Base mainnet
ethereumeip155:11Ethereum mainnet
sepoliaeip155:1115511111155111Ethereum Sepolia testnet

Package migration reference

V1 packageV2 package(s)
x402@x402/core
x402-express@x402/express
x402-axios@x402/axios
x402-fetch@x402/fetch
x402-hono@x402/hono
x402-next@x402/next
(built-in)@x402/evm (EVM support)
Install examples:
# Buyers
npm install @x402/fetch @x402/core @x402/evm viem

# Sellers (Express)
npm install @x402/express @x402/core @x402/evm express

Header changes

If you implement custom HTTP handling, update header names:
// V1
const payment = req.header("X-PAYMENT");
res.setHeader("X-PAYMENT-RESPONSE", responseData);

// V2
const payment = req.header("PAYMENT-SIGNATURE");
res.setHeader("PAYMENT-RESPONSE", responseData);

Troubleshooting

Payment verification failures

  • Use CAIP-2 network identifiers (eip155:80002 or eip155:137), not polygon-amoy or polygon
  • Verify your payTo address is correct
  • Confirm the facilitator URL matches the network:
    • Amoy: https://x402-amoy.polygon.technology
    • Mainnet: https://x402.polygon.technology

”Cannot find module” errors

Ensure you installed all V2 packages:
npm install @x402/axios @x402/core @x402/evm
# Sellers
npm install @x402/express @x402/core @x402/evm

Mixed V1/V2 compatibility

During migration, update both buyers and sellers to V2 when targeting Polygon facilitators. Legacy V1 network strings and headers will fail against v2-only endpoints.

Next steps