How to Monitor LLM API Spending Across Providers
If you're using more than one LLM provider — Claude for reasoning, GPT-4 for certain tasks, maybe a local model for drafts — you've probably hit the same wall: each provider has its own billing dashboard, its own usage export format, and its own definition of a "token." There's no native way to see total spend in one place.
The practical answer is to stop relying on provider dashboards for cross-provider visibility and instead centralize usage data yourself, either by logging every request's token counts and cost at the application layer, or by routing traffic through a gateway that normalizes metadata across providers. Below is how to actually set that up, plus the pitfalls that make this harder than it sounds.
Why Provider Dashboards Aren't Enough
Every provider gives you a usage view, but none give you the usage view:
- Different granularity. Anthropic's console shows usage by API key and date. OpenAI's shows usage by project. Neither aligns cleanly with "cost per customer" or "cost per feature" unless you've already tagged requests carefully.
- Different pricing models. Input tokens, output tokens, cached tokens, and tool-use tokens are priced differently per provider, and sometimes per model version within the same provider.
- Delayed data. Billing dashboards often lag by hours. If you're trying to catch a runaway loop or a misconfigured retry, you find out after the damage is done, not during it.
- No unified export. You end up pulling CSVs from three different consoles and reconciling them manually in a spreadsheet — which nobody keeps up with past the second month.
If your goal is a single number ("what did we spend on LLM calls this week, across all providers"), you need a data layer that sits above the providers, not inside each one.
Option 1: Log Usage Yourself at the Application Layer
The most control-heavy approach is to capture token counts and cost directly in your own code, every time you make a call.
async function callModel(provider, request) {
const start = Date.now();
const response = await provider.send(request);
const usage = response.usage; // shape differs per provider
const cost = computeCost(provider.name, usage);
await logUsage({
provider: provider.name,
model: request.model,
inputTokens: usage.input_tokens,
outputTokens: usage.output_tokens,
cost,
latencyMs: Date.now() - start,
requestId: response.id,
timestamp: new Date().toISOString(),
});
return response;
}
This works, but you own the cost tables for every model and every provider, and you have to update them whenever pricing changes. It's accurate and flexible, but it's maintenance overhead that scales with the number of providers you add.
Option 2: Standardize Metadata Before It Hits Your Database
If you're not ready to build a full logging pipeline, at minimum tag every outbound request with structured metadata you control: which feature triggered it, which customer or team it belongs to, and which environment (staging vs production) it ran in. Store that alongside the raw usage response from each provider, even if the usage response format differs.
The goal is to make every row in your logs answerable to the same questions, regardless of which provider generated it:
- Which provider and model?
- How many input/output tokens?
- What did it cost, in your currency?
- Which internal feature or customer caused it?
Once that's consistent, aggregating "total spend this month across providers" is a straightforward SQL query instead of a manual reconciliation task.
Option 3: Use a Gateway That Already Normalizes This
If building and maintaining your own cross-provider logging pipeline isn't where you want to spend engineering time, a gateway that sits in front of your LLM calls and exposes usage metadata in a consistent format solves most of this automatically — at least for the providers it supports.
For teams specifically using Claude through multiple internal apps, SubToAPI turns your Claude access into an HTTPS API with application-specific keys (sub_live_...), and every response includes usage metadata in a consistent shape regardless of which app or team member made the call. That doesn't make OpenAI spend visible in the same dashboard, but it does solve the "which of our five internal tools is burning Claude tokens" problem without you writing a custom logging layer for Claude calls specifically. You get per-key and per-seat visibility out of the box, which is the piece most teams underestimate until they're three apps deep into Claude usage and can't tell which one is expensive.
If your stack is genuinely multi-provider, the realistic setup is: normalize Claude usage through something like SubToAPI (or your own logging layer), do the same for OpenAI and any other provider, and pull both into a shared reporting view — a simple internal dashboard, a spreadsheet fed by a scheduled export, or a BI tool. There's no single hosted product today that transparently bills and reports across every provider as if they were one account, so the normalization step on your side is unavoidable.
A Minimal Cross-Provider Tracking Table
If you're rolling your own, this schema covers the essentials without over-engineering it:
CREATE TABLE llm_usage (
id UUID PRIMARY KEY,
provider TEXT NOT NULL,
model TEXT NOT NULL,
feature TEXT,
team_id TEXT,
input_tokens INT,
output_tokens INT,
cost_usd NUMERIC(10, 6),
created_at TIMESTAMPTZ DEFAULT now()
);
With this in place, a daily spend-by-provider query is one GROUP BY provider away, and you can layer alerts on top once thresholds matter.
Checklist Before You Trust Your Numbers
- Confirm whether each provider's usage field counts cached tokens the same way (they often don't).
- Recompute cost yourself from token counts rather than trusting a provider's reported dollar amount — rounding and tiered pricing can cause small discrepancies.
- Tag every request with a feature or customer identifier at call time, not after the fact.
- Reconcile your internal totals against the provider's billing dashboard monthly. Treat your dashboard as the operational view and the provider's as the source of truth for invoicing.
questions
Can I see total spend across Claude and OpenAI in one dashboard without building anything? Not from the providers directly — each bills and reports separately. You can get unified visibility for Claude usage specifically through a layer like SubToAPI, and combine that with your own tracking for other providers.
Why don't my calculated costs match the provider's invoice exactly? Differences usually come from cached-token discounts, rounding at the token-batch level, or mid-month pricing changes. Use the provider's invoice as the authoritative number and your own logs for day-to-day trend monitoring.
What's the minimum data I need to track to monitor spend reliably? Provider, model, input tokens, output tokens, and a feature or customer tag per request. That's enough to compute cost and attribute it, even before you build dashboards or alerts on top.