Provider cost, AI gateway and usage events
One monetary source and allocation that preserves the total
Cost by customer, user and model
Pricing, alerts and AI agent
What it solves
- AI cost matches the provider's invoice, day by day.
- Every unit of cost attributed to customer, user and model, or flagged as unattributed.
- Heavy users and plans with negative margin surface on their own.
Business questions it answers
Ask your agent these questions once the case is live.
What you need
- Access to the providers' or AI gateway's cost and usage APIs
- The user and customer identifier recorded on every call
- Plans and prices from billing, and the declared exchange rate
What you get
- A user x model x day consumption table, with tokens, requests and cost
- Cost by customer and plan against revenue, per month
- Alerts for users and customers above the limit
- An AI agent that answers about cost from the right monetary source
Where to activate
Cost to serve by plan against MRR, to review limits, credits and price.
A daily alert of users and customers above the limit or the p99, with the model that drove the cost.
Answers how much each customer and model cost from the monetary source, and warns when a day hasn't closed yet.
Cost APIs have limits (they don't group user and model together, close the day in UTC, paginate slowly) and the allocation of shared cost has to be designed. Start with the monetary source and add attribution afterwards. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.
The provider bills by project or key, the analytics tool knows which user made the call, and the two don't match. Analytics prices every token as new and inflates cost; the cost API doesn't return user and model in the same query; the provider's day is UTC. And shared cost, such as model infrastructure, has no owner. The result is a per-customer cost that doesn't tie to the invoice and a price nobody can defend.
How it is usually done, and the rule
Each row is a mistake that already happened in practice.
Cost in money comes from the invoice or the cost API of the provider or gateway. Analytics events say who, in which project and with which tool, but don't work as a value: in a real base, analytics sent every token as new, without the prompt cache discount, and inflated cost several times. Use analytics only to attribute, and reconcile both sources by day.
Before trusting a day, check that the sum of cost by user rebuilds the model's cost for the day (for example, 99% or more, with an absolute tolerance for models with negligible cost) and that the users collected cover the total reported by the API. A day that doesn't close raises an alarm and is collected again.
Report APIs usually group by model or by user, not both. Query cost by model for the day, as the reference, and, for each model, cost by user. Write with a merge on date, product, model and user, so a day can be collected again without duplicating.
Cost with no user at the source (infrastructure, batch calls, fixed provider charges) is allocated by a declared usage weight: requests, tokens or events. The allocated sum equals the original cost. Whatever has no traceable usage that day goes to a visible unattributed bucket, never spread silently.
The same user shows up as email, login id and app id. Bring them all to one canonical id and sum the fragments. Model names change with versions and dates: normalize to a canonical model with the provider alongside. Flag development users and check, on every load, the map from API key to product: a swapped key and label raise no error.
The team's own usage (tests, internal agents, development) is a company expense, not product cost. Put it on its own line and take it out of per-customer cost and plan margin.
The provider closes the day in UTC, which covers parts of two São Paulo days. For daily views, declare which day you are using; monthly, the difference is small. Never mix UTC-day and local-day columns in the same sum.
Most API cost is billed in dollars. Keep the amount and the source currency, convert at the rate of the accrual day in a single layer, and never sum amounts in different currencies. FX exposure = sum of the source amount in USD.
Sum the cost of the customer's users in the month and compare it with their MRR and the credits they bought. Show the cost distribution per user in percentiles (p50, p75, p90, p99): the average hides heavy users. A simple alert threshold works, such as a user spending more than US$ 20 in a day.
Usage events sent by the product can arrive twice. Deduplicate by a hash of the event content before summing tokens, and keep call retries as their own metric: a retry consumes tokens and delivers no answer.
Which source answers each question
Money on one side, attribution on the other, reconciled by day.
Definitions
Pitfalls that already happened
Cost from analytics events treated every token as new. In one month, the provider recorded most of a model's tokens as cached, and analytics priced all of them as new input.
Value always from the cost API; analytics only to attribute.
The analytics events load reported success while picking up only a few minutes of data in about a third of runs, and whole days disappeared with no alert.
Reconcile by day with the monetary source and alarm when coverage drops.
The product was defined by the API key, and one product's key saved under another's label sent consumption to the wrong product, with no error at all.
Validate the key-to-product map on every load.
The source-currency amount was removed for looking duplicated, and with most API cost in dollars nobody could state the FX exposure.
Keep amount and source currency paired.
Usage events arrived repeated through the message queue, and token consumption for some flows showed up doubled.
Deduplicate by a hash of the event content.
Acceptance test
The case is done when every item passes.
- For each day and model, the sum of cost by user rebuilds at least 99% of the model cost reported by the provider.
- Attributed cost + unattributed cost + internal usage = total cost for the day, with no difference.
- Total cost for the month matches the providers' invoices (difference under 1%, explained by FX).
- No user appears with two different ids on the same day.
- Collecting a day again doesn't change the total of other days or duplicate rows.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
AI cost by customer - The money value comes from the provider's or gateway's cost API. Analytics events are only for attributing user and project, never as a value. - Day cost = attributed + unattributed + internal usage. - Shared cost is allocated by a declared usage weight (<weight>). The allocated sum equals the original. - The team's internal usage doesn't go into per-customer cost or plan margin. - The provider's day is UTC. Say which day you are using. - Amounts in the source currency are never summed across currencies. Conversion at the accrual day's rate. - Users and models are in canonical ids. - Per-customer cost is compared with the customer's MRR and credits. Use percentiles, not only the average. - If a day hasn't passed the completeness lock, say the day hasn't closed yet. Per-client exceptions: - <client>: plan <plan> includes <n> AI credits per month. - <client>: project <project> is internal usage.
Build the "AI cost by customer, user and model" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/saas/custo-ia-por-cliente.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
When each send or generated document has its own LLM cost record, sum by delivery and compare with the unit price.
A daily series of cost and savings attributed to each model or prompt change, to prove the change paid off.
Human interventions and retries per conversation, to know whether the cheaper model is hurting service.