Get per-project usage
The per-project meter — the re-billing view (A11/C12/P3). Aggregates the project's usage over an optional [from, to] window, bucketed by a single dimension. Costs are the billing-grade cost_usd the runtime freezes at write time; null means nothing in the bucket was priced (never that it was free). Only managed providers are priced (on the runtime), so cost reflects managed usage; BYOK usage carries no LLM cost.
Every bucket also carries components — the amounts actually measured. The token counts describe LLM usage alone, so that is where a storage, api_request or compute_execution bucket reports its real quantity instead of zeroed token fields.
The rollup can also be narrowed to one session or one end user before it is bucketed. That is the question no dimension answers: group_by splits the project's whole spend, so "what did this conversation cost, per day" and "what has this end user spent across every session" are reachable only by narrowing. The narrowings intersect, apply to the totals as well as the buckets, and are echoed back complete — null for each one not applied — because a rollup of zeros is otherwise indistinguishable from a project that spent nothing.
Request
- Base URL: https://api.naturali.ai
- URL: https://api.naturali.ai/v1/projects/{project_id}/usage
- Auth: one of:
- HTTP bearer
- OAuth 2 (authorization code, authorization URL https://api.naturali.ai/authorize, token URL https://api.naturali.ai/token, scopes: mcp:access)
Query parameters
Dimension to bucket by. day buckets on the event's UTC calendar day; the others on the matching id. model buckets on the model and the provider that served it, so one model name served by two providers is two groups (see ai_provider_id). ai_provider buckets on the provider the spend was billed against — a routed generation's serving target, or the agent's pinned provider — which is the total a per-provider reconciliation wants, without summing the model dimension by hand. run buckets on the orchestration run an event belongs to; work that runs no orchestration collapses into the single null bucket, so the bucket count there is not a count of runs. session and actor bucket on the conversation and the end user behind the spend — what a customer re-billing their own users charges each of them for; traffic with no end user behind it collapses into the single null bucket on both. source buckets on what the spend was incurred for (eval, eval_judge), which is how verification spend is told apart from the traffic serving real users; ordinary traffic carries no source and is the null bucket.
Narrow the rollup to one meter type (llm_tokens, compute_execution, api_request, storage, tool_execution). Omit to include every meter. Useful with group_by=model, whose dimension otherwise mixes model ids with platform SKUs. An unrecognized value yields an empty rollup, not an error.
Narrow the whole rollup — every bucket and the top-level totals alike — to one session's traffic. Combines with group_by: group_by=day&session_id=... is one conversation's spend per day, group_by=model the same spend split by model. This is the figure behind the usage roll-up a single session read carries, broken down. An id naming no session in this project yields an empty rollup, never the project total.
The same narrowing, for one end user across every session they appear in — what a customer re-billing their own users charges each of them for. An id naming no actor in this project yields an empty rollup, never the project total.
Narrow to one agent's traffic, across every session, run and trigger that dispatched it.
Narrow to the spend billed against one provider record — a routed generation's serving target, or the agent's pinned provider.
Narrow to the events one orchestration run metered.
Narrow to the runs of one orchestration — the ones it started itself, never the subtree a loop or sub-orchestration node started under it, which is metered against the child orchestration where it was incurred. Additive: summed across a project's orchestrations the figures reach the project total exactly once.
Narrow to one generation's events. A generation writes more than one when it meters several dimensions, such as tokens and compute.
Narrow to the events recorded under one trace.
Narrow by what the spend was incurred for — eval and eval_judge are verification spend. Ordinary traffic carries no source, so it cannot be selected by this filter; omit the filter for everything.
Narrow to the spend one trigger initiated. Matched as recorded rather than resolved, so it still selects the spend of a trigger that has since been deleted.
Narrow to one caller-supplied action label, for per-action spend. Matched as recorded, like trigger_id.
Optional extras to compute. The only value is distinct, which adds the distinct object — one count per kind of entity the window touched. Opt-in because each counter costs the window another sort, so a caller who does not ask keeps the cheap response whatever the event table grows to. Any other value is a 400.
Inclusive lower bound (ISO-8601) on event time. Omit for no lower bound.
Inclusive upper bound (ISO-8601) on event time. Omit for no upper bound.
Results per page, 1 to 100 (default 50). Above 100 it is clamped; below 1 or not an integer it is 400.
Results to skip. Negative or not an integer it is 400.
Response
Usage for the project.
Example response
{
"project_id": "proj_V1StGXR8Z5jdHi6B",
"group_by": "model",
"distinct": {
"generations": 812
},
"event_count": 1280,
"cost_usd": 1.23,
"groups": {
"data": [
{
"key": "nova-lite-v1",
"ai_provider_id": "aip_V1StGXR8Z5jdHi6B",
"cost_usd": 1.23,
"event_count": 42,
"input_tokens": 120000,
"output_tokens": 45000,
"cached_tokens": 30000,
"total_tokens": 165000,
"components": [
{
"component": "gb_day",
"unit": "gb_day",
"quantity": 0.4
}
]
}
],
"total": 12,
"limit": 50
},
"input_tokens": 120000,
"output_tokens": 45000,
"cached_tokens": 30000,
"total_tokens": 165000,
"components": [
{
"component": "gb_day",
"unit": "gb_day",
"quantity": 0.4
}
]
}Changes
No recorded changes to this operation across all 1 revision of this API.