Getting Started with Next.js
Start accepting x402 payments in your Next.js application in 2 minutes.
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/
BlockEden.xyz supports multiple networks:
sui(recommended for fastest settlement)ethereumbasepolygonavalanche
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 API routes will be available at:
http://localhost:3000/api/weatherhttp://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.
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:
- Switch to production network (e.g.,
suiinstead ofsui-testnet) - Use environment variables for all sensitive data
- Enable HTTPS (handled by most hosting platforms)
- Set up proper error logging
- Configure CORS for your production domains
- Add rate limiting to prevent abuse
Deployment on Vercel
Next.js works seamlessly with Vercel. Set your environment variables in the Vercel dashboard:
- Go to your project settings
- Navigate to "Environment Variables"
- Add your variables:
ADDRESSFACILITATOR_URLNETWORKBLOCKEDEN_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_KEYis 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.localfor 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/nodeand@types/reactinstalled - Check that your
tsconfig.jsonis 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
App Router (Recommended - Next.js 13+)
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?