Documentation Index Fetch the complete documentation index at: https://developers.fd.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The @1stdigital/prism-nextjs package provides middleware for Next.js API routes and App Router route handlers. Supports both Pages Router and App Router architectures.
App Router Support for Next.js 13+ App Router
Pages Router Works with traditional API routes
Edge Runtime Compatible with Edge Runtime
Installation
npm install @1stdigital/prism-nextjs next
bash yarn add @1stdigital/prism-nextjs next
pnpm add @1stdigital/prism-nextjs next
The canonical SDK config is identifyToken (PRISM_IDENTIFY_TOKEN env var) — formerly apiKey / PRISM_API_KEY. SDKs accept the legacy names as fallback during the migration window; new code should use the canonical names.
Quick Start (App Router)
// app/api/premium/route.ts
import { NextRequest , NextResponse } from "next/server" ;
import { withPrismPayment } from "@1stdigital/prism-nextjs" ;
async function handler ( request : NextRequest ) {
// Access payer from request
const payer = ( request as any ). payer ;
return NextResponse . json ({
message : "Premium content" ,
payer ,
});
}
// Wrap handler with payment middleware
export const GET = withPrismPayment ( handler , {
identifyToken : process . env . PRISM_IDENTIFY_TOKEN || "dev-key-123" ,
baseUrl : "https://prism-gw.fd.xyz" ,
price : 0.01 , // $0.01 USD
description : "Premium API" ,
});
Quick Start (Pages Router)
// pages/api/premium.ts
import { NextApiRequest , NextApiResponse } from "next" ;
import { createPrismMiddleware } from "@1stdigital/prism-nextjs" ;
const prismMiddleware = createPrismMiddleware ({
identifyToken : process . env . PRISM_IDENTIFY_TOKEN || "dev-key-123" ,
baseUrl : "https://prism-gw.fd.xyz" ,
});
export default async function handler (
req : NextApiRequest ,
res : NextApiResponse ,
) {
// Apply middleware
const paymentResult = await prismMiddleware ( req , res , {
price : 0.01 , // $0.01 USD
description : "Premium API" ,
});
if ( ! paymentResult ) return ; // Middleware handled response
// Payment verified
res . status ( 200 ). json ({
message : "Premium content" ,
payer : ( req as any ). payer ,
});
}
Configuration
App Router Options
interface PrismRouteConfig {
identifyToken : string ;
baseUrl ? : string ;
debug ? : boolean ;
price : number | string ; // USD price
description : string ;
mimeType ? : string ;
}
Pages Router Options
interface PrismMiddlewareConfig {
identifyToken : string ;
baseUrl ? : string ;
debug ? : boolean ;
}
interface RoutePaymentConfig {
price : number | string ;
description : string ;
mimeType ? : string ;
}
App Router Routes
Single Route
// app/api/premium/route.ts
import { withPrismPayment } from "@1stdigital/prism-nextjs" ;
async function handler ( request : NextRequest ) {
return NextResponse . json ({ data : "Premium" });
}
export const GET = withPrismPayment ( handler , {
identifyToken : process . env . PRISM_IDENTIFY_TOKEN ! ,
price : 0.01 ,
description : "Premium API" ,
});
Multiple Methods
// app/api/data/route.ts
import { withPrismPayment } from "@1stdigital/prism-nextjs" ;
async function getHandler ( request : NextRequest ) {
return NextResponse . json ({ data : "GET data" });
}
async function postHandler ( request : NextRequest ) {
const body = await request . json ();
return NextResponse . json ({ received : body });
}
export const GET = withPrismPayment ( getHandler , {
identifyToken : process . env . PRISM_IDENTIFY_TOKEN ! ,
price : 0.01 ,
description : "Get data" ,
});
export const POST = withPrismPayment ( postHandler , {
identifyToken : process . env . PRISM_IDENTIFY_TOKEN ! ,
price : 0.02 ,
description : "Post data" ,
});
Accessing Payment Info
App Router
async function handler ( request : NextRequest ) {
// Payer address attached to request
const payer = ( request as any ). payer ;
// '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
// Payment object in custom property
const payment = ( request as any ). prismPayment ;
return NextResponse . json ({
message : "Data" ,
payer ,
network : payment ?. network ,
});
}
Pages Router
export default async function handler (
req : NextApiRequest ,
res : NextApiResponse ,
) {
const paymentResult = await prismMiddleware ( req , res , {
price : 0.01 ,
description : "Premium" ,
});
if ( ! paymentResult ) return ;
// Access payer
const payer = ( req as any ). payer ;
const payment = ( res as any ). locals ?. payment ;
res . json ({ payer , network : payment ?. network });
}
Settlement Validation
Coming soon: transaction hash in the X-PAYMENT-RESPONSE response header. The Next.js SDK currently confirms settlement internally before returning the response, but does not yet surface the transaction hash to the client. If your application needs the on-chain transaction hash on the client side, use the Express SDK — it returns this header today.
Next.js wraps the Response object to validate settlement:
// Internal implementation (automatic!)
async function withPrismPayment ( handler , config ) {
return async ( request : NextRequest ) => {
// ... payment validation ...
// Execute handler
const response = await handler ( request );
// Validate settlement before returning
const settlementResult = await core . settlementCallback ( ... );
if ( ! settlementResult || ! settlementResult . success ) {
// ❌ Settlement failed
return NextResponse . json (
{ error : 'Payment settlement failed' },
{ status : 402 }
);
}
// ✅ Settlement succeeded
response . headers . set ( 'X-PAYMENT-RESPONSE' , settlementResult . transaction );
return response ;
};
}
Testing
import { NextRequest } from "next/server" ;
import { GET } from "./app/api/premium/route" ;
describe ( "Next.js Payment Routes" , () => {
it ( "returns 402 without payment" , async () => {
const request = new NextRequest ( "http://localhost:3000/api/premium" );
const response = await GET ( request );
expect ( response . status ). toBe ( 402 );
const body = await response . json ();
expect ( body . paymentRequired ). toBe ( true );
});
it ( "returns 200 with valid payment" , async () => {
const payment = JSON . stringify ({
scheme : "eip3009" ,
signature : "0x" + "0" . repeat ( 130 ),
});
const request = new NextRequest ( "http://localhost:3000/api/premium" , {
headers : { "X-PAYMENT" : payment },
});
const response = await GET ( request );
expect ( response . status ). toBe ( 200 );
const body = await response . json ();
expect ( body . message ). toBe ( "Premium content" );
});
});
Production Deployment
// next.config.js
module . exports = {
env : {
PRISM_IDENTIFY_TOKEN : process . env . PRISM_IDENTIFY_TOKEN ,
PRISM_BASE_URL : process . env . PRISM_BASE_URL
},
// Enable edge runtime (optional)
experimental : {
runtime : 'edge'
}
};
// Vercel deployment
// vercel.json
{
"env" : {
"PRISM_IDENTIFY_TOKEN" : "@prism-identify-token" ,
"PRISM_BASE_URL" : "@prism-base-url"
}
}