Skip to main content

Getting Started with Next.js

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

Example Code

You can find the full code for this example on GitHub.

Step 1: Install Dependencies

Install the required packages for your Next.js application:

npm install x402 next react react-dom

Or with other package managers:

# pnpm
pnpm add x402 next react react-dom

# yarn
yarn add x402 next react react-dom

# bun
bun add x402 next react react-dom

Step 2: Set Your Environment Variables

Create a .env.local file in your project root:

echo "ADDRESS=0x...\nFACILITATOR_URL=https://x402.blockeden.xyz\nNETWORK=sui\nBLOCKEDEN_API_KEY=your_api_key_here" > .env.local

Your .env.local file should look like this:

ADDRESS=0x... # wallet public address you want to receive payments to
FACILITATOR_URL=https://x402.blockeden.xyz
NETWORK=sui # recommended for fastest settlement
BLOCKEDEN_API_KEY=your_api_key_here # get from https://blockeden.xyz/dash/
Network Options

BlockEden.xyz supports multiple networks:

  • sui (recommended for fastest settlement)
  • ethereum
  • base
  • polygon
  • avalanche

Step 3: Create Payment-Protected API Routes

Next.js uses a file-based routing system. Create API routes in the app/api directory (App Router) or pages/api directory (Pages Router).

Using App Router (Next.js 13+)

Create app/api/weather/route.ts:

import { NextRequest } from "next/server";
import { requirePayment } from "x402-nextjs";

const facilitatorUrl = process.env.FACILITATOR_URL!;
const payTo = process.env.ADDRESS! as `0x${string}`;
const network = process.env.NETWORK || "sui";
const apiKey = process.env.BLOCKEDEN_API_KEY!;

export const GET = requirePayment(
{
price: "$0.001",
network,
},
payTo,
{
url: facilitatorUrl,
apiKey,
},
async (request: NextRequest) => {
return Response.json({
report: {
weather: "sunny",
temperature: 70,
location: "San Francisco",
},
});
},
);

Create app/api/premium/content/route.ts:

import { NextRequest } from "next/server";
import { requirePayment } from "x402-nextjs";

const facilitatorUrl = process.env.FACILITATOR_URL!;
const payTo = process.env.ADDRESS! as `0x${string}`;
const network = process.env.NETWORK || "sui";
const apiKey = process.env.BLOCKEDEN_API_KEY!;

export const GET = requirePayment(
{
price: "$0.05",
network,
},
payTo,
{
url: facilitatorUrl,
apiKey,
},
async (request: NextRequest) => {
return Response.json({
content: "This is premium content",
type: "article",
timestamp: new Date().toISOString(),
});
},
);

Using Pages Router (Next.js 12 and below)

Create pages/api/weather.ts:

import type { NextApiRequest, NextApiResponse } from "next";
import { requirePayment } from "x402-nextjs/pages";

const facilitatorUrl = process.env.FACILITATOR_URL!;
const payTo = process.env.ADDRESS! as `0x${string}`;
const network = process.env.NETWORK || "sui";
const apiKey = process.env.BLOCKEDEN_API_KEY!;

async function handler(req: NextApiRequest, res: NextApiResponse) {
return res.status(200).json({
report: {
weather: "sunny",
temperature: 70,
location: "San Francisco",
},
});
}

export default requirePayment(
{
price: "$0.001",
network,
},
payTo,
{
url: facilitatorUrl,
apiKey,
},
handler,
);

Step 4: Run the Development Server

Start your Next.js development server:

npm run dev
Your Next.js application is now accepting x402 payments!

Your API routes will be available at:

  • http://localhost:3000/api/weather
  • http://localhost:3000/api/premium/content

Step 5: Test the Server

You can test payments against your API routes using HTTP clients like curl, Postman, or by building a client application.

Coming Soon

Client implementation guides for fetch API and axios will be available soon.

Manual Testing with curl

# This will return a 402 Payment Required response
curl http://localhost:3000/api/weather

# The response will include payment details in headers

Payment Configuration Options

The requirePayment wrapper accepts flexible payment configurations:

Simple Dollar Amount

export const GET = requirePayment(
{
price: "$0.001",
network: "sui",
},
payTo,
{
url: facilitatorUrl,
apiKey,
},
async (request: NextRequest) => {
return Response.json({ data: "Your data" });
},
);

Token Amount with Specific Asset

export const GET = requirePayment(
{
price: {
amount: "10000",
asset: {
address: "0x...", // Token contract address
decimals: 6,
name: "USDC",
},
},
network: "sui",
},
payTo,
{
url: facilitatorUrl,
apiKey,
},
async (request: NextRequest) => {
return Response.json({ data: "Premium data" });
},
);

Accessing Payment Information

export const GET = requirePayment(
{
price: "$0.001",
network: "sui",
},
payTo,
{
url: facilitatorUrl,
apiKey,
},
async (request: NextRequest) => {
// Payment information is attached to the request
const paymentData = (request as any).paymentData;

return Response.json({
data: "Your data",
payment: {
txHash: paymentData?.txHash,
network: paymentData?.network,
},
});
},
);

Advanced Features

Custom Payment Verification Callback

Add custom logic when payments are verified:

import { requirePayment } from "x402-nextjs";

export const GET = requirePayment(
{
price: "$0.001",
network: "sui",
},
payTo,
{
url: facilitatorUrl,
apiKey,
onPaymentVerified: (paymentData) => {
console.log("Payment verified:", paymentData.txHash);
// Custom logging, analytics, or business logic
},
},
async (request: NextRequest) => {
return Response.json({ data: "Your data" });
},
);

