AI Spend Attribution and Chargeback
The identity layer every AI FinOps practice needs — why a provider invoice has no feature, team, or GL account attached to any dollar, and the four-layer fix that gives it one.
Executive summary
“What did we spend on AI last month” is a harder question than it should be, because a provider invoice is a single number with no identity attached to it — no feature, no team, no department, no GL account. Closing that gap is not one fix but four layered ones: tag every call with identity at the moment it's made, normalize that identity across every provider you actually use, map it onto the chart of accounts finance already runs, and export it in a format the rest of your FinOps tooling already understands. Skip any one layer and the chain breaks — a GL tag on an unattributed call has nothing to attach to, and a chargeback report that only covers one provider isn't a real chargeback report. This report covers all four, in order.
5
request-layer headers: feature, department, session, GL account, user
9
providers normalized into one attribution and chargeback view
3
export formats: generic CSV, NetSuite CSV, FOCUS-aligned CSV
FOCUS 1.2
the open billing spec version Cognocient targets and tests against
I. The invoice has no identity
A single provider API key is easy to provision once and reuse everywhere — which is exactly why it ends up authenticating calls from a support chatbot, an internal search feature, an experimental agent workflow, and a batch summarization job, all in the same billing period. The invoice that arrives at the end of the month reports a model name and a token count. It says nothing about which of those features generated the spend, and nothing about which team owns the cost, because the provider never had visibility into your application's internal routing in the first place.
That gap compounds every month it goes unaddressed. By the time someone tries to explain a spend increase to finance, the honest answer is often “we don't know which feature drove it” — not because nobody cares, but because nothing in the request path ever recorded the context needed to answer the question. And the problem doesn't stay single-provider for long: one feature ships on one model because that's what the team knew at the time, a second moves to a different provider because it handles a specific task better, a third routes to a faster or cheaper model for latency-sensitive work. Each decision is reasonable on its own. Each one also adds a provider console with its own invoice and no connection to the others, so “what did we spend, total, across everything” becomes a question that requires logging into three or four consoles and adding numbers by hand.
II. Why attribution has to happen at the request layer
Three approaches to this problem look reasonable at first and fail for structural reasons, not lack of effort. Per-API-key tagging — issuing a separate provider key per feature or team — works cleanly as long as every key maps to exactly one feature, and breaks the moment a key gets shared across two product surfaces or a shared backend service fans out to multiple features using the same credential. Manual spreadsheet reconciliation — exporting the invoice and cross-referencing it against deploy logs or institutional memory — is a legitimate stopgap for a team's first month of AI spend, and does not scale past it: the reconciliation is stale the moment it's finished and has to be redone by hand every billing cycle. Billing-layer tagging — looking for a tagging feature on the provider's billing dashboard, the way you'd tag a cloud resource in AWS or GCP — doesn't exist for API usage, because the invoice reports model and token count, not which feature or team the call served. There is no billing-layer setting that recovers information the provider never captured to begin with.
The fix is to tag identity at the moment the call is made, not to reconstruct it afterward from a bill that was never built to carry it. Routing every call through a proxy in the request path makes this possible: attribution headers — X-Cost-Feature, X-Cost-Department, X-Cost-Session, plus GL-account and user-level tags — are read straight off the request before it's forwarded on, so the call is attributed the instant it happens. Because the tagging happens on the call itself rather than on the shared key that authenticates it, one key can safely serve any number of features without losing attribution.
→ Full mechanism, including the complete header list: How Do You Attribute AI API Costs by Feature and Team?
III. One view across every provider you actually use
Every provider console does one job well: show you spend on that provider. None of them have visibility into what you're spending elsewhere, because each one is optimizing its own billing experience, not a cross-provider view — asking a provider console to show combined spend across competitors is asking it to do something fundamentally outside its purpose. Exporting each console's invoice and combining them in a spreadsheet works for a single retrospective look, but the combined view is stale the moment it's finished, the same limitation as any other manual reconciliation.
Routing every provider through one proxy layer solves this structurally instead of manually. Nine providers — OpenAI, Anthropic, Google Gemini, Mistral, Groq, Together AI, Azure OpenAI, AWS Bedrock, and Google Vertex AI — proxy through a single base URL, with the provider detected automatically from the model name: no separate SDK, no re-authentication, no new keys to manage per provider. Every call, regardless of which provider ultimately serves it, is recorded in the same database with the same attribution headers and the same budget enforcement applied consistently. Moving a feature from one provider to another for a cost or quality reason becomes a one-line model-name change — the attribution, budgets, and chargeback mapping around that feature keep working without any reconfiguration.
→ Full mechanism, including per-provider setup: One Cost Dashboard for OpenAI, Anthropic, Gemini, and Every Other Provider You Use
IV. From attribution to chargeback
Attribution tells you which feature or team a call belongs to. Finance needs the next step: mapping that to a specific GL account, cost centre, and business unit so the spend can be posted directly into the ERP as a journal entry, not just displayed on an engineering dashboard. Asking engineering to estimate departmental usage share after the invoice arrives has an accuracy problem — nobody has a precise memory of which team's features drove which portion of last month's calls — and a timing problem that compounds every cycle, since the allocation has to be rebuilt from scratch every billing period by a person.
The same request-layer mechanism that solves attribution solves this too, extended with headers finance actually needs: X-Cost-Department carries the business department, and X-Cost-GL-Account carries the GL account code matching your chart of accounts. A dedicated chargeback view shows a department breakdown — total spend, call count, top features — plus a GL Mappings tab that maps each department to the accounts finance already posts journal entries against. The same mechanism extends to B2B chargeback: a client's account ID as the department value produces a per-client line-item report suitable for inclusion in a client invoice.
→ Full mechanism, including GL Mappings and NetSuite export: AI Spend Chargeback: Mapping Every API Call to a GL Account Automatically
V. Exporting into the tools finance already runs
FOCUS — the FinOps Open Cost and Usage Specification, maintained by the FinOps Foundation — is an open, vendor-neutral schema for billing data. AWS, Azure, GCP, and most SaaS and API vendors ship cost data in their own proprietary shape; FOCUS is the shared format that lets a FinOps platform show one unified view without a custom parser per vendor. Most teams already have, or are building, a FinOps practice around cloud infrastructure using tools that expect FOCUS-shaped data — an AI cost export that only speaks its own bespoke CSV forces a second, disconnected reporting pipeline instead of plugging into the one that already exists.
“FOCUS-aligned” is a claim many vendors make without saying what it was checked against. Tested against FOCUS's own official validator, Cognocient's export meets FOCUS 1.2 — every genuine rule violation found has been resolved, with a small remaining set of reported failures individually investigated and confirmed to be validator-engine false positives, not real gaps. FOCUS 1.1 is currently untestable, since the official validator dropped support for checking against it, so no 1.1 conformance claim is made either way. FOCUS 1.3, a newer and stricter version of the spec, is not yet met. Stated this way instead of as a badge, because real conformance against a living specification is a result from a specific test run against a specific validator version — not a permanent, binary state.
→ Full validator results, version by version: FOCUS for AI Spend: What the Open Billing Standard Covers
VI. The identity layer, together
None of these four layers is optional and none substitutes for the others. Attribution without multi-provider normalization gives you accurate feature-level cost on one provider and nothing on the rest. Multi-provider normalization without GL mapping gives finance a clean total with no way to post it. GL mapping without a standard export format gives finance a chargeback report that has to be manually re-keyed into every other tool they run. Run together — tag identity at the call, normalize it across providers, map it to the chart of accounts, export it in a format the rest of FinOps already understands — a provider invoice's single opaque number becomes a line-item breakdown finance can act on the day the billing period closes, not weeks later.
Give your AI spend an identity
Free forever on one provider. No credit card, ever. Attribution, multi-provider tracking, and chargeback-ready exports from day one.
Start for free →Sources & further reading