> ## 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.

# Node.js

> Add Narev Cloud usage metering and AI billing to any Node.js server running the Vercel AI SDK, with a billing-platform-agnostic pattern for Stripe, Polar, Lago, and OpenMeter.

# Node.js billing integration

Use this guide to integrate Narev Cloud billing on any Node.js server without coupling your app to a single billing provider.

The pattern works wherever you run the Vercel AI SDK on the server (Next.js route handlers, Hono, Express, Fastify, or a plain Node script behind your API).

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 call `generateText`, `streamText`, or `generateObject` from the Vercel AI SDK on the server.
* You already send AI calls through a shared model helper.
* You have a billing destination selected.

If you want provider-specific setup (destination config, metering strategy, and customer sync), use:

* [Polar billing platform integration](/docs/platform/billing/integrations/billing-platforms/polar)
* [Stripe billing platform integration](/docs/platform/billing/integrations/billing-platforms/stripe)
* [Lago billing platform integration](/docs/platform/billing/integrations/billing-platforms/lago)
* [OpenMeter billing platform integration](/docs/platform/billing/integrations/billing-platforms/openmeter)

<Tip>
  Building with Next.js and want billing UI components (`CreditUsagePolar`, credit top-up flows)? Add [`@ai-billing/nextjs`](/docs/sdk/ai-billing/reference/nextjs/typedoc/index). The middleware pattern on this page still applies.
</Tip>

## Install dependencies

Install middleware for your AI provider. This example uses the Vercel AI Gateway:

```bash theme={null}
pnpm add @ai-billing/gateway ai
```

You can swap `@ai-billing/gateway` for a provider package such as `@ai-billing/openai`, `@ai-billing/anthropic`, or `@ai-billing/openrouter`. See the [@ai-billing SDK overview](/docs/sdk/ai-billing/index).

Install your billing-platform package separately. For example:

* Polar: `@ai-billing/polar`
* Stripe: `@ai-billing/stripe`
* Lago: `@ai-billing/lago`
* OpenMeter: `@ai-billing/openmeter`

## Configure environment variables

Set provider and destination credentials in your server environment (`.env`, deployment secrets, or your host's env config):

```bash theme={null}
# Required when using @ai-billing/gateway 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:

```ts lib/ai/billing.ts theme={null}
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 your server 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`:

```ts lib/ai/providers.ts theme={null}
import { gateway } from 'ai';
import { getBillingWrappedModel } from './billing';

export function getLanguageModel(modelId: string) {
  return getBillingWrappedModel(gateway.languageModel(modelId));
}
```

Use `getLanguageModel(...)` everywhere. If a handler bypasses this helper, that usage is not billed.

## Attach billing tags on every generation call

In any server handler that calls the model, include `providerOptions['ai-billing-tags']`:

```ts theme={null}
import { streamText } from 'ai';
import { getLanguageModel } from './ai/providers';

const result = streamText({
  model: getLanguageModel(chatModel),
  messages: modelMessages,
  providerOptions: {
    'ai-billing-tags': {
      userId: session.user.id,
      modelId: chatModel,
      chatId: id,
      userType,
    },
  },
});
```

The handler can be a Next.js route, a Hono `app.post`, an Express router, or any other HTTP entrypoint. The billing contract is the same.

Minimum tag:

* `userId`

Recommended tags:

* `modelId`
* `chatId` or `requestId`
* `userType`, `workspaceId`, or `feature`

## Organize your integration

Use this structure:

* `lib/ai/billing.ts`: middleware wrapper and `wrapLanguageModel` helper.
* `lib/ai/destinations.ts`: billing-platform destinations.
* `lib/ai/providers.ts`: shared model resolver.
* Your HTTP handlers: generation routes with billing tags.

## Verify billing coverage

1. Trigger a generation request and confirm 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 handler uses `getLanguageModel(...)`.
* Confirm required provider credentials are available at runtime.

### Some routes bill and others don't

* Audit `streamText`, `generateText`, and `generateObject` usage across your codebase.
* Move direct provider calls behind your shared helper.

## What to do next

Choose your billing destination guide:

* [Polar billing platform integration](/docs/platform/billing/integrations/billing-platforms/polar)
* [Stripe billing platform integration](/docs/platform/billing/integrations/billing-platforms/stripe)
* [Lago billing platform integration](/docs/platform/billing/integrations/billing-platforms/lago)
* [OpenMeter billing platform integration](/docs/platform/billing/integrations/billing-platforms/openmeter)
