VercelVercel
Menu

Stripe Billing

Last updated March 9, 2026

You can bill your customers for AI usage by connecting AI Gateway to Stripe's metered billing. When you include Stripe headers in your requests, AI Gateway automatically emits meter events for every successful response.

When you include Stripe headers in your requests, AI Gateway:

  1. Routes the request to the appropriate AI provider
  2. On a successful response, emits two separate meter events to Stripe: one for input tokens and one for output tokens
  3. Includes the customer ID, token count, token type (input or output), and model ID in each meter event

Stripe metering is non-blocking. If a meter event fails, AI Gateway still returns the AI response. Errors are logged for observability but don't affect the response.

Before you start, you'll need:

  1. A Stripe account with access to the Billing Meter API
  2. A billing meter named token-billing-tokens configured in your Stripe dashboard
  3. A Stripe restricted access key (rk_...) with permission to write meter events
  4. Stripe customer IDs (cus_...) for the users you want to bill

You configure Stripe billing entirely through HTTP headers. No changes to the request body are needed:

HeaderRequiredDescription
stripe-customer-idYesThe Stripe customer ID to bill (e.g., cus_abc123)
stripe-restricted-access-keyYesA Stripe restricted API key with meter event write permissions (e.g., rk_live_...)

Both headers must be present for meter events to fire. If either is missing, the request proceeds normally without billing.

You can pass Stripe headers at the gateway level (applies to all requests) or per-request.

Gateway-level headers:

ai-sdk-gateway.ts
import { createGateway } from '@ai-sdk/gateway';
import { streamText } from 'ai';
 
const gateway = createGateway({
  baseURL: 'https://ai-gateway.vercel.sh/v1/ai',
  apiKey: process.env.AI_GATEWAY_API_KEY,
  headers: {
    'stripe-customer-id': process.env.STRIPE_CUSTOMER_ID,
    'stripe-restricted-access-key': process.env.STRIPE_RESTRICTED_ACCESS_KEY,
  },
});
 
const result = streamText({
  model: gateway('anthropic/claude-sonnet-4.6'),
  prompt: 'Explain quantum computing in simple terms.',
});
 
for await (const part of result.textStream) {
  process.stdout.write(part);
}

Per-request headers (useful when you bill different customers from the same gateway instance):

ai-sdk-per-request.ts
import { createGateway } from '@ai-sdk/gateway';
import { streamText } from 'ai';
 
const gateway = createGateway({
  baseURL: 'https://ai-gateway.vercel.sh/v1/ai',
  apiKey: process.env.AI_GATEWAY_API_KEY,
});
 
const result = streamText({
  model: gateway('openai/gpt-5.4'),
  prompt: 'Summarize how usage-based billing works.',
  headers: {
    'stripe-customer-id': customerId,
    'stripe-restricted-access-key': process.env.STRIPE_RESTRICTED_ACCESS_KEY,
  },
});
openai.ts
import OpenAI from 'openai';
 
const openai = new OpenAI({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/v1',
  defaultHeaders: {
    'stripe-customer-id': process.env.STRIPE_CUSTOMER_ID,
    'stripe-restricted-access-key': process.env.STRIPE_RESTRICTED_ACCESS_KEY,
  },
});
 
const completion = await openai.chat.completions.create({
  model: 'anthropic/claude-sonnet-4.6',
  messages: [{ role: 'user', content: 'Hello!' }],
});
 
console.log(completion.choices[0].message.content);
anthropic.ts
import Anthropic from '@anthropic-ai/sdk';
 
const anthropic = new Anthropic({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh',
  defaultHeaders: {
    'stripe-customer-id': process.env.STRIPE_CUSTOMER_ID,
    'stripe-restricted-access-key': process.env.STRIPE_RESTRICTED_ACCESS_KEY,
  },
});
 
const message = await anthropic.messages.create({
  model: 'anthropic/claude-sonnet-4.6',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello!' }],
});
 
console.log(message.content);
openai_billing.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv("AI_GATEWAY_API_KEY"),
    base_url="https://ai-gateway.vercel.sh/v1",
    default_headers={
        "stripe-customer-id": os.getenv("STRIPE_CUSTOMER_ID"),
        "stripe-restricted-access-key": os.getenv("STRIPE_RESTRICTED_ACCESS_KEY"),
    },
)
 
completion = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{"role": "user", "content": "Hello!"}],
)
 
print(completion.choices[0].message.content)
anthropic_billing.py
import os
import anthropic
 
client = anthropic.Anthropic(
    api_key=os.getenv("AI_GATEWAY_API_KEY"),
    base_url="https://ai-gateway.vercel.sh",
    default_headers={
        "stripe-customer-id": os.getenv("STRIPE_CUSTOMER_ID"),
        "stripe-restricted-access-key": os.getenv("STRIPE_RESTRICTED_ACCESS_KEY"),
    },
)
 
message = client.messages.create(
    model="anthropic/claude-sonnet-4.6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
 
print(message.content)

For security, use a Stripe restricted API key instead of your secret key. The restricted key only needs permission to write billing meter events.

To create one:

  1. Go to Stripe Dashboard > Developers > API keys
  2. Click Create restricted key
  3. Enable Write permission for Billing meter events
  4. Save the key (starts with rk_live_ or rk_test_)

If the key is ever exposed, the blast radius is limited. It can't access customer data, create charges, or perform any other Stripe operations.

Each successful request emits two meter events to Stripe's /v2/billing/meter_events endpoint, one for input tokens and one for output tokens:

{
  "event_name": "token-billing-tokens",
  "payload": {
    "stripe_customer_id": "cus_abc123",
    "value": "1500",
    "token_type": "input",
    "model": "anthropic/claude-sonnet-4.6"
  }
}

The model field uses the AI Gateway canonical model slug (e.g., openai/gpt-5.4, anthropic/claude-sonnet-4.6).

AI Gateway handles Stripe meter events with the following guarantees:

  • Non-blocking: You always get the AI response, even if Stripe metering fails
  • Idempotent: Each meter event has a unique identifier, which prevents duplicate billing
  • Conditional: AI Gateway only emits events on successful responses and when token counts are greater than zero
  • Observable: Failures log stripe_meter_failed metrics for monitoring

Was this helpful?

supported.