> ## Documentation Index
> Fetch the complete documentation index at: https://docs.payai.network/llms.txt
> Use this file to discover all available pages before exploring further.

> Protect Next.js pages and API routes with x402 payments using the PayAI facilitator.

# Nextjs

## Getting started with Next.js

Start accepting x402 payments in your Next.js app in 2 minutes.

<Note>You can find the full code for this example [here](https://github.com/x402-foundation/x402/tree/main/examples/typescript/fullstack/next).</Note>

### Step 1: Create an app and install dependencies

Scaffold a Next.js app, then add the x402 packages:

```bash theme={null}
npx create-next-app@latest my-app --typescript --app
cd my-app
npm install @payai/facilitator @x402/core @x402/evm @x402/extensions @x402/next @x402/paywall @x402/svm
```

This is the same dependency set as the [upstream Next.js example](https://github.com/x402-foundation/x402/tree/main/examples/typescript/fullstack/next).

### Step 2: Set your environment variables

Create a `.env.local` file in the project root and fill in your values.

```env theme={null}
EVM_ADDRESS=0x...   # EVM wallet address to receive payments
SVM_ADDRESS=...    # Solana wallet address to receive payments
```

Optionally set `APP_NAME` and `APP_LOGO` to brand the paywall shown to buyers:

```env theme={null}
APP_NAME=Next x402 Demo
APP_LOGO=/x402-icon-blue.png
```

<Tip>`@payai/facilitator` automatically connects to the PayAI facilitator — no URL configuration needed.</Tip>

### Step 3: Explore the app structure

The example uses a **proxy** for page routes and **withX402** for API routes:

```text theme={null}
├── app/
│   ├── api/           # API routes (use withX402 for payment)
│   ├── protected/     # Protected page route
│   ├── layout.tsx
│   └── page.tsx
├── proxy.ts           # x402 payment proxy (page routes)
├── next.config.ts
└── package.json
```

* **paymentProxy** (in `proxy.ts`) protects page routes and returns a paywall when payment is required.
* **withX402** wraps individual API route handlers so payment is settled only after a successful response.

Both routes also call `declareDiscoveryExtension`, which lists them in the
[PayAI bazaar](/x402/facilitators/bazaar) so buyers and agents can discover them.

### Step 4: Preview the example routes

#### Protected Page Route

The `/protected` page is protected using `paymentProxy`.

The proxy in `proxy.ts` configures the resource server, paywall, and protected routes:

```typescript theme={null}
// proxy.ts
import { paymentProxy } from "@x402/next";
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { ExactSvmScheme } from "@x402/svm/exact/server";
import { createPaywall } from "@x402/paywall";
import { evmPaywall } from "@x402/paywall/evm";
import { svmPaywall } from "@x402/paywall/svm";
import { declareDiscoveryExtension } from "@x402/extensions/bazaar";
import { facilitator } from "@payai/facilitator";

export const evmAddress = process.env.EVM_ADDRESS as `0x${string}`;
export const svmAddress = process.env.SVM_ADDRESS;

if (!evmAddress || !svmAddress) {
  console.error("❌ EVM_ADDRESS and SVM_ADDRESS environment variables are required");
  process.exit(1);
}

// Connect to the PayAI facilitator (no URL configuration needed)
const facilitatorClient = new HTTPFacilitatorClient(facilitator);

// Create x402 resource server
export const server = new x402ResourceServer(facilitatorClient);

// Register schemes
server.register("eip155:*", new ExactEvmScheme());
server.register("solana:*", new ExactSvmScheme());

// Build paywall
export const paywall = createPaywall()
  .withNetwork(evmPaywall)
  .withNetwork(svmPaywall)
  .withConfig({
    appName: process.env.APP_NAME || "Next x402 Demo",
    appLogo: process.env.APP_LOGO || "/x402-icon-blue.png",
    testnet: true,
  })
  .build();

// Build proxy
export const proxy = paymentProxy(
  {
    "/protected": {
      accepts: [
        {
          scheme: "exact",
          price: "$0.001",
          network: "eip155:84532", // base-sepolia
          payTo: evmAddress,
        },
        {
          scheme: "exact",
          price: "$0.001",
          network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", // solana devnet
          payTo: svmAddress,
        },
      ],
      description: "Premium music: x402 Remix",
      mimeType: "text/html",
      extensions: {
        ...declareDiscoveryExtension({}),
      },
    },
  },
  server,
  undefined, // paywallConfig (using custom paywall instead)
  paywall, // custom paywall provider
);

// Configure which paths the proxy should run on
export const config = {
  matcher: ["/protected/:path*"],
};
```

#### Weather API Route (using withX402)

The `/api/weather` route demonstrates the `withX402` wrapper for individual API routes:

```typescript theme={null}
// app/api/weather/route.ts
import { NextRequest, NextResponse } from "next/server";
import { withX402 } from "@x402/next";
import { declareDiscoveryExtension } from "@x402/extensions/bazaar";
import { server, paywall, evmAddress, svmAddress } from "../../../proxy";

/**
 * Weather API endpoint handler
 *
 * This handler returns weather data after payment verification.
 * Payment is only settled after a successful response (status < 400).
 *
 * @param _ - Incoming Next.js request
 * @returns JSON response with weather data
 */
const handler = async (_: NextRequest) => {
  return NextResponse.json(
    {
      report: {
        weather: "sunny",
        temperature: 72,
      },
    },
    { status: 200 },
  );
};

/**
 * Protected weather API endpoint using withX402 wrapper
 *
 * This demonstrates the v2 withX402 wrapper for individual API routes.
 * Unlike middleware, withX402 guarantees payment settlement only after
 * the handler returns a successful response (status < 400).
 */
export const GET = withX402(
  handler,
  {
    accepts: [
      {
        scheme: "exact",
        price: "$0.001",
        network: "eip155:84532", // base-sepolia
        payTo: evmAddress,
      },
      {
        scheme: "exact",
        price: "$0.001",
        network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", // solana devnet
        payTo: svmAddress,
      },
    ],
    description: "Access to weather API",
    mimeType: "application/json",
    extensions: {
      ...declareDiscoveryExtension({
        output: {
          example: {
            report: {
              weather: "sunny",
              temperature: 72,
            },
          },
        },
      }),
    },
  },
  server,
  undefined, // paywallConfig (using custom paywall from proxy.ts)
  paywall,
);
```

#### paymentProxy vs withX402

The `paymentProxy` function is used to protect page routes. It can also protect API routes, however this will charge clients for failed API responses.

The `withX402` function wraps API route handlers. This is the recommended approach to protect API routes as it guarantees payment settlement only AFTER successful API responses (status \< 400).

| Approach | Use Case |
| - | - |
| `paymentProxy` | Protecting page routes or multiple routes with a single configuration |
| `withX402` | Protecting individual API routes where you need precise control over settlement timing |

### Step 5: Run the server

```bash theme={null}
npm run dev
```

<Check>
  Your Next.js app is now accepting x402 payments!
</Check>

### Step 6: Test the server

The example includes a built-in paywall at the home page. Navigate to [http://localhost:3000](http://localhost:3000) to test payments directly.

You can also test programmatically by following the [fetch example](/x402/clients/typescript/fetch) or [axios example](/x402/clients/typescript/axios).

## Going to production

The examples above use testnets. For Mainnet, update the route's network and any explicit scheme registrations together, use the matching asset and funded buyer, and verify the paid path. The [Solana Mainnet example](/x402/solana-mainnet-express) provides a complete tested configuration; adding credentials alone does not switch networks.

This setup can serve ordinary exact mainnet payments in production within the [free allowance](/x402/facilitators/pricing) — no API key or portal signup is required. Production readiness still includes normal controls such as secret management, monitoring, and failure handling.

When you need paid capacity beyond the allowance, an autonomous agent can [buy credits and receive an API key over x402](/x402/facilitators/agent-api-keys); PayAI creates a wallet-owned agent account programmatically. You can also use the optional [merchant dashboard](https://merchant.payai.network). Add the resulting credentials to your `.env`:

```env theme={null}
PAYAI_API_KEY_ID=your-key-id
PAYAI_API_KEY_SECRET=your-key-secret
```

The `@payai/facilitator` package automatically detects these environment variables and authenticates your requests to the facilitator. See [Facilitator Pricing](/x402/facilitators/pricing) for tier details and [Facilitator Authentication](/x402/facilitators/authentication) for the full protocol reference.

## x402 reference

For a deeper dive into message shapes, headers, verification and settlement responses, see the [x402 Reference](/x402/reference).

## Need help?

<Card title="Join our Community" icon="discord" href="https://discord.gg/eWJRwMpebQ">
  Have questions or want to connect with other developers? Join our Discord server.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.