Skip to main content

OpenAI

Route your OpenAI API calls through AI SpendOps for automatic usage tracking and cost attribution.

Configuration

SettingValue
Route/v1/openai/*
Upstreamhttps://api.openai.com
Auth headerAuthorization: Bearer sk-...
Streaming usageAuto-injected (stream_options.include_usage)

SDK base URL

https://proxy.aispendops.com/v1/openai/v1

Example

curl https://proxy.aispendops.com/v1/openai/v1/chat/completions \
-H "Authorization: Bearer sk-your-openai-key" \
-H "X-ASO-API-Key: aso_k_yourkey.secret" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'

Python SDK

from openai import OpenAI

client = OpenAI(
api_key="sk-your-openai-key",
base_url="https://proxy.aispendops.com/v1/openai/v1",
default_headers={"X-ASO-API-Key": "aso_k_yourkey.secret"},
)

response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)

Usage fields

FieldDescription
prompt_tokensInput tokens, including any cached tokens
completion_tokensOutput tokens, including any reasoning tokens
total_tokensSum of prompt and completion tokens
prompt_tokens_details.cached_tokensPortion of prompt_tokens served from cache
prompt_tokens_details.audio_tokensAudio input tokens
prompt_tokens_details.image_tokensImage input tokens
completion_tokens_details.reasoning_tokensPortion of completion_tokens spent on reasoning
completion_tokens_details.audio_tokensAudio output tokens

OpenAI reports the most granular usage of any supported provider. The important structural point is that the _details objects are breakdowns of the totals above them, not additions to them.

Cache token accounting

cached_tokens is a subset of prompt_tokens, not a separate category. Before pricing, AI SpendOps subtracts the cached portion from the prompt total and charges it at the cache-read rate, so the cached input is billed once at the discounted rate rather than twice.

This is the opposite of Anthropic, where input_tokens, cache_read_input_tokens and cache_creation_input_tokens are three separate non-overlapping categories and nothing is subtracted. Getting the two the wrong way round silently over-bills one provider and under-bills the other, which is why the distinction is handled per provider rather than generically.

There is no cache write cost on OpenAI. Caching is automatic above the minimum prompt length, with no cache control parameter to set and nothing to pay for populating the cache.

Reasoning tokens

For o-series and other reasoning models, reasoning_tokens counts thinking that is billed at the output rate but never appears in the response text. It is already included in completion_tokens, so AI SpendOps records it as a separate field for visibility without adding it to the total again.

This is worth watching in its own right. A reasoning model can return a short answer while billing a large number of output tokens, and reasoning spend is usually the largest gap between what teams expect a model to cost and what it actually costs. Filter your usage events on reasoning_tokens > 0 to see how much of your output spend is thinking rather than answers.

Notes

  • Any OpenAI endpoint works through the proxy. Prefix the path with /v1/openai, including embeddings, images, and audio.
  • For /images/* calls there are no tokens to count, so AI SpendOps records image_count, image_size, and image_quality from the request instead.
  • The proxy injects stream_options: { include_usage: true } on streaming requests, so streamed calls report real token counts. See Streaming.
  • Full field definitions are in the usage event field reference.