Problem worth solving
If you are building an AI-powered product, you’ve likely run into the "billing wall." Unlike traditional SaaS, AI products are often billed per inference, token, or request. Building a robust metering and billing system that handles real-time usage data, balances, and provider integrations is a major distraction from your core product.
pnpm add @ai-billing/openai
@ai-billing is an npm package designed to handle the heavy lifting of usage-based billing in Vercel AI SDK. It does two things:
1. Adds cost in dollars to your provider
2. (optionally) Sends usage events to billing providers
How it works?
The package acts as a middleware for your usage telemetry. Instead of writing custom logic for every provider, you use a unified interface to track consumption and sync it with your chosen billing platform.
When working on it, we prioritized:
- being provider agnostic: Easily switch or add billing providers as your needs scale.
- having ready-to-use templates: We’ve provided full-stack examples for popular combinations like OpenRouter + Polar or OpenAI + Stripe.
- thinking of the developer experience: Less time configuring APIs, more time building features.
Basic example - adding cost to OpenAI calls
import {
UIMessage,
convertToModelMessages,
generateText,
wrapLanguageModel,
} from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
import { createOpenAIMiddleware } from '@ai-billing/openai';
import {
consoleDestination,
createObjectPriceResolver,
ModelPricing,
} from '@ai-billing/core';
const openai = createOpenAI({
// eslint-disable-next-line turbo/no-undeclared-env-vars
apiKey: process.env.OPENAI_API_KEY,
});
const customPricingMap: Record<string, ModelPricing> = {
'gpt-5': {
promptTokens: 1.25 / 1_000_000,
completionTokens: 10.0 / 1_000_000,
inputCacheReadTokens: 0.125 / 1_000_000,
},
'gpt-4o': {
promptTokens: 5.0 / 1_000_000,
completionTokens: 15.0 / 1_000_000,
},
};
const priceResolver = createObjectPriceResolver(customPricingMap);
const billingMiddleware = createOpenAIMiddleware({
destinations: [consoleDestination()],
priceResolver: priceResolver,
});
export async function POST() {
try {
const messages: UIMessage[] = [
{
id: 'test-gen-1',
role: 'user',
parts: [{ type: 'text', text: 'What is the capital of Sweden?' }],
},
];
const model = 'gpt-5';
const wrappedModel = wrapLanguageModel({
model: openai(model),
middleware: billingMiddleware,
});
const result = await generateText({
model: wrappedModel,
messages: await convertToModelMessages(messages),
});
return Response.json(result);
} catch (error) {
console.error('Generate Error:', error);
return Response.json({ error: (error as Error).message }, { status: 500 });
}
}
Full-stack projects built with @ai-billing
| Name | Demo Link | Repo | Deploy |
|---|---|---|---|
| Chatbot (OpenRouter + Polar) | View Demo | GitHub | Deploy with Vercel |
| Chatbot (OpenAI + Polar) | View Demo | GitHub | Deploy with Vercel |
| Chatbot (Stripe) | View Demo | GitHub | Deploy with Vercel |


Top comments (0)