**TL;DR:** Your request logs say 2k tokens but the bill says 9k. The gap is tokens you never see: hidden reasoning tokens, image tokens, and cache writes. Confirm the cause Check the usage breakdown on a real response: 1. On reasoning models, usage.output_tokens_details.reasoning_tokens counts internal thinking: billed as output, never returned in the response.

## The symptom

Billed tokens consistently exceed what your prompt plus visible response suggest. The usage object has fields your logging ignores.

## Confirm the cause

Check the usage breakdown on a real response:

1. **Hidden reasoning tokens.** On reasoning models, `usage.output_tokens_details.reasoning_tokens` counts internal thinking: billed as output, never returned in the response. A "short" answer can carry thousands of reasoning tokens. This is the biggest surprise on o-series and GPT-5.
2. **Image tokens.** Vision inputs are tokenized by size and detail level and land in input tokens. A few high-detail images can outweigh a long text prompt.
3. **Tool and schema tokens.** Tool definitions and structured output schemas count as input tokens on every call.
4. **Cache write tokens.** On GPT-5.6 and later, `prompt_tokens_details.cache_write_tokens` reports prompt tokens written to cache, billed at 1.25x the uncached input rate. Cache writes are not free on newer models.
5. **Retries and streams.** Every retried request rebills its prompt tokens. Every retried stream rebills them too.

## The fix

- Log the full usage object, not just prompt and completion totals. Break down reasoning_tokens, cached_tokens, and cache_write_tokens per call.
- Budget reasoning models with reasoning in mind: lower `reasoning_effort` when deep thinking is not needed, and size `max_completion_tokens` for reasoning plus visible output.
- Right-size image detail. `low` instead of `high` when the task allows it.
- Fix retry storms and loops first; they multiply every hidden cost above.

## Verify the fix

Compare your logged token totals against the billed totals for a day. After the fix they should reconcile within a few percent. Any remaining gap has a named field in the usage object; find it before it finds your budget.

## When to use this

- This covers exactly what the title says: OpenAI billed more tokens than your logs show.
- You are setting this up for the first time, or auditing an existing setup.
- You want the key gotchas in one place before you start.

## When not to use this

- You are doing a different workflow with OpenAI; these steps are specific to the title above.
- You need the full reference docs; this is the short path, not the manual.

## Compatibility

- Mentions 5.6 in the original; behavior may differ on much older or newer releases.