How to see what each OpenAI API request costs
Short answer: OpenAI's Usage API reports totals per time bucket (a minute, an hour or a day), not the
cost of each request. To know what a single request cost, read the usage block that comes back
with every response, split out the cached input, and multiply each part by your model's price.
Below: which fields to read for Chat Completions and the Responses API, the formula, and a tested Python function you can drop into your code.
What OpenAI's usage reports show (and don't)
OpenAI's organization Usage API (GET /v1/organization/usage/completions) returns token totals
grouped into time buckets of 1 minute, 1 hour or 1 day. You can group the totals by model, project, user, API key
and a few other fields, and it reports the number of requests in each bucket. It needs an admin key.
That is good for trends and monthly totals. It can't tell you that one particular request, the one your app sent at 14:02 for a customer, cost $0.0031. For that you need the numbers that come back with each response.
Where the per-request numbers are
Every response includes a usage block. The field names depend on which API you call:
| Chat Completions | Responses API | |
|---|---|---|
| Input tokens | prompt_tokens | input_tokens |
| …of which cached | prompt_tokens_details.cached_tokens | input_tokens_details.cached_tokens |
| Output tokens | completion_tokens | output_tokens |
| …of which reasoning | completion_tokens_details.reasoning_tokens | output_tokens_details.reasoning_tokens |
Two details matter for cost:
- Cached input is part of the input count.
cached_tokensis included in the input total, and cached input is billed at a lower rate. Subtract it from the input before applying the normal input price. - Reasoning tokens are part of the output count. They don't appear in the answer text, but they are billed as output and already included in the output total. Don't add them a second time.
The formula
new input = input tokens − cached tokens
cost (USD) = ( new input × input price
+ cached tokens × cached-input price
+ output tokens × output price ) ÷ 1,000,000
Prices are per 1 million tokens and differ by model. Take them from OpenAI's pricing page for the models you use; they change from time to time, so keep them in one place in your code.
A tested Python function
This works with both usage formats. It returns None for a model you haven't priced, so missing
prices are never silently counted as zero. (Download it, or get it with the other scripts on GitHub.)
PRICES = {
# "model-name": {"input": 0.00, "cached_input": 0.00, "output": 0.00},
}
def split_usage(usage):
"""Return (new input, cached input, output) token counts from a response's usage block."""
if "prompt_tokens" in usage or "completion_tokens" in usage: # Chat Completions
cached = (usage.get("prompt_tokens_details") or {}).get("cached_tokens") or 0
return (usage.get("prompt_tokens") or 0) - cached, cached, usage.get("completion_tokens") or 0
cached = (usage.get("input_tokens_details") or {}).get("cached_tokens") or 0 # Responses API
return (usage.get("input_tokens") or 0) - cached, cached, usage.get("output_tokens") or 0
def request_cost(model, usage, prices=PRICES):
"""Dollar cost of one request, or None if the model has no price in `prices`."""
p = prices.get(model)
if p is None:
return None
new_in, cached_in, out = split_usage(usage)
return (new_in * p["input"] + cached_in * p["cached_input"] + out * p["output"]) / 1_000_000
With the official Python SDK, response.usage.model_dump() gives you the usage block as a dictionary,
and response.model the model name. Log both, with your own request ID, and you have a receipt for
every call.
Worked example with made-up prices (input $2.00, cached input $0.50, output $8.00 per million tokens): a Chat Completions request with 1,200 prompt tokens (1,000 cached) and 300 completion tokens costs (200 × 2.00 + 1,000 × 0.50 + 300 × 8.00) ÷ 1,000,000 = $0.0033.
We tested the function on five usage blocks in both formats. Its token split matches the one NeverPayTwice's live meter uses for every case.
Things that quietly add up
- The same request, sent again. Every request is billed, including an exact repeat of one you already paid for: a retry loop, a page refresh, a user pressing the button twice.
- Retries. A retry is a new request. If the first attempt was processed too, you pay for both.
- Long conversations. Each turn resends the conversation so far as input, so input grows turn by turn. Caching makes the repeated part cheaper, not free.
Or let something record it for you
NeverPayTwice is a small app we make. Its live meter sits on your own computer between your code and the API: set
OPENAI_BASE_URL=http://127.0.0.1:8098/openai/v1 and every request is passed through unchanged and
recorded with its tokens, cost and request ID. It never blocks or changes a request, and API keys are never
stored. It flags every time you paid again for a request you had already bought, and keeps a receipt for each
one. It also works with Anthropic, Google Gemini and compatible APIs. Mac, Windows or Linux, $9 one time.
See the receipts and repeat-charge detection with sample data first, no sign-up.
Sources: OpenAI API reference for Chat Completions, the Responses API and the organization Usage API (usage/completions), checked November 14, 2026. Field names can change; check the current reference if something doesn't match.