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

# x402 Quickstart for Sellers

> Tutorial: protect API endpoints with x402 v2 payment middleware to accept USDC payments on Polygon.

This tutorial shows how to add **x402 v2** payment middleware to your API or
service. By the end, buyers and AI agents will automatically pay in USDC when
accessing your protected endpoints.

<Note>
  Polygon facilitators on [Amoy](https://x402-amoy.polygon.technology) and
  [mainnet](https://x402.polygon.technology) run **x402 v2**. Use the `@x402/*`
  packages below. For Go or Python server examples, see the
  [official x402 seller quickstart](https://docs.x402.org/getting-started/quickstart-for-sellers).
</Note>

<Warning title="Security notice">
  These snippets are for demonstration only.
  Store private keys and facilitator URLs in a secure vault. Never hardcode secrets.
</Warning>

## Prerequisites

| Requirement            | Example / Notes                                                         |
| ---------------------- | ----------------------------------------------------------------------- |
| Wallet to receive USDC | Any EVM-compatible wallet (Metamask, Rabby, Safe, etc.)                 |
| Node.js                | [Node.js 18+](https://nodejs.org/en) with npm or [Bun](https://bun.sh/) |
| Existing API / server  | Express, Next.js, or Hono                                               |
| Polygon network        | [Amoy testnet](/pos/reference/rpc-endpoints/) or mainnet                |

This guide starts with **Amoy testnet** configuration. See
[Running on Polygon mainnet](#running-on-polygon-mainnet) when you are ready for
production.

## Install dependencies

> Wherever `bun` is used, replace it with `npm` or your preferred package manager.

<Tabs>
  <Tab title="Express">
    ```bash theme={null}
    bun install @x402/express @x402/core @x402/evm express
    ```
  </Tab>

  <Tab title="Next.js">
    ```bash theme={null}
    bun install @x402/next @x402/core @x402/evm
    ```
  </Tab>

  <Tab title="Hono">
    ```bash theme={null}
    bun install @x402/hono @x402/core @x402/evm hono @hono/node-server
    ```
  </Tab>
</Tabs>

## Add payment middleware

Integrate payment middleware with:

* A **facilitator client** pointing at the Polygon Amoy facilitator
* An **`x402ResourceServer`** with the EVM scheme registered
* Route config using an **`accepts`** array with `scheme`, `price`, `network`, and `payTo`

<Tabs>
  <Tab title="Express">
    Full example in the [x402 repo](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers/express).

    ```ts theme={null}
    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 payTo = "0xYourEvmAddress";

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

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

    app.get("/weather", (_req, res) => {
      res.send({
        report: { weather: "sunny", temperature: 70 },
      });
    });

    app.listen(4021, () => {
      console.log("Server running at http://localhost:4021");
    });
    ```
  </Tab>

  <Tab title="Next.js">
    Full example in the [x402 repo](https://github.com/x402-foundation/x402/tree/main/examples/typescript/fullstack/next).

    Use `withX402` for API routes. It settles payment only after a successful
    response (status below 400).

    ```ts theme={null}
    // lib/x402-server.ts
    import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
    import { ExactEvmScheme } from "@x402/evm/exact/server";

    export const payTo = "0xYourEvmAddress";

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

    export const server = new x402ResourceServer(facilitatorClient).register(
      "eip155:80002",
      new ExactEvmScheme()
    );
    ```

    ```ts theme={null}
    // app/api/weather/route.ts
    import { NextRequest, NextResponse } from "next/server";
    import { withX402 } from "@x402/next";
    import { payTo, server } from "../../../lib/x402-server";

    const handler = async (_: NextRequest) => {
      return NextResponse.json(
        {
          report: { weather: "sunny", temperature: 72 },
        },
        { status: 200 }
      );
    };

    export const GET = withX402(
      handler,
      {
        accepts: [
          {
            scheme: "exact",
            price: "$0.001",
            network: "eip155:80002",
            payTo,
          },
        ],
        description: "Access to weather API",
        mimeType: "application/json",
      },
      server
    );
    ```
  </Tab>

  <Tab title="Hono">
    Full example in the [x402 repo](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers/hono).

    ```ts theme={null}
    import { Hono } from "hono";
    import { serve } from "@hono/node-server";
    import { paymentMiddleware, x402ResourceServer } from "@x402/hono";
    import { ExactEvmScheme } from "@x402/evm/exact/server";
    import { HTTPFacilitatorClient } from "@x402/core/server";

    const app = new Hono();
    const payTo = "0xYourEvmAddress";

    const facilitatorClient = new HTTPFacilitatorClient({
      url: process.env.FACILITATOR_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()
        )
      )
    );

    app.get("/weather", (c) => {
      return c.json({
        report: { weather: "sunny", temperature: 70 },
      });
    });

    serve({ fetch: app.fetch, port: 4021 });
    ```
  </Tab>
</Tabs>

Buyers calling protected routes receive a 402 challenge, pay via the facilitator,
and then receive the response.

## Running on Polygon mainnet

Once you have tested on Amoy, switch to mainnet:

### 1. Update the facilitator URL

```ts theme={null}
const facilitatorClient = new HTTPFacilitatorClient({
  url: "https://x402.polygon.technology",
});
```

### 2. Update the network identifier

Change `eip155:80002` (Amoy) to `eip155:137` (Polygon mainnet) in every
`accepts` entry and scheme registration:

```ts theme={null}
// Testnet → Mainnet
network: "eip155:137",
// ...
server.register("eip155:137", new ExactEvmScheme());
```

Both Polygon facilitators run **x402 v2**. See
[Using the Polygon Facilitator](./using-polygon-facilitator.mdx) for signer
addresses and health endpoints.

## Reference

### Schema

| name              | type   | required | example                                  | description                                          |
| ----------------- | ------ | -------- | ---------------------------------------- | ---------------------------------------------------- |
| `payTo`           | string | yes      | `0xYourAddress`                          | Address that receives USDC                           |
| `network`         | string | yes      | `eip155:80002`                           | CAIP-2 network ID (Amoy or `eip155:137` for mainnet) |
| `scheme`          | string | yes      | `"exact"`                                | Payment scheme                                       |
| `price`           | string | yes      | `"$0.001"`                               | Cost per request in USDC                             |
| `FACILITATOR_URL` | string | optional | `"https://x402-amoy.polygon.technology"` | Polygon facilitator endpoint                         |
| `description`     | string | optional | `"Weather data"`                         | Used for discoverability in x402 Bazaar              |
| `mimeType`        | string | optional | `"application/json"`                     | Response content type                                |

### Errors

| case / code       | meaning                       | fix                                                         |
| ----------------- | ----------------------------- | ----------------------------------------------------------- |
| `402_LOOP`        | Client cannot fulfill payment | Check facilitator URL, network ID, and wallet               |
| `INVALID_NETWORK` | Wrong network identifier      | Use `eip155:80002` (Amoy) or `eip155:137` (mainnet)         |
| `BAD_CONFIG`      | Missing route config          | Define `accepts`, `price`, `network`, and `payTo` per route |

### Do / Don't Do Guardrails

| Do                                                          | Don't                                                       |
| ----------------------------------------------------------- | ----------------------------------------------------------- |
| Use `https://x402-amoy.polygon.technology` for Amoy testing | Use legacy `x402-express` against Polygon facilitators      |
| Use `https://x402.polygon.technology` for mainnet           | Expose private keys in middleware                           |
| Test on Amoy before mainnet                                 | Use V1 network strings like `"polygon-amoy"` or `"polygon"` |
| Include `description` and `mimeType` for AI discoverability | Skip `payTo` in route config                                |

### References

* [@x402/express on npm](https://www.npmjs.com/package/@x402/express)
* [@x402/next on npm](https://www.npmjs.com/package/@x402/next)
* [@x402/hono on npm](https://www.npmjs.com/package/@x402/hono)
* [Official x402 seller quickstart](https://docs.x402.org/getting-started/quickstart-for-sellers)
* [x402 TypeScript server examples](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers)
* [Using the Polygon Facilitator](./using-polygon-facilitator.mdx)
* [Migration: V1 to V2](./migration-v1-to-v2.mdx)
