Usage & Cost

Every billable Onlist response reports token counts in a standard OpenAI usage object. Cost, however, is handled differently than on OpenRouter: it is out of band, not in the response body. This page covers what the usage object contains, where cost actually lives, and how prepaid credits settle each request.

The usage object

On /v1/chat/completions, /v1/completions, /v1/responses, and /v1/messages, the response carries a usage object with the familiar token counts. These three fields are always present:

FieldTypeDescription
prompt_tokensintegerTokens in the input (messages, system prompt, tools).
completion_tokensintegerTokens generated in the response.
total_tokensintegerprompt_tokens + completion_tokens.

Two optional breakdown objects appear when the upstream model reports them:

FieldDescription
prompt_tokens_details.cached_tokensPrompt tokens served from the upstream prompt cache.
prompt_tokens_details.audio_tokensAudio tokens in the input.
completion_tokens_details.reasoning_tokensHidden reasoning tokens (o-series, reasoning models).
completion_tokens_details.audio_tokensAudio tokens in the output.
completion_tokens_details.accepted_prediction_tokensPredicted-output tokens that matched.
completion_tokens_details.rejected_prediction_tokensPredicted-output tokens that were discarded.

When Onlist ran a web search for a chat completion, usage also carries server_tool_use.web_search_requests, in OpenRouter's shape: 1 for the web plugin or :online, and the number of search queries charged for the openrouter:web_search server tool. With the server tool, the model may be called several times in one request (a search between each call), and usage is the sum over all of those calls.

Sample usage JSON

The usage object is part of an otherwise standard chat-completion response body:

{
  "id": "chatcmpl-9x2k...",
  "object": "chat.completion",
  "created": 1748563200,
  "model": "gpt-4o-2024-08-06",
  "choices": [],
  "usage": {
    "prompt_tokens": 1024,
    "completion_tokens": 256,
    "total_tokens": 1280,
    "prompt_tokens_details": {
      "cached_tokens": 768,
      "audio_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 0,
      "audio_tokens": 0,
      "accepted_prediction_tokens": 0,
      "rejected_prediction_tokens": 0
    }
  }
}
Note

When you stream (stream: true), the usage object arrives in the final chunk before data: [DONE], not on every chunk. Onlist forces stream_options.include_usage to true so that terminal usage chunk is always emitted. See Streaming.

Cost is out of band

If you are coming from OpenRouter, the key difference is that Onlist does not add a cost field to usage. The usage object reports tokens only. Cost is resolved separately, after the request, against the platform settlement record.

Caution

usage.cost is not returned in the response body. Unlike OpenRouter, Onlist never injects a per-request cost into usage. Do not parse usage.cost: it will be absent. Read cost out of band from the usage log, as described below.

The reason is the platform model: a request is priced and settled against a specific provider's listing, and that settlement is the source of truth for what you were charged. Keeping cost out of the response body keeps the response byte-faithful to the upstream provider and the OpenAI schema.

How to find cost

Cost is recorded per request in your usage log, next to the provider that served it. One lookup answers both "who served this" and "what did it cost" — there is no correlation step.

In the dashboard

Usage Logs lists one row per call with the provider, the model, tokens in and out, latency and time-to-first-token, and the cost in USD. Opening a row adds the request id, the billing mode, and the unit prices that applied to that call.

Programmatically

Four endpoints, differing in what they authenticate with and what they answer:

EndpointAuthenticates withAnswers
GET /api/log/tokenthe API key itselfthat key's latest 1000 entries, one row per call
GET /api/v1/generationthe API key itselfone call, by request id — what it cost and who served it
GET /api/v1/keythe API key itselfthat key's lifetime, daily, weekly and monthly spend
GET /api/v1/activitya management keylast 30 complete UTC days, grouped by day × model × provider
Usage Logs pageyour browser loginfull history, pagination, filtering, per-call details

Each key sees only its own calls, so issuing a separate key per downstream tenant keeps their logs apart. The /api/v1/ endpoints are the OpenRouter-compatible surface; see Management API for the full reference.

curl -sS https://onlist.io/api/log/token \
  -H "Authorization: Bearer YOUR_ONLIST_API_KEY"

Each entry carries exactly these fields:

FieldDescription
costWhat you were charged for the call, in USD
model_nameThe model that served the request
other.provider_name / other.provider_idWhich upstream provider served it
prompt_tokens / completion_tokensToken counts, matching the response usage object
other.cache_tokensPrompt tokens served from the upstream cache, when the model reports it
use_time / other.frtTotal seconds, and time to first token in milliseconds (streaming only)
request_id / created_atRequest identifier and Unix timestamp
token_name / type / is_streamKey name, log type, and whether the call was streamed
other.error_code / other.status_codeOn a failed call, the error code and HTTP status
other.platform_search_calls / other.platform_search_usdWeb search fee: searches charged and their cost in USD, included in cost
other.web_search_call_countSearches run by the provider's own search tool (recorded, not charged)

