← Blog

LLM Cost Tracking: How to Actually Monitor API Spend

2026-09-18 · 5 min read · SubToAPI Team

LLM cost tracking means recording, attributing, and monitoring how much you spend on model API calls — broken down by user, feature, environment, or team — so you can catch overspend before the invoice arrives. It's different from cost estimation (predicting spend in advance) because it deals with actual, historical usage data pulled from real requests.

If you're searching for this, you probably already have an LLM feature in production and you've either been surprised by a bill or you're trying to avoid being surprised next month. This article covers what to track, how to instrument it, and how to build a system that gives you answers instead of guesses.

Why Cost Tracking Gets Skipped

Most teams add LLM calls to a feature, ship it, and only look at cost when finance asks a question. This happens for a few reasons:

None of these are hard problems individually, but they compound. By the time you notice a cost spike, you've usually lost the context needed to explain it.

What to Actually Track

A useful LLM cost tracking setup captures more than a running total. At minimum, log these fields per request:

With these fields, you can answer the questions that actually matter: which feature is expensive, which users are driving cost, and whether a recent deploy changed your spend trajectory.

Instrumenting Cost Tracking Yourself

If you're calling a model API directly, the token counts usually come back in the response metadata. A basic logging wrapper looks like this:

async function trackedCall(payload, meta) {
  const start = Date.now();
  const response = await callModel(payload);

  await logUsage({
    timestamp: new Date().toISOString(),
    model: payload.model,
    inputTokens: response.usage.input_tokens,
    outputTokens: response.usage.output_tokens,
    feature: meta.feature,
    userId: meta.userId,
    environment: process.env.NODE_ENV,
    latencyMs: Date.now() - start,
  });

  return response;
}

This gets you raw data, but you still have to build the pricing math, the dashboard, and the alerting on top of it. For a side project that's fine. For anything with multiple developers or multiple features hitting the model, it turns into ongoing maintenance — pricing tables change, new models get added, and someone has to keep the aggregation queries correct.

Attribution: The Part People Underbuild

Raw totals tell you what you spent. Attribution tells you why. The most common attribution gaps:

Tagging every call correctly is tedious to enforce manually — someone always forgets to pass the metadata, and now you have a chunk of untracked spend.

Where a Managed Layer Helps

This is where a managed API layer can remove a category of work rather than just adding another dashboard. SubToAPI sits between your app and Claude, issuing application-level API keys (sub_live_...) per team or per project, and every request that goes through those keys carries usage metadata — tokens in, tokens out, model used — that you can pull for reporting.

Instead of building your own logging wrapper, pricing table, and aggregation job, you generate a separate key per feature or per environment from the SubToAPI dashboard, and the usage naturally splits along those lines. If you want per-customer attribution, a key per customer works the same way. The quickstart covers key creation and the messages docs cover the request format, which mirrors the standard Claude API shape:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Summarize this ticket."}]
  }'

Because seats and keys are managed per team (Solo €9, Team €19/seat, Scale €49/seat), cost tracking maps directly to your org structure instead of requiring a separate attribution system bolted on afterward. That's a meaningful shortcut if you're a small team and don't want to own a billing pipeline as a side project.

Setting Up Alerts, Not Just Dashboards

A dashboard you check once a week won't catch a runaway loop that burns through your budget in six hours. At minimum, set up:

If you're building this yourself, a simple cron job that queries yesterday's usage and compares it against a rolling average catches most anomalies without much engineering effort.

Keeping It Simple

You don't need a full observability platform on day one. Start with per-request logging of tokens, model, and feature. Add per-user attribution once you have more than one meaningful user segment. Add alerting once you've been burned once by a spike you didn't see coming. Every added layer should answer a specific question you've actually needed to answer — not one you might need to answer someday.

Questions

Does LLM cost tracking replace rate limiting? No. Cost tracking tells you what happened after the fact; rate limiting prevents runaway spend in real time. You generally want both — tracking for reporting and attribution, limits for protection.

Can I track cost without provider-level token metadata? You can estimate it by counting tokens client-side with a tokenizer library, but actual provider-reported usage is more accurate, especially for output tokens in streaming responses.

How often should I review LLM cost data? Daily for anomaly detection (a spike usually means a bug, not organic growth) and weekly for trend review across features and teams.

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 →