LLM Cost Allocation: How to Attribute Spend on OpenAI, Anthropic, Bedrock, Vertex and Mistral
Tanguy (CTO)
LLM cost is going the same way cloud did ten years ago. It starts small so nobody looks, and by the time the bill is big enough to look at, nobody can say where it came from. The pricing makes it worse. Every provider prices differently, and within one provider a call costs a different amount depending on the prompt size, whether the tokens were cached, and whether you ran it batch or on-demand. So even one call is a pain to reason about, and figuring out whose call it was never happens. Untagged EC2, again.
Over the last six months our customers' bills have changed a lot. They're spikier than they used to be, and the spend is spread across things that never used to be separate line items someone's coding agent running on Claude Code, some workload on Bedrock, something else hitting Gemini through Vertex.
The providers have been slow at start that's changed since the end of H1; the tooling to actually allocate this stuff is finally showing up. This guide covers how to use it: the cleanest way to attribute spend on each provider, and then how to get all of it into one view you can budget and report against.
The jungle of today
In cloud this got solved a long time ago: you tag a resource, the tag lands on the bill, everyone settled on the convention and moved on. The LLM providers looked at a solved problem and decided to innovate. So there's no shared standard , each built its own way of telling you who spent what, and none of them agree. Different mechanism, different granularity, different amount of setup.
It starts one level down, at pricing. Before you can attribute a cost you have to know what you're paying for, and an API call's price moves on four axes: model, prompt size, priority tier, and caching. Sitting next to all of that is a separate track , flat per-seat subscriptions, which is how most coding agents actually get billed.
Provider | Model range ($/1M in→out) | Prompt size | Priority tier | Caching | Subscription |
|---|---|---|---|---|---|
OpenAI | GPT-5.4 nano $0.20/$1.25 → GPT-5.6 Sol $5/$30 | Long-context surcharge on some models | Batch · Flex · Standard · Priority | Automatic; reads discounted, writes free | ChatGPT Plus / Team / Enterprise (Codex) |
Anthropic | Haiku 4.5 $1/$5 → Fable 5 $10/$50 (Opus 4.8 $5/$25) | >200K-token tier priced higher | Batch · Standard · Priority Tier | Explicit ( | Claude Pro / Max (Claude Code) |
Azure OpenAI | GPT-5.4 nano $0.20/$1.25 → GPT-5.6 Sol $5/$30 (mirrors OpenAI rates) | Same as OpenAI models | Batch · Standard · Provisioned (PTU) | Cached input | None (M365 Copilot is the sibling) |
AWS Bedrock | Nova Micro $0.035/$0.14 → Claude Opus 4.8 $5/$25 | Varies by model | Batch · On-demand · Provisioned Throughput | Supported, model-dependent | None |
GCP Vertex AI | Gemini 3.1 Flash-Lite $0.25/$1.50 → 3.1 Pro $2/$12 | Per-character on some; >200K raises Pro to $4/$18 | Batch · Flex PayGo · Standard PayGo · Priority · Provisioned Throughput | Context caching (charges for storage) | Gemini Code Assist |
Mistral | Small 4 $0.15/$0.60 → Magistral Medium $2/$5 (Large 3 flagship $0.50/$1.50) | Varies by model | Batch · Standard | Model-dependent | Le Chat Pro / Team |
Standard-tier list prices, USD per 1M tokens (input/output), as of 23 July 2026 , verify before budgeting. Bedrock and Vertex also host other vendors' models (e.g. Claude) at higher rates than their native flagship.
Caching is usually the biggest lever on the whole bill. A cache read costs a fraction of a fresh input token, so getting it to hit is most of the game. The catch is it only works if you lay the prompt out for it. The cache matches from the start of the prompt, so static stuff , system prompt, tool definitions, the documents you keep re-sending , goes at the top, and whatever changes per request goes at the bottom. Get that backwards, put the user's question first, and you break the cache on every call. You pay full price and nothing tells you.
The discounts also look like they add up, and mostly they don't. Batch is half off, caching is another big cut, so batch plus caching should be huge , except the two often don't combine, and switching tiers can quietly switch caching off. OpenAI won't let you run batch and prompt caching together at all. Anthropic will, and stacked they get you near a 95% discount. So if you push a workload to batch or flex to save 50% and that provider drops caching to do it, you can come out paying more than before. Check that caching still applies on the tier you picked , the bill won't flag it.
Provider by provider
The cleanest attribution each provider gives you today, and the one thing to watch:
Provider | How you tag | Granularity | Watch out |
|---|---|---|---|
OpenAI | One project + project key per team; read via the Usage & Cost API | Team (project) | No per-call labels , log your own metadata next to |
Anthropic (Claude) | One API key per team/app; read back by key and actor via the Admin / Cost & Usage API | Team / app | Anything finer than team needs your own logging |
Azure OpenAI / Foundry | One deployment per use case, plus resource tags on top | Deployment ≈ feature | Project-level chargeback is still in preview |
AWS Bedrock | Tag IAM roles → read cost by | Team (IAM) / model | GA April 2026; a shared gateway role hides everyone behind one identity |
GCP Vertex AI | One project per team; per-call metadata labels for finer detail | Project (team) | Labels are real work to roll out and keep consistent |
Mistral | One workspace per team or environment, keys scoped to the workspace | Workspace | Billing is per workspace only |
If you want per call allocation, use the model through Vertex AI layer: the labeling also works with partner models ! |
Official cost/billing docs: OpenAI · Anthropic · Azure OpenAI · AWS Bedrock · Vertex AI · Mistral. Full setup for every provider is in the Costory LLM cost allocation docs.
Vertex AI cost allocation , isolate (project) or label (per call)
Vertex is the only provider that gives you a clean choice of both patterns. Isolate: one GCP project per team, but it needs zero code and the split lands in the billing export automatically. Label: pass metadata on every call for feature or customer-level detail. "Every call" is the catch: a label you forget to pass is spend you can't attribute later, and rolling labels through the SDK across every call site is real work to keep consistent.
Both signals , project and label , flow into the BigQuery billing export, which is where you actually read Vertex cost back at the grain you tagged. Two gotchas to price in before you commit: Gemini 3.x models bill their internal reasoning as output tokens, so a heavy-thinking workload costs more than the prompt and response sizes suggest; and regional endpoints carry a ~10% premium over global routing, so where you send the call changes the number you're allocating. Google's own reference is Add labels to Vertex API calls.
The gateway shortcut
If every call already passes through a gateway (LiteLLM, Portkey, Helicone, OpenRouter, Vertex, Bedrock), you get virtual keys per team and per-key budgets from one chokepoint , just remember its request log is a metering estimate, not a billing ledger, so reconcile it against the provider invoices.
Team vs feature vs customer
Team is the easy one. If you've got the emails behind the spend you can map each person to a team and roll the cost up from there. That's what we do in Costory. When you use labels, keep them at the lowest level that makes sense, usually the feature. Tag by feature, not by team. Then if a feature moves to a different team later you just remap it instead of re-tagging every call site.
Customer Name is worth the extra work when cost varies a lot between customers (which is our case 😅), or when you want to break it down by plan tier.
Unifying across providers
None of this helps if each provider stays in its own console. You've got six bills in six shapes, split by project, key, IAM role, deployment, label, or workspace, and to budget or report you need them in one place speaking the same language: same currency, same time grain, same idea of what a team is, then reconciled against the real invoices since the metering always drifts a bit.
That's what we built Costory to do, pull each provider's cost signal onto one team and feature model so a team's spend is one number instead of six. The attribution work above is what makes it possible.
LLM cost is repeating cloud's early mistake, and the fix is the same one that worked then: allocate now. Tokenmaxxing is easy. Valuemaxxing is the hard part. And you can’t value something you don’t measure.
FAQ
How do you do Anthropic cost allocation across teams?
Give each team its own Anthropic API key. The key name lands in the billing data, so the split happens with zero code , you read spend back by key and actor through the Cost and Usage API. It's the cleanest starting point of any provider. Anything finer than team needs your own per-call logging. Docs: Anthropic Cost & Usage API.
If you per call allocation, use Vertex AI the labeling also works with partner models !
How do you do OpenAI cost allocation by project?
Create one OpenAI project and project key per team, then read spend with the Usage and Cost API, grouping by project_id and model. The export carries no per-call labels, so for per-feature detail you log your own metadata next to response.usage at call time. Docs: OpenAI Usage & Cost API.
Should I use one GCP project per team or per-call labels for Vertex AI cost allocation?
Start with one project per team , it's zero-code and gives you a clean team split in the billing export immediately. Add per-call labels only where you need feature- or customer-level detail, since every call site has to set them consistently. Most teams ship the project split first and layer labels on the few workloads that need finer attribution. Docs: Add labels to Vertex API calls.
Can I allocate AWS Bedrock costs by team?
Yes. Bedrock has no per-call labels, so you allocate by caller identity: tag one IAM role per team, enable caller-identity allocation in a CUR 2.0 export, and read spend by the line_item_iam_principal column. The blind spot is a shared gateway role, which collapses every team behind one identity. It can be annoying to have to create that many IAM roles but it’s the only solution. Docs: Track Bedrock costs by caller identity.
Team, feature, or customer , which should I allocate by?
Team is the default and the easiest: map each key, project, or role to a team and roll spend up. Move to feature when you need unit economics, and tag at the feature level so you can remap ownership without re-tagging call sites. Add customer only when cost varies a lot between customers or you bill by plan tier.
Should I build LLM cost allocation myself or buy it?
Build the per-provider attribution yourself , it's mostly configuration, and this guide covers it. The harder part is unifying six billing shapes into one schema, one team axis, reconciled against real invoices, and keeping it current as keys and projects change. That ongoing normalization is where a tool like Costory earns its place. See the Costory LLM cost allocation docs.
FAQ