Skip to content

Organization Usage & Costs API

Report what this deployment consumed and what it cost, in time buckets, through the OpenAI Administration Usage and Costs API.

At a glance

  • Eleven endpoints — ten /v1/organization/usage/* families reporting tokens, characters, seconds of audio, images and tool calls, plus /v1/organization/costs for what AWS bills — see Endpoints.
  • Grouped by model, source, tenant API key or user — the keys that are served, and the ones refused with an explanation, are listed under Grouping.
  • 1m buckets for 15 days, 1h and 1d for 455 — a query past the boundary is refused rather than answered at a coarser resolution, see Bucket width.
  • Off by default — the surface is served only when usage_api is enabled.
from openai import OpenAI

client = OpenAI(base_url="https://your-gateway/v1", api_key="...")

page = client.admin.organization.usage.completions.list(
    start_time=1756000000, bucket_width="1d", limit=7, group_by=["model"]
)
for bucket in page.data:
    for result in bucket.results:
        print(bucket.start_time, result.model, result.input_tokens)

Administrator endpoints, disabled by default

These endpoints report the whole deployment, not the calling client, and every query is billed by Amazon CloudWatch. They are served only when usage_api is enabled, and only to administrator credentials — see Who may call it.

Endpoints

Endpoint Reports
GET /v1/organization/usage/completions Input, output and cached tokens of chat, responses, text completion, messages and realtime requests
GET /v1/organization/usage/embeddings Input tokens of embeddings requests
GET /v1/organization/usage/moderations Input tokens of moderation requests
GET /v1/organization/usage/images Images produced by generation, edit and variation requests
GET /v1/organization/usage/audio_speeches Characters synthesized
GET /v1/organization/usage/audio_transcriptions Seconds of audio transcribed or translated
GET /v1/organization/usage/web_search_calls Searches run by the built-in web search tool
GET /v1/organization/usage/file_search_calls Vector store searches run
GET /v1/organization/usage/vector_stores Nothing: vector store storage is not measured
GET /v1/organization/usage/code_interpreter_sessions Nothing: no code interpreter is served
GET /v1/organization/costs What AWS bills this deployment for serving the requests

The two endpoints that report nothing answer a well-formed page of empty buckets rather than a 404: the endpoint exists, and no measurement was taken.

GET /v1/usage is not served

The retired top-level usage endpoint is absent from OpenAI's current API surface and from the openai package, so there is no shape to mirror. Use the /v1/organization/usage/* family above.

Enabling the surface

Setting Needed for
cloudwatch_metrics Publishing the usage the endpoints read back. Nothing is reported for the period before it was enabled.
usage_api Serving the endpoints at all, and publishing usage per endpoint.
cost_tracking /v1/organization/costs only.

With usage_api disabled every endpoint answers 503. Enabling usage_api without cloudwatch_metrics fails at startup instead, rather than serving endpoints that could never answer — the server log names the missing setting.

The server role needs cloudwatch:GetMetricData and cloudwatch:ListMetrics — see Usage API IAM permissions — and the queries are billed per metric read, which Usage API query cost puts a number on.

Query parameters

Every endpoint takes:

Parameter Default Notes
start_time Required. Unix seconds, inclusive.
end_time now Unix seconds, exclusive.
bucket_width 1d 1m, 1h or 1d. /v1/organization/costs accepts 1d only.
limit 7 (1d), 24 (1h), 60 (1m) Buckets per page. Maximum 31, 168 and 1440 respectively; 180 on /v1/organization/costs.
page Cursor from the next_page of a previous response.
group_by See Grouping.
models Report only these models. Not on /v1/organization/costs or file_search_calls.
user_ids, api_key_ids Report only these callers. Accepted only where that identity is recorded — see Grouping.

Buckets are aligned to the UTC grid of the requested width, so start_time is rounded down to a bucket boundary and the reported start_time of the first bucket may be earlier than the one asked for.

/v1/organization/usage/images additionally takes sources (image.generation, image.edit, image.variation).

Grouping

group_by Served
model On every model-backed endpoint.
source On images.
api_key_id When tenant API keys are issued. Otherwise refused: the deployment has one key, which identifies itself rather than a caller.
user_id When cloudwatch_metrics_user_dimension is enabled. Otherwise refused: consumption is not recorded per user by default, because that is one stored metric series per user.
project_id There are no projects here, so usage is never attributed to one.
batch Batch API usage is not reported by these endpoints at all — see Limits and behaviour to know.
service_tier The service tier a request ran under is not reported apart.
size The size of a generated image is not reported.
context_level The context size of a web search is not reported.
vector_store_id File searches are not reported per vector store.
line_item Costs are not reported per product line item.

A refused key answers 400 naming the key and the reason. A refused key is never silently ignored: the grouping is the request.

api_key_id and user_id may each be combined with model, but not with each other: usage is reported per key or per user, never per pair of the two. The same holds for the api_key_ids and user_ids filters, and for one of them combined with a grouping by the other.

A key that was not grouped by is omitted from the JSON object rather than sent as an explicit null. The openai SDK reads it back as None either way, so only a client parsing the raw JSON sees the difference — read such a key with result.get("model"), never result["model"].

Bucket width and how far back

Narrow buckets are only kept for so long:

bucket_width Reported for
1m The last 15 days
1h The last 455 days
1d The last 455 days

A query past the boundary is refused with 400 naming the limit, rather than answered at a coarser resolution than it asked for — a usage report that silently changes resolution mid-range is a number that ends up in a spreadsheet. Ask for a later start_time, or a wider bucket_width.

The span between start_time and end_time is additionally bounded by usage_api_max_range_days, 92 days by default.

A model idle for two weeks stops being reported

The endpoints find the series to read through CloudWatch's metric index, which only carries what reported data in the last 14 days. A model, endpoint, tenant key or user that has served nothing for a fortnight is therefore missing from every bucket of the answer, however recent the range asked for — and so is its spend on /v1/organization/costs. Retire a model and its history stops being reported two weeks later; the same holds for a user or a tenant that went quiet.

This bounds the surface to reporting on what a deployment is currently serving. Where a permanent record is needed, keep the request logs, which are written per request and retained for as long as their log group is.

Costs

/v1/organization/costs reports the cost of the work in daily buckets, one result per currency:

{
  "object": "bucket",
  "start_time": 1756000000,
  "end_time": 1756086400,
  "results": [
    {
      "object": "organization.costs.result",
      "amount": {"value": 1.42, "currency": "usd"}
    }
  ]
}

This is the AWS bill, not an invoice to your clients

amount is what AWS charges this deployment's account for serving the requests. It is not what a reseller charges its own customers, and it carries no margin.

Amounts are never summed across currencies: a deployment spanning partitions reports one result per currency.

Who may call it

Credential Accepted
The deployment's own API key It is the operator's own credential.
An Amazon Cognito token Only when it carries every scope in usage_api_admin_scopes. With that list empty, no token is accepted.
A tenant API key A per-customer credential is never an administrator credential.

Anything else answers 403. Upstream gates the same endpoints on a separate administrator credential; this is the closest equivalent a deployment can express.

Limits and behaviour to know

Where this surface answers differently from the upstream Administration API:

  • Only the grouping keys and filters in Grouping are served; the rest are refused with an explanation rather than ignored.
  • completions reports input_tokens, output_tokens, input_cached_tokens, input_cache_write_tokens, input_uncached_tokens and num_model_requests. input_tokens covers the whole prompt, cached and cache-write tokens included, so it reconciles with the prompt_tokens the same requests returned. The text/audio/image token breakdown upstream also publishes is not reported.
  • num_model_requests counts only the records carrying the endpoint's own measurement. A guardrail applied around the call, the built-in web search, a managed knowledge base retrieval and the translation behind an audio translation are each billed apart and recorded under the operation of the request they served, so they reach neither the count nor the group_by=model rows of the endpoint that request went to.
  • moderations reports num_model_requests for every moderation, and input_tokens only for the ones a language model answered: a guardrail and Amazon Comprehend are moderating backends here rather than a filter around another call, so their records are counted — and a moderation answered by an Amazon Bedrock guardrail counts once per policy that guardrail applies.
  • web_search_calls reports num_requests and num_model_requests; context_level is never reported. num_model_requests counts every request the model answered in the bucket, not only the ones that called the search tool, whenever the two shared the same model, operation and grouping in that bucket: the search count is recorded on the model's own usage record, so a bucket mixing searching and non-searching traffic to the same model cannot be told apart from the metrics alone.
  • file_search_calls counts searches for the deployment as a whole; vector_store_id is never reported.
  • Batch API usage is absent from the usage endpoints. A batch's tokens are recorded against the route that collected its results, which carries no reported endpoint, so they reach neither completions nor embeddings — yet their spend is included in /v1/organization/costs. On a deployment running significant batch traffic, usage and costs therefore do not reconcile, by the whole batch workload.
  • Usage is reported from a single region — see cloudwatch_metrics_region. A deployment publishing from more than one region reports the one it reads.
  • next_page is this server's own cursor and is only meaningful to it.

How far back a bucket width is answered, and the two-week metric index behind every answer, are covered in Bucket width and how far back.

Try it

Report the last seven days of token usage per model, with administrator credentials:

curl -G "https://your-gateway/v1/organization/usage/completions" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d start_time=1756000000 \
  -d bucket_width=1d \
  -d limit=7 \
  -d group_by=model

Next steps

Next: Configuration · Cost Management · Logging & Monitoring · IAM Permissions