Next.js + Privy + X402 Example¶
This example demonstrates how to integrate Privy server wallets with X402 payment protocol in a Next.js application for autonomous payment handling.
Overview¶
This is a production-ready example showing:
- Server-side wallet management using Privy (no private keys in code)
- Automatic X402 payment handling for paid API endpoints
- Two-server architecture (Next.js frontend + Express backend)
- No webpack bundling issues - proper separation of concerns
- Perfect for AI agents and backend services
Architecture¶
Due to Next.js webpack limitations with Privy's dependencies, this example uses a two-server pattern:
This is a production-standard pattern for integrating Node.js-specific SDKs with modern frontends.
Features¶
- ✅ Secure Wallet Management - Private keys managed by Privy's SOC 2 certified infrastructure
- ✅ Automatic Payments - Transparent 402 payment handling
- ✅ Safety Limits - Configurable maximum payment amounts
- ✅ Real-time Balance - Live wallet balance display
- ✅ Interactive UI - Test endpoints directly from the browser
- ✅ Production Ready - Proper error handling and logging
Quick Start¶
Prerequisites¶
- Node.js 18+
- pnpm (or npm/yarn)
- Privy account with server wallet
1. Install Dependencies¶
2. Get Privy Credentials¶
- Go to dashboard.privy.io
- Create or select an app
- Get your App ID and App Secret from Settings
- Create a Server Wallet and copy the Wallet ID
3. Configure Environment¶
Edit .env:
4. Run Both Servers¶
Terminal 1 - Express Backend:
Server starts on http://localhost:3002
Terminal 2 - Next.js Frontend:
Frontend starts on http://localhost:3000
5. Open the App¶
Visit http://localhost:3000
How It Works¶
Express Backend (server/src/index.ts)¶
The Express server handles all Privy SDK operations:
Next.js Frontend (app/api/*/route.ts)¶
Proxy routes forward requests to Express backend:
React Components (app/components/)¶
Interactive UI for testing:
Payment Flow¶
- User clicks "Test Endpoint" in UI
- Frontend calls Next.js proxy route
- Proxy forwards to Express backend
- Express uses Privy client to make X402 request
- Receives 402 Payment Required
- Automatically creates & signs payment via Privy API
- Broadcasts transaction to Solana
- Retries request with payment authorization
- Returns data back through proxy to frontend
- UI displays result
API Endpoints¶
Express Backend (Port 3002)¶
- GET /api/wallet - Get Privy server wallet info & balance
- GET /api/paid/data?url=
- Make paid GET request to X402 endpoint - GET /health - Health check
Next.js Frontend (Port 3000)¶
- GET /api/wallet - Proxies to Express backend
- GET /api/paid/data - Proxies paid requests to Express
File Structure¶
Why Two Servers?¶
The Problem:
Privy's @privy-io/server-auth uses dynamic require() statements incompatible with Next.js webpack bundling.
The Solution:
- Express - Full Node.js environment, no webpack, supports Privy SDK
- Next.js - Modern UI framework, proxy routes to Express
- Industry Standard - Common pattern for Node.js SDKs + modern frontends
Deployment¶
Option 1: Separate Deployments (Recommended)¶
Frontend (Vercel):
Backend (Railway/Fly.io/Heroku):
Set PRIVY_SERVER_URL in Vercel to your backend URL.
Option 2: Docker (Combined)¶
Option 3: Express Only¶
Skip Next.js, use Express as standalone API:
Access at http://localhost:3002/api/*
Testing¶
Test Wallet Info¶
- Ensure both servers are running
- Visit http://localhost:3000
- Click "Test Endpoint" on Wallet Information card
- See your Privy wallet address and SOL balance
Test Paid Requests¶
You need an X402-enabled API. Use the Express server example:
Then test paid endpoints from the Next.js UI.
Environment Variables¶
| Variable | Required | Default | Description |
|---|---|---|---|
PRIVY_APP_ID |
✅ | - | Privy App ID |
PRIVY_APP_SECRET |
✅ | - | Privy App Secret |
PRIVY_WALLET_ID |
✅ | - | Privy Server Wallet ID |
X402_NETWORK |
❌ | solana-devnet |
Solana network |
X402_MAX_PAYMENT |
❌ | 10.0 |
Max payment limit (USDC) |
X402_API_URL |
❌ | localhost:8000 |
Target X402 API |
SERVER_PORT |
❌ | 3002 |
Express port |
PRIVY_SERVER_URL |
❌ | localhost:3002 |
Express URL |
Security Features¶
- No Private Keys - All keys managed by Privy
- Payment Limits - Configurable max per transaction
- Environment Variables - Sensitive data in env only
- Audit Trail - All transactions in Privy dashboard
- SOC 2 Compliance - Privy's secure infrastructure
Troubleshooting¶
"Cannot connect to server"¶
→ Make sure Express is running on port 3002
→ Check PRIVY_SERVER_URL in .env
"Missing Privy credentials"¶
→ Set all 3 variables in .env
→ Get from dashboard.privy.io
"Insufficient funds"¶
→ Fund wallet with SOL and USDC
→ Devnet: solana airdrop 1 <address> --url devnet
Port already in use¶
→ Change SERVER_PORT in .env
→ Or kill: lsof -ti:3002 | xargs kill
Use Cases¶
Perfect for:
- 🤖 AI agents making autonomous payments
- 🔄 Backend services accessing paid APIs
- 📡 Webhook handlers requiring paid data
- ⏰ Scheduled jobs accessing premium endpoints
- 🏢 Microservices with payment requirements
Learn More¶
- Full Documentation: See
README.mdin example directory - Architecture Details: See
README-ARCHITECTURE.md - Quick Start Guide: See
QUICKSTART-UPDATED.md - X402 Protocol: openlib.xyz
- Privy Docs: docs.privy.io
- Privy Package: openlibx402-privy
Related Examples¶
- Privy Agent - Standalone Privy agent (no Next.js)
- Next.js App - Next.js with browser wallets
- Express Server - X402 server example
Source Code¶
View the complete source code in the repository: