Usage and cost
Per-model, per-key, and over-time breakdowns, priced at the rate in force when each request ran.
Every request is metered with its model, token counts, and outcome, at an
accuracy an invoice could be produced from. You can read that in the console, or
through GET /v1/usage.
Reading usage
curl "https://api.inference.runatlas.com/v1/usage?group_by=model,api_key&bucket=day" \
-H "Authorization: Bearer $ATLAS_READ_KEY"Authenticates with a console session or a read-scoped
key (atl_read_). An inference key
(atl_live_) is not accepted here.
startstringISO 8601 timestamp, or a bare date meaning the start of that UTC day. Defaults to the start of the current UTC month.
endstringExclusive end of the period. Defaults to the start of the next UTC month.
modelstringRestrict to one model identifier.
api_key_idstringRestrict to one key, by its id (not its prefix).
group_bystringdefault: modelAny combination of model, api_key, and time, comma-separated. All
requested breakdowns come back from the one call.
bucketstringdefault: dayhour or day. Only affects the time breakdown.
A period may span at most 93 days. An end at or before start is refused.
The response
{
"organization_id": "...",
"period": { "start": "2026-09-01T00:00:00.000Z", "end": "2026-10-01T00:00:00.000Z", "bucket": "day" },
"filters": { "model": null, "api_key_id": null },
"requests": 18422,
"tokens": {
"backend_reported_input": 5218440,
"backend_reported_output": 1044210,
"backend_reported_reasoning": 0,
"generated_output": 1044210,
"delivered_output": 1041902,
"atlas_counted_input": 261200,
"atlas_counted_output": 52180,
"atlas_counted_requests": 920
},
"cost": { "input": "2.60922", "output": "1.56631", "total": "4.17553", "currency": "USD", "provisional": true },
"breakdowns": { "model": [ ... ], "api_key": [ ... ] },
"throttled": { "source": "rejection_counters", "total": 37, "by_limit_scope": [ ... ] },
"pricing": { "provisional": true, "billing_enabled": false, ... },
"cost_units": { "decimals": 14, "basis": "price_per_million_tokens_stamped_on_row" }
}Which token figure to use
There are several, and they are not redundant. Using the wrong one is the easiest way to produce a number that quietly disagrees with your invoice.
backend_reported_input / backend_reported_outputthe meter of recordThese are the figures you are priced on. Reported by the serving backend. If you are reconciling cost, use these and nothing else.
backend_reported_reasoningalready countedReasoning tokens, counted inside backend_reported_output. Never add the
two — you would double-count.
generated_output vs delivered_outputnot derivable from each otherWhat the model produced, versus what reached your client. They differ when a client disconnects mid-stream. You are billed on what was generated: the compute happened. Neither figure can be reconstructed from the other after the fact, which is why both are stored.
atlas_counted_*sample onlyAtlas's own independent token count, over a sampled fraction of requests
only — atlas_counted_requests tells you how many rows that fraction covers.
It exists so metering accuracy can be checked against the backend's figures.
It is not a billing figure and does not cover all traffic.
Cost is stamped, not recomputed
Each usage row carries the price that was in force when the request ran. Cost figures are projected from that stamped price, never repriced by today's published price. If Atlas changes a model's price mid-month, your figures for earlier in the month do not move.
Cost strings carry 14 decimal places, because a per-million-token price applied to a handful of tokens is a very small number and rounding it early loses money in one direction consistently. Round for display, not for storage.
If a period mixes currencies, cost is null and mixed_currency: true is
set, rather than summing figures that cannot be added.
Throttling
"throttled": {
"source": "rejection_counters",
"total": 37,
"by_limit_scope": [{ "limit_scope": "tokens", "model_identifier": "atlas-mid-1", "count": 37 }]
}Rate-limited requests are counted, not metered — a rejection writes no usage row — so these figures come from admission counters. They are recent and approximate where the metered figures are durable and exact.
"source": "unavailable" with "total": null means no counter source is
wired, not that nothing was throttled. Zero is never reported for "we did
not look".
Breakdowns
breakdowns carries one array per group_by you asked for, each entry a key
plus the same totals shape:
"model": [
{ "key": { "model_identifier": "atlas-mid-1", "model_id": "..." }, "requests": 14200, "tokens": { ... }, "cost": { ... } }
],
"api_key": [
{
"key": {
"api_key_id": "8f2c1d5e-...",
"api_key_label": "production",
"api_key_prefix": "atl_live_9f1c0f6e"
},
"requests": 9100, "tokens": { ... }, "cost": { ... }
}
],
"time": [
{ "key": { "bucket_start": "2026-09-08T00:00:00.000Z" }, "requests": 640, "tokens": { ... }, "cost": { ... } }
]Each key carries the label and non-secret prefix you know it by, alongside the
id the api_key_id filter takes. Both are null for the unattributed group,
which has no key on the request.
The per-key breakdown is only as useful as your key hygiene — one key per deployed service is what makes it answer "which system is spending this?", and the label is what makes the answer readable.
Reconciling
For row-level records rather than aggregates — one row per request, with the price stamped on it — use usage export.