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 (cache_control); write 1.25–2×, cheap reads

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 response.usage for per-feature

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 line_item_iam_principal in CUR 2.0, or use Application Inference Profiles

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.

import vertexai
from vertexai.generative_models import GenerativeModel

vertexai.init(project="my-project", location="us-central1")
model = GenerativeModel("gemini-3.1-flash-lite")

response = model.generate_content(
    "What is Costory?",
    labels={"team": "search", "feature": "ai-search", "customer": "acme"},
)

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

Frequently Asked
Questions

Frequently Asked
Questions

Frequently Asked
Questions

How secure is my data, and what exactly do you access?

€250 / month, is that real?

My tags are inconsistent, do I need to clean them up first?

How fresh is the data, and can I use Costory for real-time alerts?

What if you don't natively support one of my data sources?

How secure is my data, and what exactly do you access?

€250 / month, is that real?

My tags are inconsistent, do I need to clean them up first?

How fresh is the data, and can I use Costory for real-time alerts?

What if you don't natively support one of my data sources?

Ready to get started?

Costory makes sure you only spend time on FinOps when it matters, and gives you the answers to act fast.

Feels Familiar

Import your CSP and LLM provider metadata via Terraform.

Privacy & Security

No agents. No code. No sensitive data. Just billing and usage exports.

Try now, pay later

14-day free trial, then subscribe to a flat fee via credit card, GCP or AWS Marketplace.

Ready to get started?

Costory makes sure you only spend time on FinOps when it matters, and gives you the answers to act fast.

Feels Familiar

Import your CSP and LLM provider metadata via Terraform.

Privacy & Security

No agents. No code. No sensitive data. Just billing and usage exports.

Try now, pay later

14-day free trial, then subscribe to a flat fee via credit card, GCP or AWS Marketplace.

Ready to get started?

Costory makes sure you only spend time on FinOps when it matters, and gives you the answers to act fast.

Feels Familiar

Import your CSP and LLM provider metadata via Terraform.

Privacy & Security

No agents. No code. No sensitive data. Just billing and usage exports.

Try now, pay later

14-day free trial, then subscribe to a flat fee via credit card, GCP or AWS Marketplace.