Skip to main content
Glama

stripe

Official
by stripe
README.md10 kB
# Stripe Token Meter Generic token metering for native AI SDKs with automatic Stripe billing integration. Track and bill token usage from OpenAI, Anthropic, and Google Gemini without any framework dependencies. ## Private preview access required Stripe Billing for LLM Tokens is currently only available to organizations participating in the Billing for LLM Tokens Private Preview. If you do not have access and would like to request it, please visit: **[Request Access to Billing for LLM Tokens Private Preview](https://docs.stripe.com/billing/token-billing)** ## Why use Stripe Token Meter? - **Native SDK Support**: Works directly with native AI SDKs (OpenAI, Anthropic, Google) - **No Framework Required**: Direct integration without Vercel AI SDK or other frameworks - **Automatic Detection**: Automatically detects provider and response types - **Streaming Support**: Full support for streaming responses from all providers - **Fire-and-Forget**: Billing events are sent asynchronously without blocking - **Universal API**: Single interface works across all supported providers ## Installation ```bash npm install @stripe/token-meter ``` ## Supported providers - **OpenAI**: Chat Completions, Responses API, Embeddings (streaming and non-streaming) - **Anthropic**: Messages API (streaming and non-streaming) - **Google Gemini**: GenerateContent API (streaming and non-streaming) ## Quick start ### OpenAI ```typescript import OpenAI from 'openai'; import { createTokenMeter } from '@stripe/token-meter'; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const meter = createTokenMeter(process.env.STRIPE_API_KEY); // Non-streaming const response = await openai.chat.completions.create({ model: 'gpt-4o-mini', messages: [{ role: 'user', content: 'Hello!' }], }); meter.trackUsage(response, 'cus_xxxxx'); ``` ### Anthropic ```typescript import Anthropic from '@anthropic-ai/sdk'; import { createTokenMeter } from '@stripe/token-meter'; const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }); const meter = createTokenMeter(process.env.STRIPE_API_KEY); // Non-streaming const response = await anthropic.messages.create({ model: 'claude-3-5-sonnet-20241022', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello!' }], }); meter.trackUsage(response, 'cus_xxxxx'); ``` ### Google Gemini ```typescript import { GoogleGenerativeAI } from '@google/generative-ai'; import { createTokenMeter } from '@stripe/token-meter'; const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY); const meter = createTokenMeter(process.env.STRIPE_API_KEY); const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' }); const response = await model.generateContent('Hello!'); meter.trackUsage(response.response, 'cus_xxxxx'); ``` ## API reference ### `createTokenMeter(stripeApiKey, config?)` Creates a token meter instance for tracking usage. **Parameters:** - `stripeApiKey` (string): Your Stripe API key - `config` (optional): Configuration options - `meterEventName` (string): Custom meter event name (default: 'token-billing-tokens') **Returns:** TokenMeter instance ### `TokenMeter.trackUsage(response, customerId)` Tracks usage from a non-streaming response (fire-and-forget). **Parameters:** - `response`: The response object from OpenAI, Anthropic, or Google - `customerId` (string): Stripe customer ID to attribute usage to **Supported response types:** - `OpenAI.ChatCompletion` - `OpenAI.Responses.Response` - `OpenAI.CreateEmbeddingResponse` - `Anthropic.Messages.Message` - `GenerateContentResult` (Gemini) ### `TokenMeter.trackUsageStreamOpenAI(stream, customerId)` Wraps an OpenAI streaming response for usage tracking. **Parameters:** - `stream`: OpenAI stream (Chat Completions or Responses API) - `customerId` (string): Stripe customer ID **Returns:** The wrapped stream (can be consumed normally) **Important:** For OpenAI streaming, include `stream_options: { include_usage: true }` in your request. ### `TokenMeter.trackUsageStreamAnthropic(stream, customerId)` Wraps an Anthropic streaming response for usage tracking. **Parameters:** - `stream`: Anthropic message stream - `customerId` (string): Stripe customer ID **Returns:** The wrapped stream (can be consumed normally) ### `TokenMeter.trackUsageStreamGemini(stream, customerId, modelName)` Wraps a Google Gemini streaming response for usage tracking. **Parameters:** - `stream`: Gemini streaming result - `customerId` (string): Stripe customer ID - `modelName` (string): Model name (e.g., 'gemini-2.5-flash') **Returns:** The wrapped stream (can be consumed normally) ## Examples ### OpenAI streaming ```typescript import OpenAI from 'openai'; import { createTokenMeter } from '@stripe/token-meter'; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const meter = createTokenMeter(process.env.STRIPE_API_KEY); const stream = await openai.chat.completions.create({ model: 'gpt-4o-mini', messages: [{ role: 'user', content: 'Count to 5' }], stream: true, stream_options: { include_usage: true }, // Required for metering }); const meteredStream = meter.trackUsageStreamOpenAI(stream, 'cus_xxxxx'); for await (const chunk of meteredStream) { process.stdout.write(chunk.choices[0]?.delta?.content || ''); } ``` ### Anthropic streaming ```typescript import Anthropic from '@anthropic-ai/sdk'; import { createTokenMeter } from '@stripe/token-meter'; const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }); const meter = createTokenMeter(process.env.STRIPE_API_KEY); const stream = await anthropic.messages.create({ model: 'claude-3-5-sonnet-20241022', max_tokens: 1024, messages: [{ role: 'user', content: 'Count to 5' }], stream: true, }); const meteredStream = meter.trackUsageStreamAnthropic(stream, 'cus_xxxxx'); for await (const event of meteredStream) { if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') { process.stdout.write(event.delta.text); } } ``` ### Google Gemini streaming ```typescript import { GoogleGenerativeAI } from '@google/generative-ai'; import { createTokenMeter } from '@stripe/token-meter'; const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY); const meter = createTokenMeter(process.env.STRIPE_API_KEY); const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' }); const result = await model.generateContentStream('Count to 5'); const meteredStream = meter.trackUsageStreamGemini( result, 'cus_xxxxx', 'gemini-2.5-flash' ); for await (const chunk of meteredStream.stream) { process.stdout.write(chunk.text()); } ``` ### OpenAI Responses API ```typescript import OpenAI from 'openai'; import { createTokenMeter } from '@stripe/token-meter'; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const meter = createTokenMeter(process.env.STRIPE_API_KEY); const response = await openai.responses.create({ model: 'gpt-4o-mini', input: 'What is 2+2?', instructions: 'You are a helpful math assistant.', }); meter.trackUsage(response, 'cus_xxxxx'); console.log('Output:', response.output); ``` ### OpenAI embeddings ```typescript import OpenAI from 'openai'; import { createTokenMeter } from '@stripe/token-meter'; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const meter = createTokenMeter(process.env.STRIPE_API_KEY); const response = await openai.embeddings.create({ model: 'text-embedding-3-small', input: 'Hello, world!', }); meter.trackUsage(response, 'cus_xxxxx'); console.log('Embedding dimensions:', response.data[0].embedding.length); ``` ## How it works The token meter: 1. **Detects Provider**: Automatically identifies the AI provider from the response 2. **Extracts Usage**: Pulls token counts from the response object 3. **Reports to Stripe**: Sends meter events asynchronously to Stripe 4. **Non-Blocking**: Never interrupts your application flow For streaming responses, the meter wraps the stream and reports usage after the stream completes. ## Stripe meter events Each API call generates meter events sent to Stripe: **Input tokens event:** ```javascript { event_name: 'token-billing-tokens', payload: { stripe_customer_id: 'cus_xxxxx', value: '100', model: 'openai/gpt-4o-mini', token_type: 'input' } } ``` **Output tokens event:** ```javascript { event_name: 'token-billing-tokens', payload: { stripe_customer_id: 'cus_xxxxx', value: '50', model: 'openai/gpt-4o-mini', token_type: 'output' } } ``` ## Error handling The token meter handles errors gracefully: - **Stripe API Errors**: Logged to console but don't interrupt your application - **Missing Usage Data**: Handles responses without usage information - **Invalid Provider**: Logs a warning for unrecognized providers ## TypeScript support Full TypeScript support with type definitions for all providers: ```typescript import type { TokenMeter, SupportedResponse, SupportedStream } from '@stripe/token-meter'; ``` ## Comparison with AI SDK Meter ### Use Token Meter when - You're using native SDKs (OpenAI, Anthropic, Google) directly - You don't want to depend on Vercel AI SDK - You need maximum control over API parameters - You're working with embeddings or specialized APIs ### Use AI SDK Meter when - You're already using Vercel AI SDK - You want a unified interface across providers - You need AI SDK-specific features (tool calling abstractions, etc.) - You prefer the AI SDK's streaming abstractions ## Additional resources - [Stripe Meter Events Documentation](https://docs.stripe.com/api/billing/meter-event) - [Stripe Token Billing Documentation](https://docs.stripe.com/billing/token-billing) - [OpenAI API Documentation](https://platform.openai.com/docs/api-reference) - [Anthropic API Documentation](https://docs.anthropic.com/claude/reference) - [Google Gemini API Documentation](https://ai.google.dev/docs) - [Example Applications](./examples/) ## License MIT

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stripe/agent-toolkit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server