usage object reporting the tokens the request consumed. Sunra reports usage in the semantics of the endpoint you called: a Messages response follows the Anthropic contract, and a Chat Completions or Responses response follows the OpenAI contract.
These shapes differ, deliberately. An OpenAI SDK reading a Chat Completions response assumes OpenAI semantics, and an Anthropic SDK reading a Messages response assumes Anthropic semantics. Each endpoint honors what its own specification promises rather than being forced into one shared shape.
Messages
On/v1/messages, the three input buckets are mutually exclusive. No token is counted twice, so the prompt total is their sum:
integer
Fresh input tokens only. Excludes both cache buckets.
integer
Tokens written to the cache by this request.
integer
Tokens served to this request from the cache.
integer
Tokens generated by the model.
integer
The three input buckets plus
output_tokens. Present on non-streaming responses.null counts as zero.
Worked example
The same 19,000-token prefix sent twice againstclaude-opus-4-8. The first request writes the cache; the second reads it.
Cold request (cache write)
Warm request (cache read)
input_tokens stays at 8 across both requests, because 8 is the genuinely new input each time. The 19,349-token prefix moves from the creation bucket to the read bucket. Both requests sum to the same 19,359 total tokens but do not cost the same: cache writes and cache reads are priced at their own per-token rates, which is why they are reported as separate buckets.
Chat Completions and Responses
These endpoints report OpenAI semantics, unchanged. The prompt count is the whole prompt, and cached tokens are a subset of it reported separately./v1/chat/completions
prompt_tokens and cached_tokens double-counts. To get the fresh input on these endpoints, subtract:
/v1/responses with input_tokens and input_tokens_details.cached_tokens.
The sunra_usage_semantics marker
Responses that Sunra has normalized carry a marker inside usage:
usage object; on a streamed response it appears in message_start, the event that carries the input buckets. When it is present with this value, the guarantees on this page hold: the three input buckets are mutually exclusive, and total_tokens — where present — is their sum plus output_tokens.
Its absence is also a promise. Sunra normalizes only response shapes it has measured. Anything else is forwarded from the upstream provider untouched and left unmarked, and a response without the marker is one whose buckets Sunra does not vouch for.
Assert on the marker rather than inspecting the numbers to guess which convention a response follows. Shape sniffing is what this field exists to replace — a heuristic such as “the buckets must be exclusive because they sum to more than the prompt count” is satisfied by more than one convention and will eventually read a response wrong.
/v1/messages responses ever carry the marker. Chat Completions and Responses follow the OpenAI specification and are not marked.
The value is versioned. A breaking change to the meaning of these fields ships under a new value, so an equality check against anthropic.exclusive.v1 will not silently start reading a different contract.
Streaming
On a streamed Messages request, usage arrives across two events.message_start carries the input side and the marker. The terminal message_delta carries output_tokens only. Assert on the marker in message_start, then merge the two events as usual — apply the later event’s usage over the earlier one — to arrive at the values documented above.
total_tokens is omitted from streamed responses. No single event knows both the input and output side, so any total computed mid-stream would be wrong. Sum the buckets yourself once the stream completes.
Migrating from the previous behavior
Sunra previously forwarded the upstreamusage object verbatim on /v1/messages. The translation layer in front of some providers folds cache-creation tokens into input_tokens, so a caller who followed the Anthropic contract and summed the three buckets counted the cache-creation tokens twice.
- If you sum the three buckets, as the Anthropic contract describes, you are now correct. No change is required on your side.
- If you compensated for the old behavior — subtracting
cache_creation_input_tokensout ofinput_tokensyourself, or otherwise reverse-engineering the fold — stop. That correction now subtracts tokens that were already excluded and will understate your input. - If you read
total_tokens, it continues to report the full count: fresh input, both cache buckets, and output.