Skip to main content

Documentation Index

Fetch the complete documentation index at: https://narev.ai/docs/llms.txt

Use this file to discover all available pages before exploring further.

Next.js billing integration

Use this guide to integrate Narev Cloud billing in a Next.js App Router project without coupling your app to a single billing provider. You’ll:
  1. Wrap all model calls with @ai-billing middleware.
  2. Attach consistent billing tags for attribution.
  3. Keep your provider logic modular so you can use Polar, Stripe, or another destination.

Before you start

  • You already use Next.js App Router and Vercel AI SDK.
  • You already send AI calls through a shared model helper.
  • You have a billing destination selected.
If you want the Polar-specific setup (destination config and customer sync), use Polar billing platform integration.

Install dependencies

Install the framework-level package:
pnpm add @ai-billing/gateway
Install your billing-platform package separately. For example:
  • Polar: @ai-billing/polar
  • Stripe: @ai-billing/stripe

Add framework-level environment variables

Set variables that your framework integration needs in .env.local:
# Required outside Vercel deployments
AI_GATEWAY_API_KEY=****
Add destination-specific variables in the billing platform guide for your provider.

Build a platform-agnostic billing wrapper

Create lib/ai/billing.ts and inject destinations from a separate module:
lib/ai/billing.ts
import { wrapLanguageModel } from 'ai';
import type { LanguageModelV3 } from '@ai-sdk/provider';
import { createGatewayV3Middleware } from '@ai-billing/gateway';
import { getBillingDestinations } from './destinations';

let _billingMiddleware: ReturnType<typeof createGatewayV3Middleware> | null =
  null;
let _initAttempted = false;

function getBillingMiddleware() {
  if (_initAttempted) return _billingMiddleware;
  _initAttempted = true;

  const destinations = getBillingDestinations();
  if (destinations.length === 0) return null;

  _billingMiddleware = createGatewayV3Middleware({ destinations });
  return _billingMiddleware;
}

export function getBillingWrappedModel(model: LanguageModelV3): LanguageModelV3 {
  const middleware = getBillingMiddleware();
  if (!middleware) return model; // Keep local/dev environments resilient.
  return wrapLanguageModel({ model, middleware });
}
This keeps Next.js integration stable while destination details live in platform-specific docs.

Route all model access through one provider helper

Create a single model entrypoint in lib/ai/providers.ts:
lib/ai/providers.ts
import { gateway } from 'ai';
import { getBillingWrappedModel } from './billing';

export function getLanguageModel(modelId: string) {
  return getBillingWrappedModel(gateway.languageModel(modelId));
}
Use getLanguageModel(...) everywhere. If a route bypasses this helper, that usage is not billed.

Attach billing tags on every generation call

In routes such as app/api/chat/route.ts, include providerOptions['ai-billing-tags']:
import { streamText } from 'ai';
import { getLanguageModel } from '@/lib/ai/providers';

const result = streamText({
  model: getLanguageModel(chatModel),
  messages: modelMessages,
  providerOptions: {
    'ai-billing-tags': {
      userId: session.user.id,
      modelId: chatModel,
      chatId: id,
      userType,
    },
  },
});
Minimum tag:
  • userId
Recommended tags:
  • modelId
  • chatId or requestId
  • userType, workspaceId, or feature

Organize your integration

Use this structure:
  • lib/ai/billing.ts: framework middleware wrapper.
  • lib/ai/destinations.ts: provider-specific destinations.
  • lib/ai/providers.ts: shared model resolver.
  • app/api/**/route.ts: generation routes with billing tags.

Verify billing coverage

  1. Trigger chat generation and confirm Polar or your billing platform receives usage events.
  2. Trigger non-chat AI features and confirm your billing platform receives those usage events.
  3. Confirm every AI path uses getLanguageModel(...).
  4. Confirm userId is always present in ai-billing-tags.

Troubleshooting

No usage events appear

  • Confirm your destination config loads during server startup.
  • Confirm each route uses getLanguageModel(...).
  • Confirm required provider credentials are available at runtime.

Some routes bill and others don’t

  • Audit streamText, generateText, and generateObject usage.
  • Move direct provider calls behind your shared helper.

What to do next

Choose your billing destination guide: