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

# 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

This setup works on the **free tier** out of the box — no API keys required.

When you're ready for production, create a merchant account at [merchant.payai.network](https://merchant.payai.network), get your API keys, and add them 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>
