API Reference¶
A concise tour of the public surface. Everything below is importable from
openai_usage unless noted otherwise.
Usage¶
The core model. See Tracking Usage for the field table.
Usage.from_openai(openai_usage, *, inplace=False) -> Usage¶
Build a normalized Usage (with requests=1) from any
supported usage type. This is the only entry point — it
accepts the OpenAI SDK types plus google-genai and litellm usage.
openai_usage— any object in theAnyUsageunion.inplace— whenTrue, return the constructed instance directly; whenFalse(default), return a re-validated copy.- Raises
ValueErrorfor an unsupported type.
Usage.add(other) -> None¶
Accumulate other into self, in place. Sums requests, input_tokens,
output_tokens, total_tokens, seconds, and every field of both token-detail
breakdowns (cached, cache-write, reasoning, audio, image, text, video).
Usage.estimate_cost(model=None, *, realtime_pricing=False, ignore_not_found=True) -> float¶
Estimate the cost of this usage as a float. See
Estimating Costs.
model— a resolved model object, a model-namestr, orNoneto fall back toUsage.model(then togpt-4o-mini).realtime_pricing— ignore the cache TTL and re-download both catalogs.ignore_not_found— return0.0for an unknown model (default) instead of raisingValueError.
Usage.estimate_cost_str(...) -> str¶
Same parameters as estimate_cost, but returns the exact Decimal cost as a
string with no float rounding.
Token detail models¶
UsageInputTokensDetails¶
Extends openai.types.responses.InputTokensDetails.
| Field | Default | Source |
|---|---|---|
cached_tokens |
— | OpenAI schema |
cache_write_tokens |
0 |
OpenAI schema |
audio_tokens |
0 |
extension |
text_tokens |
0 |
extension |
image_tokens |
0 |
extension |
video_tokens |
0 |
extension |
cache_write_tokens mirrors the field newer OpenAI SDKs add to
InputTokensDetails. It is redefined with a 0 default so the model stays
constructible on both older SDKs (which lack the field) and newer ones (which
make it required).
UsageOutputTokensDetails¶
Extends openai.types.responses.OutputTokensDetails.
| Field | Default | Source |
|---|---|---|
reasoning_tokens |
— | OpenAI schema |
audio_tokens |
0 |
extension |
text_tokens |
0 |
extension |
image_tokens |
0 |
extension |
video_tokens |
0 |
extension |
Type aliases¶
AnyUsage¶
A typing.Union of every usage type accepted by from_openai, including the
optional google-genai and litellm types. Use it to type your own functions:
from openai_usage import AnyUsage, Usage
def track(raw: AnyUsage) -> Usage:
return Usage.from_openai(raw)
OpenAIUsage¶
The OpenAI-only subset of AnyUsage, kept for backward compatibility.
Pricing — openai_usage.pricing¶
get_model(model_name, *, realtime_pricing=False) -> PricedModel | None¶
Resolve a model name across both catalogs. Returns None when nothing matches.
from openai_usage.pricing import get_model
model = get_model("gpt-4o")
print(model.pricing.price_per_input_token_without_cached)
print(model.pricing.price_per_output_audio_token)
ModelPricing¶
A runtime-checkable Protocol describing the rates the estimator needs, so both
catalogs can be priced through one interface:
price_per_request, price_per_input_token_without_cached,
price_per_input_token_with_cached, price_per_input_cache_write_token,
price_per_output_not_reasoning_token, price_per_output_reasoning_token,
price_per_input_audio_token, price_per_output_audio_token,
price_per_input_image_token, price_per_output_image_token,
price_per_second.
Every property returns a decimal.Decimal, and is 0 when the catalog has no
figure for it.
PricedModel¶
A runtime-checkable Protocol with id: str and pricing: ModelPricing.
OpenRouterModel and LiteLLMModel both satisfy it.
Cache controls¶
openai_usage.pricing.cache_dir(), ttl_seconds() and is_offline() report the
effective cache settings. See Estimating Costs for
the environment variables.
Per-catalog modules¶
openai_usage.pricing.litellm¶
| Function | Returns |
|---|---|
get_model(name) |
One LiteLLMModel, exact key first then relaxed |
get_model_exact(name) |
Exact catalog key only, case-insensitive |
get_model_loose(name) |
Relaxed matching only |
get_entries() |
The raw catalog entries as dict[str, dict] |
get_models() |
The whole catalog, validated |
The catalog is held as raw entries and validated one model at a time, so a
lookup builds only what it returns. get_models() validates all ~3,000 of
them, so prefer get_model() unless you genuinely want the full set.
All of these return empty or None rather than raising when the source is
unreachable — there is no bundled snapshot for this catalog.
openai_usage.pricing.open_router¶
get_models(realtime_pricing=False), get_model(name), plus
OpenRouterModel, OpenRouterPricing and the rest of the catalog schema.
OpenRouterPricing keeps its original price_per_audio_token and
price_per_image_token properties alongside the split input/output ones.
Name matching is exposed too, since both catalogs share it:
| Function | Purpose |
|---|---|
matches_loosely(name, model_id) |
One-shot relaxed match |
normalize_query(name) |
Precompute the three forms a name is matched under |
matches_normalized(query, model_id) |
Match an already-normalized query |
Use the latter two when scanning many ids; matches_loosely re-derives the
normalized forms on every call.
openai_usage.extra.open_router is deprecated
It still re-exports everything it did in v0.9.x, so existing imports keep
working. New code should import from openai_usage.pricing.open_router.