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 the prepaid wallet settles 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:
| Field | Type | Description |
|---|---|---|
prompt_tokens | integer | Tokens in the input (messages, system prompt, tools). |
completion_tokens | integer | Tokens generated in the response. |
total_tokens | integer | prompt_tokens + completion_tokens. |
Two optional breakdown objects appear when the upstream model reports them:
| Field | Description |
|---|---|
prompt_tokens_details.cached_tokens | Prompt tokens served from the upstream prompt cache. |
prompt_tokens_details.audio_tokens | Audio tokens in the input. |
completion_tokens_details.reasoning_tokens | Hidden reasoning tokens (o-series, reasoning models). |
completion_tokens_details.audio_tokens | Audio tokens in the output. |
completion_tokens_details.accepted_prediction_tokens | Predicted-output tokens that matched. |
completion_tokens_details.rejected_prediction_tokens | Predicted-output tokens that were discarded. |
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
}
}
}
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.
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 using the X-Onlist-Route-Id header, 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
Every Onlist response — streaming and non-streaming — includes an X-Onlist-Route-Id response header. It is an opaque UUID identifying the routing decision for that request (Onlist's analogue of OpenRouter's x-generation-id). On streams it is written before the first SSE byte.
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 and settlement.
Capture the header, then use it to look up cost:
- Read the header on the response.
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- Look up the cost. Either browse the request in your buyer dashboard, or call the owner-only metadata endpoint with the route id:
curl -sS https://onlist.io/api/mkt/routes/3f2a9c7e-1b4d-4a6e-9c11-2b8e0d5f7a31 \
-H "Authorization: Bearer YOUR_ONLIST_TOKEN"
The endpoint is authenticated and owner-only: you can only read the route metadata for requests made with your own token.
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.
-
Top up your wallet. You add funds to a balance held in your buyer account.
-
Send requests. Before a request is relayed, Onlist estimates its cost and checks your balance. If the balance is below the estimate, the request is rejected with
402 insufficient_balancerather than going through. -
Funds are held in escrow. While a request is in flight, the estimated amount is reserved. Escrow is the platform mechanism that keeps a provider from disappearing with prepaid balances — funds are not released to the provider until the request settles.
-
Each request settles and debits the wallet. On settlement, the actual cost (computed from the
usagetoken counts and the provider's listing price) is debited from your balance, and the route's cost record is finalized — the same record you read viaX-Onlist-Route-Id.
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).