← Blog

Claude API Usage-Based Billing Implementation

2026-10-15 · 5 min read · SubToAPI Team

Why usage-based billing is hard with the Claude API

If you're building a product on top of Claude and charging customers based on how much they use it, you need a system that turns raw API responses into accurate, auditable billing records. The core challenge is that Claude's API bills you (the developer) per token, but your customers probably don't want to think in tokens — they want to pay per message, per document processed, per seat, or a flat monthly fee with usage caps. Implementing usage-based billing means building the translation layer between Anthropic's token-based pricing and whatever pricing model your product actually sells.

This article walks through the pieces you need: capturing usage data from every API call, aggregating it correctly across streaming and tool-use requests, mapping it to a price, and getting that into an invoicing system like Stripe without losing accuracy or double-counting retries. If you'd rather skip building this yourself, a proxy like SubToAPI exposes per-key usage metadata out of the box — but the rest of this guide is useful whether you build it in-house or not.

What you need to meter

Every Claude API response includes a usage object with input and output token counts. That's your raw metering data, but it's not the whole picture:

A minimal usage record per API call should look like this:

{
  "request_id": "req_8f2a...",
  "customer_id": "cus_104",
  "model": "claude-sonnet-4",
  "input_tokens": 842,
  "output_tokens": 311,
  "cache_read_tokens": 0,
  "cache_write_tokens": 0,
  "timestamp": "2025-01-14T10:22:03Z"
}

Store this for every call, not just successful ones with completions — you'll need it for reconciliation later.

Capturing usage from streaming responses

Streaming complicates metering because the usage field doesn't arrive until the final event. You have to buffer the stream server-side (even if you relay it to the client in real time) and read the message_stop or final message_delta event to get the authoritative token counts.

let finalUsage = null;

for await (const event of stream) {
  if (event.type === "message_delta" && event.usage) {
    finalUsage = event.usage;
  }
  // relay event to your client as usual
}

await recordUsage({
  customerId,
  inputTokens: finalUsage.input_tokens,
  outputTokens: finalUsage.output_tokens,
});

Never estimate token counts client-side with a tokenizer approximation for billing purposes — small discrepancies compound at scale and lead to billing disputes. Always use the counts Anthropic returns. See the streaming guide in the docs at /docs/streaming if you're integrating this through a proxy rather than the raw API.

Mapping usage to a price

Once you have raw token counts, you need a pricing function. Keep this as a pure function, separate from your metering pipeline, so you can change prices without touching how data is collected:

function calculateCost(usage, rateCard) {
  const inputCost = usage.input_tokens * rateCard.inputPerToken;
  const outputCost = usage.output_tokens * rateCard.outputPerToken;
  const cacheCost =
    usage.cache_read_tokens * rateCard.cacheReadPerToken +
    usage.cache_write_tokens * rateCard.cacheWritePerToken;
  return inputCost + outputCost + cacheCost;
}

Decide early whether you're passing Anthropic's raw cost through with a markup, charging a flat per-request fee, or bundling usage into subscription tiers with overage billing. Most SaaS products on top of Claude do some combination: a base plan with included usage, then metered overage billed through Stripe's usage records API.

Sending usage to your billing provider

Aggregate usage records on a schedule (hourly or daily is typical) rather than calling your billing provider on every API request — this avoids rate limits and keeps your billing pipeline resilient to retries:

const dailyUsage = await aggregateUsageByCustomer(date);

for (const [customerId, usage] of dailyUsage) {
  await stripe.billing.meterEvents.create({
    event_name: "claude_tokens",
    payload: {
      stripe_customer_id: customerId,
      value: usage.totalTokens.toString(),
    },
  });
}

Keep the raw per-request records even after aggregation — you'll need them if a customer disputes a charge or you need to debug a spike in usage.

Multi-tenant and team billing

If your product has teams or seats, usage needs to roll up from individual API keys to an organization, and you need a way to attribute each call to the right tenant even when requests come from shared infrastructure. This is one of the more tedious parts to build correctly — key provisioning, per-key usage tracking, and rollups to a team invoice.

This is exactly the layer SubToAPI handles if you don't want to build it: it issues scoped application keys (sub_live_...) per team member, tracks usage metadata per key automatically, and gives you a dashboard view without writing a metering pipeline yourself. Plans run from Solo at €9 up to Team and Scale tiers with per-seat pricing — see /pricing for details, or start with a free trial at /signup. If you're integrating against it directly, the request format mirrors the standard Messages API, documented at /docs/messages and /docs/quickstart.

Common pitfalls

FAQ

Does Anthropic provide usage-based billing for my own customers? No. Anthropic bills you directly for API usage. If you want to charge your own customers based on their usage, you need to build (or use) a separate metering and invoicing layer on top.

Should I bill customers in tokens or in a simplified unit like "credits"? Most products abstract tokens into credits or request counts because customers don't think in tokens. Keep token counts as your internal source of truth and convert to whatever unit you expose externally.

How often should I sync usage data to my billing provider? Hourly or daily batches are standard for most products. Real-time sync is rarely necessary unless you're enforcing hard spending caps, in which case you need a separate real-time counter independent of your invoicing pipeline.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →