> ## 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.

# Migration: x402 V1 to V2

> Guide for upgrading Polygon x402 integrations from V1 to V2: packages, headers, network identifiers, and middleware patterns.

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.

<Note>
  Polygon facilitators on [mainnet](https://x402.polygon.technology) and
  [Amoy](https://x402-amoy.polygon.technology) run **x402 v2**. V1 clients and
  middleware will not work against these endpoints.
</Note>

For Go, Python, and full upstream details, see the
[official migration guide](https://docs.x402.org/guides/migration-v1-to-v2).

## Overview

| Aspect          | V1                                         | V2                                                                       |
| --------------- | ------------------------------------------ | ------------------------------------------------------------------------ |
| Payment header  | `X-PAYMENT`                                | `PAYMENT-SIGNATURE`                                                      |
| Response header | `X-PAYMENT-RESPONSE`                       | `PAYMENT-RESPONSE`                                                       |
| Network format  | String (`polygon-amoy`, `polygon`)         | CAIP-2 (`eip155:80002`, `eip155:137`)                                    |
| Version field   | `x402Version: 1`                           | `x402Version: 2`                                                         |
| Packages        | `x402-fetch`, `x402-axios`, `x402-express` | `@x402/fetch`, `@x402/axios`, `@x402/express`, `@x402/core`, `@x402/evm` |

## For buyers

### Before (V1)

```ts theme={null}
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)

```ts theme={null}
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_KEY` → `EVM_PRIVATE_KEY`
4. **Receipt header:** Read `PAYMENT-RESPONSE` via `x402HTTPClient.getPaymentSettleResponse()`, not `decodeXPaymentResponse()` on `x-payment-response`

## For sellers

### Before (V1)

```ts theme={null}
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)

```ts theme={null}
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-amoy` → `eip155:80002`, `polygon` → `eip155: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 name        | V2 CAIP-2 ID      | Chain ID | Description              |
| -------------- | ----------------- | -------- | ------------------------ |
| `polygon-amoy` | `eip155:80002`    | 80002    | Polygon Amoy testnet     |
| `polygon`      | `eip155:137`      | 137      | Polygon PoS mainnet      |
| `base-sepolia` | `eip155:84532`    | 84532    | Base Sepolia testnet     |
| `base`         | `eip155:8453`     | 8453     | Base mainnet             |
| `ethereum`     | `eip155:1`        | 1        | Ethereum mainnet         |
| `sepolia`      | `eip155:11155111` | 11155111 | Ethereum Sepolia testnet |

## Package migration reference

| V1 package     | V2 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:

```bash theme={null}
# 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:

```ts theme={null}
// 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:

```bash theme={null}
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

* [x402 Quickstart for Buyers](./quickstart-buyers.mdx)
* [x402 Quickstart for Sellers](./quickstart-sellers.mdx)
* [Using the Polygon Facilitator](./using-polygon-facilitator.mdx)
* [Official migration guide](https://docs.x402.org/guides/migration-v1-to-v2)
