PayWeavePayWeaveBack to Home
Apps

Next.js Integration

The @payweave/next package works with Next.js API routes and Route Handlers. Unlike Express and Hono where .charge() returns standalone middleware, the Next.js integration wraps your handler function, returning a new handler with payment verification built in.

Installation

Terminal
npm install @payweave/next

Route Handlers (App Router)

In the App Router, export the wrapped handler directly from your route file:

TypeScript
// app/api/lookup/route.ts
import { Payweave } from '@payweave/next';

const payweave = new Payweave(
  process.env.PAYWEAVE_APP_ID!,
  process.env.PAYWEAVE_APP_SECRET!
);

export const GET = payweave.charge(
  { price: '0.002', description: 'Lookup API' },
  async (req) => {
    const query = req.nextUrl.searchParams.get('q');
    return Response.json({ result: query });
  }
);
Notice the signature difference: payweave.charge(opts, handler) takes the charge options as the first argument and your handler as the second. This is because Next.js does not support Express-style middleware chaining.

Pages Router (API routes)

For the Pages Router, wrap your API handler the same way:

TypeScript
// pages/api/translate.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { Payweave } from '@payweave/next';

const payweave = new Payweave(
  process.env.PAYWEAVE_APP_ID!,
  process.env.PAYWEAVE_APP_SECRET!
);

export default payweave.charge(
  { price: '0.005', description: 'Translation API' },
  async (req: NextApiRequest, res: NextApiResponse) => {
    res.json({ translated: 'Bonjour le monde' });
  }
);

Dynamic pricing

The price field accepts a function that receives the request object, so you can price based on query params, body content, or headers:

TypeScript
export const POST = payweave.charge(
  {
    price: async (req) => {
      const body = await req.json();
      return body.model === 'gpt-4' ? '0.02' : '0.005';
    },
    description: 'AI completion',
  },
  async (req) => {
    return Response.json({ completion: '...' });
  }
);

Accessing payment data

The payment receipt is injected into the request headers. Read it with req.headers.get('x-payweave-receipt') in your handler:

TypeScript
export const GET = payweave.charge(
  { price: '0.001', description: 'Data API' },
  async (req) => {
    const receipt = req.headers.get('x-payweave-receipt');
    return Response.json({ data: '...', receipt });
  }
);
Keep your Payweave instance outside the handler function so it is reused across requests. This avoids reinitializing the client on every invocation.