← Blog

How to Monitor LLM API Costs Across Providers

2026-10-30 · 6 min read · SubToAPI Team

If you're spending money on more than one LLM provider, you've probably noticed that none of them make it easy to see the full picture. OpenAI gives you a usage dashboard, Anthropic gives you a different one, and if you're calling a third model through a gateway or self-hosted endpoint, you get a CSV or nothing at all. Monitoring LLM API costs across providers means collecting usage and spend data from every source into one place, normalizing it so the numbers are comparable, and setting up alerts before a bill surprises you.

There are three practical approaches: pull usage data from each provider's billing API and aggregate it yourself, tag every request with metadata so you can attribute cost after the fact, or route everything through a single gateway that logs usage centrally. Most teams end up combining the second and third. Below is how to actually do it, step by step.

Why Provider Dashboards Aren't Enough

Each provider's console tells you what you spent with them — nothing more. That's a problem once you're running more than one model in production:

The fix is to stop relying on provider dashboards as your source of truth and instead build (or adopt) a layer that sits above them.

Step 1: Tag Every Request at the Source

Before you can monitor cost across providers, you need cost to be attributable. The cheapest way to do this is to tag requests at call time with metadata like customer ID, feature name, and environment, then log token usage alongside that tag every time a response comes back.

async function callModel(prompt, { customerId, feature }) {
  const start = Date.now();
  const response = await client.messages.create({
    model: "claude-sonnet-4",
    max_tokens: 1024,
    messages: [{ role: "user", content: prompt }],
  });

  logUsage({
    provider: "anthropic",
    model: "claude-sonnet-4",
    customerId,
    feature,
    inputTokens: response.usage.input_tokens,
    outputTokens: response.usage.output_tokens,
    latencyMs: Date.now() - start,
  });

  return response;
}

Do the same wrapper for every provider you call, normalizing the log shape so provider, model, inputTokens, outputTokens, and costUsd always mean the same thing regardless of where the request went. This single decision — one log schema for all providers — is what makes cross-provider monitoring possible later.

Step 2: Centralize Token-to-Cost Conversion

Token counts are useless for cost tracking unless you convert them using current pricing. Keep a small pricing table in your codebase or config store, rather than hardcoding costs inline, because pricing changes:

const PRICING = {
  "anthropic:claude-sonnet-4": { input: 3.00, output: 15.00 }, // per 1M tokens
  "openai:gpt-4o": { input: 2.50, output: 10.00 },
};

function computeCostUsd(provider, model, inputTokens, outputTokens) {
  const rate = PRICING[`${provider}:${model}`];
  return (inputTokens / 1_000_000) * rate.input +
         (outputTokens / 1_000_000) * rate.output;
}

Apply this at log time so every row in your usage table already has a dollar figure. That lets you sum, group, and compare costs across providers using plain SQL, instead of reconciling token counts against each provider's pricing page every time you need a number.

Step 3: Build One Dashboard, Not Three

Once usage is logged with a consistent schema, push it into whatever analytics tool you already use — Postgres plus a BI layer, or even a scheduled export to a spreadsheet for smaller teams. The dashboard should answer four questions at a glance:

  1. Total spend by provider, this month vs last month
  2. Spend by feature or customer, to catch runaway usage early
  3. Cost per request trend, to spot regressions after a prompt change
  4. Cache hit rate and savings, if your provider supports prompt caching

If you're already proxying requests through a unified API layer, this step is largely done for you. SubToAPI, for example, exposes usage metadata on every response and in the dashboard, so request counts, token usage, and cost per key are visible without wiring up your own logging pipeline for the Claude side of your stack. See the docs for the response shape, or pricing for plan details if you're evaluating it.

Step 4: Set Budget Alerts Before You Need Them

Don't wait for a surprise invoice. Set alerts at two levels:

A simple cron-based check is enough to start:

const hourlySpend = await db.query(
  `SELECT SUM(cost_usd) FROM usage_log WHERE created_at > now() - interval '1 hour'`
);
if (hourlySpend > HOURLY_BUDGET_THRESHOLD) {
  await sendAlert(`Hourly LLM spend exceeded threshold: $${hourlySpend}`);
}

Step 5: Review Cost Per Outcome, Not Just Per Call

Raw spend numbers are misleading without context. A feature that costs more per call but resolves a task in one round trip can be cheaper overall than a "cheap" model that needs three retries to get a usable answer. Once you have cost and outcome data (success rate, retries, user satisfaction) in the same table, you can compute cost-per-successful-outcome by feature — which is the number that actually matters when deciding whether to switch providers or models.

Keeping It Simple If You're Using One API Layer

If part of the reason you're juggling multiple dashboards is that you access Claude through several different API keys or integrations, consolidating access first makes monitoring much easier. A single key with usage metadata attached to every response removes the need to build your own token-to-cost pipeline for that provider — you just read the numbers off the response or the dashboard. Check the quickstart if you want to see how request-level usage metadata looks in practice, and streaming if your cost concerns are specifically about long-running streamed responses, which can be harder to account for than single-shot calls.

FAQ

Do all LLM providers report token usage the same way? No. Field names, cache-token accounting, and whether usage is returned per-request or only in aggregate billing reports all differ. Normalize to your own schema immediately after each call rather than trying to compare raw provider fields.

What's the fastest way to start monitoring costs if I have nothing in place today? Add a logging wrapper around every model call that records provider, model, token counts, and a tag for feature or customer. Even without a dashboard, a simple SQL query against that log will answer most cost questions within a day.

Can I monitor costs without building custom logging? Partially. Provider dashboards cover single-provider totals, and a unified API layer like SubToAPI can give you per-key usage metadata for the traffic routed through it, but cross-provider aggregation still requires pulling that data into one place yourself.

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 →