Error Handling

Create a custom error handler in app/api/error/route.ts:

import { NextRequest } from "next/server";

export async function GET(request: NextRequest) {
return Response.json(
{
error: "Internal server error",
timestamp: new Date().toISOString(),
},
{ status: 500 },
);
}

CORS Configuration

Enable CORS for your API routes using Next.js middleware.

Create middleware.ts in your project root:

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
const response = NextResponse.next();

// Set CORS headers
response.headers.set("Access-Control-Allow-Origin", "*");
response.headers.set(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS",
);
response.headers.set(
"Access-Control-Allow-Headers",
"Content-Type, Authorization",
);

// Handle preflight requests
if (request.method === "OPTIONS") {
return new NextResponse(null, { status: 200, headers: response.headers });
}

return response;
}

export const config = {
matcher: "/api/:path*",
};

Environment-Specific Configuration

Create different configurations for development and production:

// lib/x402-config.ts
export const x402Config = {
facilitator: {
url: process.env.FACILITATOR_URL || "https://x402.blockeden.xyz",
apiKey: process.env.BLOCKEDEN_API_KEY!,
},
network: process.env.NETWORK || "sui",
payTo: process.env.ADDRESS! as `0x${string}`,
};

// Validate configuration
if (!x402Config.facilitator.apiKey || !x402Config.payTo) {
throw new Error("Missing required x402 environment variables");
}

Then use it in your routes:

import { requirePayment } from "x402-nextjs";
import { x402Config } from "@/lib/x402-config";

export const GET = requirePayment(
{
price: "$0.001",
network: x402Config.network,
},
x402Config.payTo,
x402Config.facilitator,
async (request: NextRequest) => {
return Response.json({ data: "Your data" });
},
);

Production Deployment

Before deploying to production:

  1. Switch to production network (e.g., sui instead of sui-testnet)
  2. Use environment variables for all sensitive data
  3. Enable HTTPS (handled by most hosting platforms)
  4. Set up proper error logging
  5. Configure CORS for your production domains
  6. Add rate limiting to prevent abuse

Deployment on Vercel

Next.js works seamlessly with Vercel. Set your environment variables in the Vercel dashboard:

  1. Go to your project settings
  2. Navigate to "Environment Variables"
  3. Add your variables:
    • ADDRESS
    • FACILITATOR_URL
    • NETWORK
    • BLOCKEDEN_API_KEY

Deployment on Other Platforms

For other platforms (Netlify, AWS, etc.), ensure your environment variables are set and your build command is:

npm run build

Production Example

// app/api/data/route.ts
import { NextRequest } from "next/server";
import { requirePayment } from "x402-nextjs";

// Production configuration
const config = {
facilitator: {
url: "https://x402.blockeden.xyz",
apiKey: process.env.BLOCKEDEN_API_KEY!,
onPaymentVerified: (paymentData) => {
// Log to your analytics service
console.log("Payment verified:", paymentData.txHash);
},
},
network: "sui", // Production Sui network
payTo: process.env.ADDRESS! as `0x${string}`,
};

export const GET = requirePayment(
{
price: "$0.01",
network: config.network,
},
config.payTo,
config.facilitator,
async (request: NextRequest) => {
try {
// Your business logic here
const data = { content: "Protected data" };

return Response.json({
data,
payment: {
verified: true,
},
});
} catch (error) {
console.error("Error processing request:", error);
return Response.json({ error: "Internal server error" }, { status: 500 });
}
},
);

Troubleshooting

Common Issues

Payment verification fails

  • Verify your BLOCKEDEN_API_KEY is correct in .env.local
  • Check that the wallet address format matches the network
  • Ensure the facilitator URL is accessible
  • Restart the Next.js dev server after changing environment variables

CORS errors

  • Add the middleware configuration as shown above
  • Check that the client origin is allowed
  • Verify CORS headers are being set correctly

Network mismatch

  • Ensure client and server use the same network
  • Check that the token address is valid for the network

Environment variables not loading

  • Use .env.local for local development
  • Restart the dev server after changes
  • Use NEXT_PUBLIC_ prefix only for client-side variables
  • Never expose sensitive keys (API keys) to the client

TypeScript errors

  • Ensure you have @types/node and @types/react installed
  • Check that your tsconfig.json is properly configured
  • Use type assertions for environment variables: process.env.VAR!

Why Choose Next.js?

Next.js is an excellent choice for x402 payment applications:

  • Full-stack framework: API routes + React frontend in one project
  • Server-side rendering: Optimal performance and SEO
  • File-based routing: Intuitive API route organization
  • Edge functions: Deploy globally with low latency
  • Vercel integration: Zero-config deployments
  • TypeScript support: First-class TypeScript experience

App Router vs Pages Router

Pros:

  • Modern React features (Server Components, Suspense)
  • Better performance and smaller bundle sizes
  • Improved routing and layouts
  • Built-in loading and error states

Use when:

  • Starting a new project
  • Want the latest Next.js features
  • Need advanced routing capabilities

Pages Router (Legacy)

Pros:

  • More mature and stable
  • Extensive community resources
  • Simpler mental model

Use when:

  • Maintaining an existing project
  • Need maximum stability
  • Team is familiar with older Next.js versions

Next Steps

Need Help?

Join Our Community

Have questions or want to connect with other developers?

Join Discord