← Blog

Claude API Usage Tracking Per Customer: A Practical Guide

2026-09-25 · 6 min read · SubToAPI Team

If you're building a product on top of Claude and charging customers, at some point you need to answer a simple question: how much is each customer actually costing me, and are they within their plan limits? Anthropic's API gives you aggregate token usage in your console, but it doesn't know about your customers, your tiers, or your billing periods. That mapping is entirely on you to build.

This article covers the practical ways to implement per-customer usage tracking for the Claude API — what to log, how to attribute costs, how to enforce quotas, and where a managed layer like SubToAPI removes most of the plumbing.

Why Anthropic's dashboard isn't enough

The Anthropic console shows you total requests and token counts for your organization. That's useful for your own cost forecasting, but it's a single number — it doesn't break down by end user, tenant, or API key. If you're running a multi-tenant SaaS where different customers make Claude calls through your backend, you need your own attribution layer sitting between your app and the Anthropic API.

There are three common reasons teams need this:

What to log on every request

Whatever approach you take, capture this data for every call, ideally in a structured table rather than raw logs:

The usage field in every Claude API response gives you input_tokens and output_tokens directly — you don't need to estimate with a tokenizer. Store both, since output tokens are usually priced higher and dominate cost for long-form responses.

const response = await fetch("https://api.anthropic.com/v1/messages", {
  method: "POST",
  headers: {
    "x-api-key": process.env.ANTHROPIC_API_KEY,
    "anthropic-version": "2023-06-01",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    model: "claude-sonnet-4-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: prompt }],
  }),
});

const data = await response.json();

await db.usageEvents.insert({
  customerId,
  model: data.model,
  inputTokens: data.usage.input_tokens,
  outputTokens: data.usage.output_tokens,
  createdAt: new Date(),
});

Once you have this table, per-customer usage is just a GROUP BY customer_id query over your chosen billing window.

Building attribution into your architecture

The cleanest pattern is to route every Claude call through a single internal function or service that wraps the API call and writes the usage event atomically. Avoid calling Claude directly from multiple places in your codebase — you'll inevitably miss logging in one path and end up with under-billed customers.

A common structure:

  1. Your app calls an internal callClaude(customerId, params) function.
  2. That function makes the actual API request, applying your system prompt and any per-customer overrides.
  3. On response, it writes the usage event before returning the result to the caller.
  4. A separate job aggregates events into daily or monthly rollups per customer for billing and dashboards.

This gives you a single choke point for logging, rate limiting, and quota checks, which is much easier to reason about than scattering API calls across your codebase.

Enforcing quotas before the request

Tracking after the fact is necessary for billing, but if you want to stop a customer from blowing past their plan limit, you need a check before the request goes out — otherwise you're always one request behind.

async function callClaude(customerId, params) {
  const usage = await getMonthlyUsage(customerId);
  const plan = await getPlan(customerId);

  if (usage.totalTokens >= plan.tokenLimit) {
    throw new Error("Usage limit exceeded for this billing period");
  }

  // proceed with the API call
}

For high-throughput products, run this check against a cache (Redis counter incremented per request) rather than querying your primary database on every call — a database round trip per request adds latency you don't want on the hot path.

Where per-key tracking simplifies things

If each of your customers or applications gets its own API key, usage tracking becomes much simpler — you can attribute cost by key instead of building a separate tagging system inside your database.

This is one of the reasons teams put a layer like SubToAPI in front of their Claude access: it issues distinct sub_live_... keys per application or team, and every request made with a key is already tagged with usage metadata — streaming responses, tool calls, and token counts included — without you writing custom logging middleware. If you're already tracking usage per customer manually, moving key issuance to /docs/quickstart can remove a chunk of the bookkeeping, since the per-key breakdown is available directly in the dashboard instead of being reconstructed from logs.

For teams with multiple seats, plans like Solo (€9), Team (€19/seat), and Scale (€49/seat) map naturally onto per-customer or per-team key structures — see /pricing for details.

Handling streaming and tool use in your logs

Two things trip people up when they add usage tracking after the fact:

Getting this wrong doesn't break functionality, but it does produce billing numbers that don't match what actually happened — which is the kind of bug that only surfaces when a customer disputes an invoice.

Getting started quickly

If you're weighing whether to build this attribution layer yourself or use a hosted one, the honest answer depends on scale: a single-tenant internal tool can get away with a simple logging wrapper and a cron job. A multi-tenant SaaS billing customers directly benefits from key-level separation from day one, since retrofitting per-customer attribution onto a shared API key is painful. You can try a free trial at /signup to see the dashboard-based approach before committing.

questions

Do I need to track tokens or requests for accurate billing? Tokens. Request counts don't reflect cost — a single request with a 50,000-token document costs far more than dozens of short ones. Always log input_tokens and output_tokens from the API response.

Can I track usage without giving each customer a separate API key? Yes, by tagging every internal call with a customer ID and logging usage in your own database. It works, but it puts the correctness burden entirely on your application code rather than the infrastructure.

How often should I aggregate usage data for billing? Daily rollups are enough for most SaaS billing cycles. Real-time counters (Redis or similar) are only necessary if you're enforcing hard quotas mid-request rather than just reporting usage after the fact.

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 →