# AtmoRouter — Usage & request timing

Source: https://atmorouter.dev/docs/observability

Use the dashboard Usage page or `GET /api/dashboard/usage?range=24h` with a login session. Responses contain the latest 200 requests in the selected range, newest first. An inference key does not grant access to dashboard history.

## Timing fields and units

**latency_ms**

Total server-side duration through settlement and logging. This is not the browser’s full network time.

**ttft_ms**

Time to the first streaming bytes flushed by the gateway. Metadata or keepalive bytes can arrive before text.

**inference_metrics.first_output_ms**

Time to the first answer, reasoning, or tool-output delta.

**inference_metrics.first_content_ms**

Time to the first answer-text delta, excluding reasoning.

**inference_metrics.first_reasoning_ms**

Time to the first reasoning delta, when present.

**inference_metrics.before_upstream_ms**

Time spent before starting the upstream request.

**inference_metrics.upstream_header_wait_ms**

Cumulative wait for response headers across upstream attempts.

**inference_metrics.response_ms**

Time until the gateway finishes reading the response, before final settlement.

**inference_metrics.upstream_attempts**

How many upstream attempts the request made.

**inference_metrics.terminal_event**

Whether a complete protocol terminal event was observed. Inspect this when investigating truncated streams.

## Effective throughput

`output_tokens × 1000 / latency_ms` gives effective tokens per second for a successful request with a positive duration. It includes waiting and reported reasoning tokens. It is not generation-only TPS. Partial/error rows do not get a throughput value in the dashboard.

## Older requests and unknown measurements

Older rows may have `inference_metrics: null`. First-byte timing can also be null on non-streaming requests. Missing values mean no measurement, not zero speed. A recorded zero-millisecond offset is valid and should remain zero.

## Request correlation and billing

Record `X-Atmorouter-Request-Id` when supplied. Share the request ID, UTC timestamp, model, protocol, and client version with support; do not send keys or customer prompts. Settled usage history is the reconciliation source. A final-charge HTTP header cannot be added after an SSE response has begun; consume reported stream usage and check the settled log.

## Playground and service status

`POST /api/dashboard/playground/chat` uses your login session and the same inference billing core, with no API key ID. `GET /api/public/status` reports request-weighted service availability; quiet windows are not synthetic uptime measurements. Family differences remain available under upstream details.

## Read a request’s billing receipt

Open a request in Usage to inspect its Billing receipt, Request price limits, and Failure details. New receipts are recorded prospectively at request time. Older requests may show historical billing receipts or rule details as unavailable; current catalogue prices are never used to reconstruct a historical bill.

The total charged is the recorded settlement amount. A verified aggregate total does not establish separate input, cached-input, or output rates: a receipt with `basis: verified_total` leaves those component rates unreported. Separate rates and component costs appear only when recorded and supported by the billing basis. An effective blended rate divides the total by billed tokens and can include minimum charges and rounding; it is not an actual component token price.

The recorded minimum request charge is a threshold, not the actual total charged. Its presence does not mean a charge occurred. The receipt identifies when the settled charge equals that minimum. Read the total charged independently of the response status: a failed or interrupted response and its billing outcome are separate records.

Request price limits retain the effective caps, pricing snapshot, and applied catalogue, account, API-key, and request rules captured for that request. These are immutable request-time snapshots; editing a budget later does not change the historical receipt. Percentage rules show their recorded discount and resulting caps when available. Missing historical rules remain unavailable.

## Interpret a failure and its source

Failure details show a canonical reason and source when evidence is available; an unknown reason remains unavailable. For example, `provider_balance_unavailable` describes model-provider billing capacity, not your customer account balance. A customer-facing `insufficient_balance` refusal instead calls for reviewing your account’s Billing page. Do not infer either cause from a generic HTTP status alone.

Usage is request history, not a complete audit of every preflight rejection. Authentication, customer balance, or price-limit refusals made before forwarding may not appear in Usage. Preserve the client error and request identifier for diagnosis. See [Errors & retries](https://atmorouter.dev/docs/errors) for the next action.
