Skip to content

API Response Inspector

Paste a completion response and get every field explained, plus the arithmetic checks that catch a truncated or malformed one.

Everything on this page runs in your browser. Nothing you paste is uploaded, logged, or written into the URL — only the settings are, so a configured tool can still be linked to. Responses carry ids, prompts and sometimes customer data. This one stays in the tab.

Fields explained
20 of 20

0 fields on this response are not in this page's glossary — they are listed below rather than quietly dropped.

fieldvaluewhat it means
id"resp_7f21c9"the identifier for this request. Log it — it is the only thing support can look anything up by.
object"chat.completion"the kind of thing this is, so a client can dispatch on it.
created1785312000when the response was produced, in seconds since the epoch.
model"example-model-v1"which model actually served the request. Worth asserting on: a routing layer can silently give you a different one from the one you asked for.
choices1 itemthe completions returned. One entry unless you asked for more, and asking for more multiplies the output tokens you pay for.
choices[0]3 fieldsthe completions returned. One entry unless you asked for more, and asking for more multiplies the output tokens you pay for.
choices[0].index0the position of this choice, for when there is more than one.
choices[0].message2 fieldsthe assistant's turn — role, plus content and/or tool calls.
choices[0].message.role"assistant"who is speaking. Everything in choices is the assistant.
choices[0].message.content"{\"invoice_id\": \"INV-2201\", \"total\": 1250"the text. Null or empty is normal when the model called a tool instead of answering.
choices[0].finish_reason"length"why generation stopped. "stop" is a complete answer; "length" means it was cut off; "tool_calls" means it wants a tool; "content_filter" means something blocked it.
usage5 fieldsthe token counts you are billed on. This is the block to log on every call.
usage.prompt_tokens1840input tokens. Includes the system prompt, the whole conversation history and every tool schema — which is why it grows even when your user's message did not.
usage.completion_tokens256output tokens. Priced higher than input almost everywhere, and the number worth optimising first.
usage.total_tokens2096input plus output. Derived, so it should always equal the sum — if it does not, one of the three is measuring something else.
usage.prompt_tokens_details1 fielda breakdown of the input tokens, usually into cached and uncached.
usage.prompt_tokens_details.cached_tokens1536input tokens served from a prompt cache. Billed at a lower rate where caching exists — check whether this is a subset of prompt_tokens or additional to it, because providers differ and it changes your cost model.
usage.completion_tokens_details1 fielda breakdown of the output tokens, usually separating reasoning from visible text.
usage.completion_tokens_details.reasoning_tokens192output tokens spent thinking rather than answering. You are billed for them and you usually cannot see them, so a short answer can carry a large bill.
system_fingerprint"fp_examp1e"an opaque identifier for the backend configuration. When it changes, output can change even with identical inputs and a fixed seed.

Arrays are expanded for their first three entries. Nesting is followed six levels deep and 200 fields at most.

  • noteusage.prompt_tokens_details.cached_tokens1,536 of 1,840 input tokens came from cache — 83% of the prompt

    Expected: you to check which convention your provider uses before multiplying anything by a cached rate. Both conventions exist and they differ by the whole cached amount

  • noteusage.completion_tokens_details.reasoning_tokens192 of 256 output tokens were reasoning — 75% of the output you paid for is not in the text you received

    Expected: you to price on completion_tokens, not on the length of the visible answer. A two-line reply can carry a four-figure token count

  • errorchoices[0].finish_reason"length" — this answer was cut off mid-generation, not completed

    Expected: "stop". The content you have is a prefix, and if it was meant to be JSON it will not parse. Raise max_tokens, or shorten what you asked for — retrying unchanged will truncate at the same place

  • errorchoices[0].message.contentthe content looks like JSON and does not parse — Expected ',' or '}' after property value in JSON at position 40 (line 1 column 41)

    Expected: valid JSON, if you are relying on it. Truncation is the usual cause and finish_reason will say so; a leading markdown fence is the other

What this checked: this parses the body and names every field it recognises, with the arithmetic checks that catch a broken response: whether total_tokens equals input plus output, whether generation was truncated, whether content that looks like JSON actually parses, whether tool-call arguments parse, whether an error envelope is hiding where a completion should be. The fields it does not recognise are listed as such, because a response inspector that silently drops what it does not know is worse than none. It carries no prices and no model data of any kind — it cannot tell you what this call cost, only how many tokens of what kind it used — and the glossary describes what field names conventionally mean, not what your particular provider guarantees.
What this assumes: a single JSON object, not a stream. A server-sent-events stream is a sequence of partial objects and needs unpacking first. Field meanings follow the shapes the major chat APIs converged on; where two providers use different names for the same idea — prompt_tokens and input_tokens, completion_tokens and output_tokens — both are recognised and treated as the same thing. Where they genuinely differ, most importantly in whether cached tokens are counted inside the input total or in addition to it, this page says so rather than picking one.

The two fields that decide whether you have an answer

The finish reason and the content are the whole verdict, and code that reads only the content gets it wrong in two directions. A length finish means the string you are holding is a prefix — it will be valid prose and invalid JSON, which is precisely the combination that passes a smoke test and fails in production. And an empty content with tool calls is a completely successful response that a null check will treat as a failure. Branch on the finish reason first, then read the content.

Log the usage block, not a computed cost

Token counts are facts the provider asserts; a cost is your arithmetic over a rate that changes. Store the raw counts — input, output, cached, reasoning — with the model name and the request id, and compute money when you report on it. Do it the other way round and a price change, or a discovery that cached tokens were being double-counted, means the history is wrong and unrecoverable. It is also the only way to notice the thing that quietly doubles most bills: an input token count that grows every turn because the whole conversation is being resent.

API Response Inspector · Multigrid