> ## Documentation Index
> Fetch the complete documentation index at: https://www.narev.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started

> First steps with OpenMeter destination for tracking AI costs.

## Installation

```bash npm theme={null}
npm install @ai-billing/openmeter @ai-billing/core
```

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

```bash yarn theme={null}
yarn add @ai-billing/openmeter @ai-billing/core
```

## Overview

The `@ai-billing/openmeter` package provides a destination for sending calculated AI costs and token usage to [OpenMeter](https://openmeter.io).

Unlike other destinations, OpenMeter ingests usage as **CloudEvents**. The destination automatically formats the AI SDK usage into CloudEvents, using the event `type` to identify the meter and the `subject` to identify the customer. Cost data is sent in nano-dollars (or your base currency) in the data payload, which is merged with other billing metadata.

## Usage

To use the OpenMeter destination, initialize it with your API key, then pass it to any billing middleware.

**1. Initialize the OpenMeter destination**

Set up the destination using your OpenMeter API key. You can optionally customize the `eventType` (defaults to `llm_usage`), `apiUrl`, and define a type for your billing tags for type safety.

```typescript theme={null}
import { createOpenMeterDestination } from '@ai-billing/openmeter';

type BillingTags = {
  userId?: string;
  org_name?: string;
};

const openMeterDestination = createOpenMeterDestination<BillingTags>({
  apiKey: process.env.OPENMETER_API_KEY,
  // Optional configurations:
  // eventType: 'llm_usage', // default
  // apiUrl: 'https://eu.api.konghq.com', // default
  // customerIdKey: 'userId', // custom key for identifying the user
});
```

**2. Set up price resolution**

In order for the OpenMeter destination to send costs, the `cost` property on the generated events must be populated.

If you are using a provider that returns pricing natively (like OpenRouter or Anthropic), the cost is automatically calculated and you can skip this step.

However, if you are using a provider that **doesn't** return pricing natively (such as Groq or local models), you must supply a price resolver like Narev or a local object resolver. Without this, the cost will be undefined and the destination cannot send the meter event to OpenMeter.

```typescript theme={null}
import { createNarevPriceResolver } from '@ai-billing/core';

const priceResolver = createNarevPriceResolver({
  apiKey: process.env.NAREV_API_KEY,
});
```

**3. Create the billing middleware**

Initialize the billing middleware for your preferred provider and include the `openMeterDestination` in the destinations array.

```typescript OpenRouter theme={null}
// Example using OpenRouter (pricing returned natively)
import { createOpenRouterV3Middleware } from '@ai-billing/openrouter';

const billingMiddleware = createOpenRouterV3Middleware<BillingTags>({
  destinations: [openMeterDestination],
});
```

```typescript Groq + Narev theme={null}
// Example using Groq with Narev for price resolution
import { createGroqMiddleware } from '@ai-billing/groq';

const billingMiddleware = createGroqMiddleware<BillingTags>({
  destinations: [openMeterDestination],
  priceResolver, // Pass the Narev price resolver here
});
```

**4. Wrap the model**

Use `wrapLanguageModel` from the `ai` package to apply the billing middleware to your model.

```typescript theme={null}
import { wrapLanguageModel } from 'ai';
import { createOpenRouter } from '@openrouter/ai-sdk-provider';

const openrouter = createOpenRouter({
  apiKey: process.env.OPENROUTER_API_KEY,
});

const wrappedModel = wrapLanguageModel({
  model: openrouter('openai/gpt-4o'),
  middleware: billingMiddleware,
});
```

**5. Pass tags during generation**

Finally, use the wrapped model with AI SDK functions like `generateText` or `streamText`.

### Understanding Billing Tags

The `ai-billing-tags` object has specific requirements for OpenMeter:

* **Customer Identity (Subject)**: By default, the destination looks for `userId` or `openMeterCustomerId` in your tags to populate the CloudEvents `subject`. If omitted, the event is skipped to avoid ingesting anonymous data. You can override this by providing `customerIdKey` in the destination options.
* **Data Payload**: Metadata (like `model_id`, `input_tokens`, and your custom tags such as `org_name`) are merged along with `cost_nanos` and `currency` into the `data` field of the CloudEvent.

```typescript theme={null}
import { streamText } from 'ai';

const result = streamText({
  model: wrappedModel,
  prompt: 'What is the capital of Sweden?',
  providerOptions: {
    'ai-billing-tags': {
      userId: 'user_openmeter_test', // Used as the CloudEvents subject
      org_name: 'Acme Corp', // Sent as additional metadata in data payload
    } as BillingTags,
  },
});
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.