Research-backed calculator guide
AI Cost Attribution by Customer: From Shared API Keys to Gross Margin
A practical method for attributing AI spend to customers, allocating shared infrastructure, reconciling invoices, and calculating customer-level gross margin.
If one API key serves every tenant, the provider invoice cannot answer the question finance actually asks: which customers consumed the AI budget, and did the revenue from each customer cover the cost to serve them? AI cost attribution by customer is the process of answering that question with a traceable ledger rather than an even split or a dashboard total.
The useful unit is not just “tokens per customer.” It is a customer cost-to-serve record that separates directly observed request costs from allocated shared costs, ties every amount back to a usage event or a published driver, and can be reconciled to the invoice. Once that record is stable, customer gross margin is straightforward:
Customer gross margin = customer revenue − customer cost-to-serve Gross margin percentage = (revenue − cost-to-serve) ÷ revenue × 100
This guide uses illustrative rates in its worked example. They are assumptions for demonstrating the method, not a current vendor quote. Replace them with the rate card and invoice units that apply to your account.
Quick answer
Build a request ledger with one row per model, embedding, retrieval, tool, or agent step. Put a durable customer_id, feature, environment, provider, model, usage quantities, retry status, and request or trace ID on every row. Calculate direct cost from the usage actually returned by the provider. Then add shared pools—such as a gateway, GPU cluster, vector store, or platform service—using a documented driver such as request share, token share, GPU-hours, or GB-days.
At month end, reconcile the sum of ledger costs to the provider invoice. Investigate the difference instead of silently spreading it. If a price change, late invoice, retry, or missing event remains, post a labelled true-up. Keep unallocated or centrally funded costs visible as exclusions. Only then compare each customer’s cost-to-serve with revenue to calculate margin.
This approach avoids two opposite errors. A single shared key is too coarse for customer economics. A mathematically precise allocation that hides assumptions is not finance-grade either. The goal is a repeatable estimate whose inputs, drivers, and uncertainty can be reviewed.
What belongs in customer-level AI cost
Start by defining the cost boundary. For many AI SaaS products, customer AI cost has four layers:
- Direct model and tool usage. This includes input and output tokens, cached or reasoning tokens where separately billed, image or audio units, embeddings, reranker calls, web-search calls, and paid tool invocations caused by that customer’s request.
- Shared inference infrastructure. A self-hosted GPU, managed endpoint, model gateway, or orchestration service may handle requests for many customers. Its cost needs a usage driver rather than an invented customer tag.
- Shared data services. Vector storage, retrieval, ingestion, cache storage, and network or data-transfer charges can be direct, shared, or mixed. Define the meter before allocating it.
- Operating exclusions or centrally funded overhead. Evaluation runs, development environments, support, safety review, and a platform team may be treated as product overhead instead of customer COGS. That is a policy choice, not a missing number. Keep it visible and state whether it is included in margin.
The distinction between direct and shared cost matters. If the same request produces a model charge and a gateway charge, do not count the gateway’s provider fee twice. Give each pool a unique ledger category and a source invoice or internal cost record.
A useful event schema can include event_id, trace_id, customer_id, feature_id, environment, provider, model, operation, input_tokens, output_tokens, cached_tokens, reasoning_tokens, tool_units, retry_of, usage_timestamp, and rate_card_version. OpenTelemetry’s GenAI conventions document standard fields for operations, providers, and usage; its guidance also says input usage should include cached tokens when applicable and reasoning output should be included in output tokens. Use those conventions where they fit, then add business dimensions such as customer and plan. [1]
Do not put raw prompts, private customer text, or email addresses into a cost ledger unless your privacy policy permits it. A stable tenant identifier or pseudonymous key is normally enough for finance aggregation. The ledger’s job is to join cost to a customer, not to reproduce the conversation.
A practical attribution method
1. Capture identity before the model call
Attach customer and feature context at the start of the request or trace, not after the response. Propagate the same context through retries, tool calls, retrieval, and child-agent spans. If a background job is legitimately shared, mark it as shared and route it to an allocation pool rather than guessing at a customer.
The identity field needs a defined ownership rule. A customer can be the paying tenant, while an end user is the person making a request. Store both when they answer different business questions. For margin, aggregate by paying tenant. For product behavior, a user-level slice may be useful. Langfuse documents a similar pattern: propagate a userId across observations so usage cost and trace metrics can be aggregated by user, with values kept as strings and attached early enough to cover child observations. [3]
2. Record usage, not just estimated tokens
Use provider-returned usage whenever available. Store each billable unit separately instead of reducing the response to one token total. This is important when a provider distinguishes ordinary input, cached input, output, reasoning output, audio, image, or search units.
For each usage type, calculate:
direct cost = billable units ÷ rate-card unit divisor × price per unit
A rate-card record should include provider, model or service, usage type, currency, effective date, unit divisor, price, and source. The rate_card_version on each event makes a later audit possible if the provider changes prices. Never apply a current price retroactively to historical events without recording that restatement.
Langfuse’s documentation illustrates a defensible implementation pattern: cost can be ingested from an LLM response or inferred from a model definition, with usage types and prices stored separately. It also supports custom model definitions and pricing tiers for request conditions. [2] That is a useful design principle even if you build the ledger yourself: the rate card is data, not a hard-coded constant buried in application logic.
3. Allocate each shared pool with one driver
Choose the driver that best reflects consumption and publish the rule before looking at the result. Examples include:
- Gateway or orchestration: allocate by billable request count, weighted request count, or token share.
- GPU inference: allocate by measured GPU-hours, occupied accelerator-seconds, or a documented proxy such as generated tokens when runtime data is unavailable.
- Vector storage: allocate by customer GB-days; allocate shared indexes by query share or indexed-document share.
- Evaluation and safety: allocate directly when a run belongs to one customer; otherwise keep a product pool or split by evaluation volume.
- Reserved capacity: assign the committed baseline using the capacity policy, then allocate spillover from actual usage. Do not make a reservation look like a variable request charge.
The FinOps Foundation separates allocation strategy, tagging or metadata strategy, and shared-cost strategy. It notes that fixed, proportional, and proxy-metric allocations are all possible, and that some organizations may deliberately keep a shared cost in a central budget when allocation would not improve decisions. [5] Apply that discipline to AI: a centrally funded platform pool is acceptable when labelled, reviewed, and excluded consistently from the customer margin view.
AWS Bedrock provides a concrete provider-side option for some workloads. Its application inference profiles carry cost-allocation tags into Cost Explorer and Cost and Usage Reports for InvokeModel and Converse, while the documentation says those profiles are not supported for Responses and Chat Completions. That is a useful direct allocation path where it applies, but it is not a universal solution for every provider or API surface. [4]
4. Reconcile and true up
At the close of a billing period, compare three numbers:
- the provider invoice or cloud cost-and-usage export;
- the sum of directly attributed ledger events; and
- the sum of shared pools and centrally funded exclusions.
The reconciliation difference is not automatically customer cost. Classify it. Common causes are tax, credits, minimum commitments, invoice timing, unlogged retries, asynchronous jobs, price changes, or a missing provider meter. Add a suspense category until the cause is known. If you must distribute a residual, record the driver and mark it as a true-up with a reason and approval date.
A practical control is to report allocation coverage alongside cost. For example, show direct plus shared costs with a customer or approved pool, divided by total AI-related invoice cost. Also show the unallocated dollar gap and the age of the data. High coverage is not proof of accuracy, but a falling unexplained gap is evidence that the process is becoming more useful.
Worked cost example
Assume a one-month SaaS ledger for three customers. The rates below are intentionally simple assumptions: model input at $2 per million tokens, model output at $8 per million tokens, and the listed embedding or tool amount already normalized to dollars. They are not a vendor quote and should be replaced with your dated rate card.
| Step / pool | Assumptions and inputs | Customer A | Customer B | Customer C | Output or allocation rule |
|---|---|---|---|---|---|
| Direct model input | 2.0M / 8.0M / 1.0M input tokens × $2/M | $4.00 | $16.00 | $2.00 | Usage event × input rate |
| Direct model output | 0.5M / 2.0M / 0.25M output tokens × $8/M | $4.00 | $16.00 | $2.00 | Usage event × output rate |
| Direct embeddings/tools | Reconciled request-level amounts | $1.50 | $3.00 | $0.50 | Direct customer assignment |
| Shared gateway | $120 pool; request shares 42%, 42%, 16% | $50.40 | $50.40 | $19.20 | Request-share driver |
| Shared GPU | $180 pool; measured GPU-hours 20, 30, 10 | $60.00 | $90.00 | $30.00 | GPU-hour driver |
| Shared vector store | $60 pool; GB-days 100, 150, 50 | $20.00 | $30.00 | $10.00 | GB-day driver |
| Customer cost-to-serve | Direct rows + allocated shared rows | $139.90 | $205.40 | $63.70 | Margin cost basis |
| Monthly revenue | Contracted revenue for the same month | $1,000.00 | $1,200.00 | $300.00 | Billing system input |
| Gross margin | Revenue − cost-to-serve | $860.10 | $994.60 | $236.30 | Revenue less cost |
| Gross margin percentage | Gross margin ÷ revenue × 100 | 86.01% | 82.88% | 78.77% | Customer margin output |
The table makes the assumptions inspectable. Customer B generates the largest direct usage and receives the largest GPU and storage allocations. Customer C has the smallest absolute cost, but its lower revenue makes its margin percentage the weakest of the three. That conclusion depends on the chosen boundary: a $90 platform-support pool was not included. If finance decides it belongs in cost of revenue, add a stated driver, such as request share, and recalculate all three customers.
The next control is invoice reconciliation. Suppose the provider invoice is $44.00 higher than the directly recorded model, embedding, and tool rows because a late batch job and retry charges arrived after the first export. Do not quietly add $14.67 to each customer. Link the late batch to its customer if possible. If it is genuinely shared, place it in the appropriate pool. If the owner cannot be established by close, post $44.00 unallocated—pending true-up and show how the margin changes when it is resolved.
For a broader monthly spend model, use the AI Agent Cost Calculator | Model Full Monthly Spend. For the estimate-to-invoice control, the AI API invoice reconciliation calculator is the more relevant companion. Those tools answer different questions from this ledger: one forecasts system spend, while the other tests actual-versus-estimated totals.
How to make the numbers trustworthy
Version the policy. Store the allocation driver, effective date, owner, and review cadence beside the result. A request-share rule can be reasonable in January and misleading after a feature changes its token profile.
Keep direct cost direct. Do not allocate a customer’s own model call through a shared pool merely because the API key is shared. The key is a credential boundary; request telemetry is the economic boundary.
Separate showback from chargeback. Publish one or two months of customer and feature cost as showback while teams challenge missing events and drivers. Move to pricing or chargeback decisions only after reconciliation is stable. A precise-looking number with an unresolved invoice gap should not set a customer price.
Track retries and background work. A failed request can still incur cost. Store retry_of and attempt status, then decide whether the retry belongs to the originating customer, a product reliability pool, or a provider incident pool. The decision should be consistent across periods.
Protect margin data. Customer cost and gross margin can be commercially sensitive. Restrict row-level access, retain only the identifiers needed for the decision, and provide aggregated views for product teams.
Use a clear exclusion list. State whether training, development, evaluations, safety review, support, discounts, credits, reserved capacity, and taxes are included. A gross-margin number without a cost boundary invites false comparisons across plans.
If a customer-level attribution project also needs to quantify the operational benefit of tracing and anomaly detection, compare the cost of instrumentation and review with the expected avoided waste using the AI observability ROI calculator. Keep that ROI calculation separate from customer COGS so an observability investment is not accidentally charged to the tenant that happened to trigger an alert.
Run your scenario
Turn this framework into an editable estimate.
Use dated, source-linked assumptions and see cost per request, successful task and month.
FAQ
What is AI cost attribution by customer?
It is the assignment of AI-related cost to the paying customer or tenant that caused it, using request-level usage for direct charges and a documented allocation driver for shared charges. It is more granular than an account invoice and more defensible than dividing total spend by customer count.
How do you calculate AI cost per customer?
Sum each customer’s direct model, tool, embedding, retrieval, and other billable request costs. Add the customer’s share of approved shared pools such as gateway, GPU, and vector storage. Reconcile the total to the invoice, classify the difference, and then compare the resulting cost-to-serve with that customer’s revenue.
Should shared GPU cost be divided equally among customers?
Usually not when usage data is available. GPU-hours, occupied accelerator-seconds, or a documented proxy tied to workload are generally more informative than an equal split. An equal split can still be a deliberate policy for a small shared service, but label it, document why it is useful, and review the choice when customer usage changes.
What metadata is required for LLM cost attribution by customer?
At minimum, capture a stable customer or tenant ID, feature or product surface, environment, provider, model, operation, usage quantities, timestamp, request or trace ID, retry status, and rate-card version. Add plan, region, and data-residency fields when they change pricing or reporting. Avoid collecting prompt content solely to allocate cost.
How do you handle a request that fails and retries?
Record each billable attempt and link it to the original request. Attribute the actual provider charge once, then apply your policy consistently: customer cost when the customer caused the work, or a reliability/shared pool when the retry resulted from a platform or provider fault. The ledger should make that choice visible rather than hiding retries inside an average.
Can customer gross margin be calculated from tokens alone?
Not reliably for a full cost-to-serve view. Tokens can cover direct model usage, but shared GPU time, retrieval, storage, gateway, evaluation, and support may also matter. Tokens may be a reasonable proxy for one pool when runtime data is unavailable, but the proxy and its limitations should be shown beside the margin result.
How often should allocation rules be reviewed?
Review them at least when provider prices, models, architecture, plans, or customer usage patterns change, and set a regular quarterly review for shared pools. Reconcile monthly so a broken mapping does not survive until the next annual pricing exercise.
Primary sources checked
Pricing and product behavior can change. These sources support the time-sensitive claims in this guide; verify current provider terms before committing spend.