Atlas Inference

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.

startstring

ISO 8601 timestamp, or a bare date meaning the start of that UTC day. Defaults to the start of the current UTC month.

endstring

Exclusive end of the period. Defaults to the start of the next UTC month.

modelstring

Restrict to one model identifier.

api_key_idstring

Restrict to one key, by its id (not its prefix).

group_bystringdefault: model

Any combination of model, api_key, and time, comma-separated. All requested breakdowns come back from the one call.

bucketstringdefault: day

hour 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 record

These 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 counted

Reasoning tokens, counted inside backend_reported_output. Never add the two — you would double-count.

generated_output vs delivered_outputnot derivable from each other

What 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 only

Atlas'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.

On this page