other is a JSON object, present only when at least one of its fields applies.

Note

This response is a fixed reporting projection — the fields above and nothing else. Account identifiers, source IPs, internal channel data and free-form diagnostic text are deliberately excluded, because an API key travels further than an account credential: it gets embedded in downstream services, CI configuration and clients. For the complete record, use Usage Logs in the dashboard.

cost is a plain USD amount, the same unit as your credits and the prices on every model page. There is no conversion step and no rate to look up. If you are coming from OpenRouter, it is the equivalent of total_cost on a generation.

Charges are metered in whole units of $0.000002, so a call whose true cost falls below that is billed at $0.000002 rather than rounded away. A cost of exactly 0 means the call genuinely cost nothing: a listing priced at zero, or a call that produced no tokens.

Caution

/api/log/token, /api/status and everything under /api/v1/ are served from https://onlist.io only. The China acceleration endpoint (https://api.onlist.net) relays inference traffic and answers 403 for these paths. Point your inference client at whichever endpoint suits you, and keep reporting calls on the main domain.

Per-call cost by request id

Every Onlist response carries an X-Oneapi-Request-Id header — the same value that appears as request_id in /api/log/token. Feed it to /api/v1/generation to get one call's cost, provider, latency and token counts:

curl -sS "https://onlist.io/api/v1/generation?id=THE_REQUEST_ID" \
  -H "Authorization: Bearer YOUR_ONLIST_API_KEY"

total_cost (and its alias usage) is the USD amount you were charged — OpenRouter's total_cost on a generation, same field name and same unit. Full field list in the Management API.

Route ids explain routing, not cost

Every Onlist response (streaming and non-streaming) also includes an X-Onlist-Route-Id response header. It is an opaque UUID identifying the routing decision for that request. On streams it is written before the first SSE byte.

Note

/api/v1/generation takes If you are looking up what a call cost, use X-Oneapi-Request-Id (see above). X-Onlist-Route-Id identifies the routing decision, not the log entry, and is the id used by the routing-explanation endpoints.

Note

X-Onlist-Route-Id is not the body id field. The body id is the upstream completion id (for example chatcmpl-...); the route id is Onlist's own identifier for the routing decision.

curl -sS -D - -o /dev/null https://onlist.io/v1/chat/completions \
  -H "Authorization: Bearer YOUR_ONLIST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Hello"}]
  }' | grep -i x-onlist-route-id

To see how a request was routed — which provider was selected, which listing, what the candidate pool looked like, and every failover attempt — open that call in Usage Logs in the dashboard. The route id identifies that record.

Route inspection is a signed-in surface, not a programmatic one: it is served to your browser session, and API keys do not authenticate against it.

Important

Route records explain routing, not cost. They carry no charge, and the usage log has no route-id column to join against. For per-request cost, read the usage log directly: it already names the provider, so nothing needs to be correlated. Reach for route ids when you want to understand why a request went where it did.

For the full list of Onlist response headers and their semantics, see Limits & headers.

Billing model

Onlist billing is prepaid. There is no monthly invoice and no post-paid credit line.

  1. Buy credits. Credits are prepaid usage on Onlist and sit in your buyer account until you spend them.

  2. Send requests. Before a request is relayed, Onlist estimates its cost and checks your remaining credits. If your credits are below the estimate, the request is rejected with 402 insufficient_balance rather than going through.

  3. Credits are reserved while the call runs. While a request is in flight, the estimated amount is held back from your credits. Nothing is paid out to the provider until the request settles, so a provider cannot walk away with credits for work it never delivered. With the openrouter:web_search server tool, more is reserved before each further model call, and the request stops when it cannot be.

  4. Each request settles and debits your credits. On settlement, the actual cost (computed from the usage token counts and the provider's listing price) is debited from your credits, and the entry appears in your usage log with the provider that served it. Anthropic 1-hour cache writes are billed at the 1-hour rate only when your request asked for a 1-hour breakpoint ("ttl": "1h"); otherwise they are billed at the 5-minute rate. A request that used Onlist's web search also carries the search fee, and the estimate in step 2 already includes it. With the openrouter:web_search server tool, every model call in the request is billed at the provider's price and priced on its own (a long-context price applies only to a call whose own prompt is long enough; per-request prices count each call), the usage log records one entry with the totals, and its details show how many model calls were made.

Caution

Because settlement needs the terminal usage chunk, streaming requests always run with stream_options.include_usage forced to true. You cannot opt out. See Streaming.

Next steps

  • Streaming: How usage arrives in the final SSE chunk and why include_usage is forced true.
  • Limits & headers: X-Onlist-Route-Id, X-Onlist-Warnings, Retry-After, and rate-limit behavior.
  • Errors: The insufficient_balance and quota_exhausted 402 codes, and the full error envelope.
  • OpenAPI spec: Exhaustive request and response schemas, including the usage object (YAML download).