July 17, 2026

8 min read

OpenAI Usage API + Anthropic Cost API Integration Guide

AICosts.ai

A copy-pasteable OpenAI Usage API Anthropic Cost API integration guide: real endpoints, auth, Python code, gotchas, and a unified schema.

#openai usage api anthropic cost api integration guide

#openai organization usage api tutorial

#anthropic admin usage and cost api

#track openai and claude costs together

#multi-provider llm cost dashboard api

Wiring OpenAI's Usage API and Anthropic's Cost API Into One Dashboard

The billing page works fine when you have one provider. The moment you're running GPT-4o for one workload and Claude for another — which is most teams by month three — you have two dashboards, two currencies of granularity, and zero way to answer "what did we spend on AI last Tuesday, broken down by model." This is the actual plumbing: endpoints, auth, code, and the parts of the docs that will burn an afternoon if you don't know them going in.

Both OpenAI and Anthropic now expose real admin-grade usage and cost APIs (Anthropic's newest addition, the Enterprise Analytics API, adds per-user attribution across Claude, Claude Code, and Cowork). Here's how to pull from both and normalize them into one schema.

OpenAI: Admin key, org ID, and two endpoints

You need an Admin API key, not a regular project key. Generate one under Organization Settings → Admin Keys (only org owners can do this). Project-scoped keys will 401 on these endpoints.

  • /v1/organization/usage/completions — raw token/request usage, bucketed over time.
  • /v1/organization/costs — actual dollar spend, bucketed over time.

These are separate endpoints on purpose: usage gives you tokens and request counts (useful for capacity planning and per-model comparisons), cost gives you dollars (useful for finance). You typically need both.

curl https://api.openai.com/v1/organization/costs \
  -H "Authorization: Bearer $OPENAI_ADMIN_KEY" \
  -G \
  --data-urlencode "start_time=1717200000" \
  --data-urlencode "bucket_width=1d" \
  --data-urlencode "group_by=project_id"

Python version, pulling both usage and cost for the last 7 days:

import requests, time

ADMIN_KEY = "sk-admin-..."
HEADERS = {"Authorization": f"Bearer {ADMIN_KEY}"}
start = int(time.time()) - 7*86400

usage = requests.get(
    "https://api.openai.com/v1/organization/usage/completions",
    headers=HEADERS,
    params={"start_time": start, "bucket_width": "1d", "group_by": "model"}
).json()

costs = requests.get(
    "https://api.openai.com/v1/organization/costs",
    headers=HEADERS,
    params={"start_time": start, "bucket_width": "1d", "group_by": "project_id"}
).json()

for bucket in costs["data"]:
    for line in bucket["results"]:
        print(bucket["start_time"], line["project_id"], line["amount"]["value"])

Useful group_by values: project_id, api_key_id, model, batch, user_id (only present if you're tagging requests with user identifiers via the API). Both endpoints paginate with a page cursor in the response when results exceed the limit — don't assume one call gets everything once you're past a handful of projects.

OpenAI gotchas that will cost you an afternoon

  • Costs are in dollars, not cents. The amount.value field on the costs endpoint is a decimal USD figure already. Don't divide by 100 — that's a habit from Stripe-style APIs and it will quietly halve every number you show finance.
  • The old billing endpoints are dead. /v1/dashboard/billing/usage and /v1/dashboard/billing/subscription are legacy, undocumented, and can disappear without notice. If a tutorial you find still references them, it's outdated — use the organization endpoints above.
  • bucket_width has a floor. You can request 1m (minute) buckets, but only for short windows — request a month of minute-level data and you'll get truncated or rejected. For anything beyond a few hours of granularity, use 1h or 1d.
  • Usage ≠ cost per model directly. The usage endpoint doesn't return a dollar figure per model bucket — you have to cross-reference against current published per-token pricing yourself if you want cost-per-model without going through the costs endpoint's project-level grouping.

Anthropic: Admin key, Usage & Cost API, and the new Enterprise Analytics API

Anthropic's equivalent requires an Admin API key (prefixed sk-ant-admin...), created by an org owner in the Anthropic Console. Every request needs the standard anthropic-version header alongside your key.

  • /v1/organizations/usage_report/messages — token and request counts, grouped by workspace, API key, or model.
  • /v1/organizations/cost_report — dollar spend over time, same grouping options.
  • Enterprise Analytics API — the newer addition, layering per-user cost and usage attribution on top, across Claude, Claude Code, and Cowork — useful if you need to know which engineer's Claude Code sessions are driving spend, not just which workspace.
curl https://api.anthropic.com/v1/organizations/cost_report \
  -H "x-api-key: $ANTHROPIC_ADMIN_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -G \
  --data-urlencode "starting_at=2024-06-01T00:00:00Z" \
  --data-urlencode "bucket_width=1d" \
  --data-urlencode "group_by=workspace_id"

Python pull, mirroring the OpenAI pattern above:

import requests, datetime

HEADERS = {
    "x-api-key": ANTHROPIC_ADMIN_KEY,
    "anthropic-version": "2023-06-01",
}
start = (datetime.datetime.utcnow() - datetime.timedelta(days=7)).isoformat() + "Z"

resp = requests.get(
    "https://api.anthropic.com/v1/organizations/cost_report",
    headers=HEADERS,
    params={"starting_at": start, "bucket_width": "1d", "group_by": "workspace_id"}
).json()

for bucket in resp["data"]:
    for line in bucket["results"]:
        print(bucket["starting_at"], line["workspace_id"], line["cost"])

Anthropic gotchas

  • 90-day history limit. Both the Usage & Cost API and the Enterprise Analytics API only expose the trailing 90 days. If you want a longer trend line, you need to be pulling and storing this data yourself starting now — there's no backfill past that window.
  • Tokenizer differences break naive cross-provider math. Claude's tokenizer and OpenAI's tiktoken don't count tokens the same way for identical text, so "tokens per dollar" comparisons across providers are misleading unless you're comparing dollar cost directly, not token counts.
  • Workspace and user IDs aren't self-explanatory. The API returns opaque workspace_id and user_id values — you'll need to maintain your own mapping table (workspace_id → team name, user_id → employee) if you want readable reports rather than a wall of UUIDs.
  • The Enterprise Analytics API is new and still settling. Field names and grouping options have changed since initial release — pin your integration to a specific API version and re-check the response shape before you ship a dashboard that depends on it.

Normalizing both into one schema

Once you're pulling from both, collapse everything into one row shape before it touches a chart or a spreadsheet:

FieldSource (OpenAI)Source (Anthropic)
providerliteral "openai"literal "anthropic"
datebucket.start_timebucket.starting_at
modelline.modelline.model
cost_usdline.amount.valueline.cost
team_keyproject_id (mapped)workspace_id (mapped)

Write both into a table with that shape — Postgres, SQLite, or honestly a Google Sheet if you're under 10k rows/month — and you can group by provider, model, or team without touching provider-specific logic again.

Where the DIY pipeline breaks down

A cron job hitting two endpoints and writing to a spreadsheet works for exactly this: two providers, low volume, one person checking it. It stops working once any of these show up:

  • A third provider. Add Pinecone, Midjourney, or a vector DB and you're now maintaining three different auth schemes, three different bucket/group_by vocabularies, and three sets of rate limits.
  • Budgets and alerts. Neither API has a native "tell me when project X crosses $500 this month" feature — you have to build the threshold logic and the notification channel yourself.
  • Schema drift. Anthropic's Enterprise Analytics API is actively changing shape. A hardcoded parser breaks silently the next time a field gets renamed.
  • Per-user attribution across tools. If part of your AI spend is an agent — say an outbound lead-gen agent making thousands of API calls a day — you need usage rolled up by workload, not just by provider, which neither native API gives you out of the box.

This is also a good moment to check whether some of that spend should exist at all in its current form. If a chunk of your OpenAI or Claude bill is a narrow, repetitive task — classification, extraction, a fixed-format agent step — fine-tuning a smaller open-weight model on your own data and running it behind an OpenAI-compatible endpoint often cuts that specific line item by 70-90%, and it shows up as a distinct SKU in your cost data once you're tracking spend granularly enough to see it.

The shortcut

Everything above — auth, pagination, cents-vs-dollars, the 90-day window, ID mapping, schema normalization — is exactly the plumbing AICosts.ai already runs, against OpenAI, Anthropic, and 48+ other providers. You connect an admin key per provider, and it's pulling normalized cost, usage, and per-model breakdowns into one dashboard with budgets and alerts within minutes — no cron job, no schema to maintain when Anthropic changes a field name next quarter.

Quick reference: endpoints and auth

ProviderEndpointAuthHistory limit
OpenAI/v1/organization/usage/completionsAdmin API keyNo hard cap
OpenAI/v1/organization/costsAdmin API keyNo hard cap
Anthropic/v1/organizations/usage_report/messagesAdmin API key (x-api-key)90 days
Anthropic/v1/organizations/cost_reportAdmin API key (x-api-key)90 days
AnthropicEnterprise Analytics APIAdmin API key (x-api-key)90 days

FAQ

  • Do I need an admin/org-owner account to get these keys? Yes for both. OpenAI Admin keys and Anthropic Admin API keys can only be generated by an organization owner in each provider's console — a regular project or workspace key returns 401/403 on these endpoints.
  • Can I get cost broken down by individual user, not just project/workspace? On OpenAI, only if you're passing a user identifier with each request and grouping by user_id. On Anthropic, the Enterprise Analytics API is specifically built for this — it's the main reason it exists.
  • Why don't my token counts match my dollar costs when I compute them manually? Published per-token pricing changes by model version and sometimes by batch vs. real-time tier — always pull from the costs/cost_report endpoint for dollars rather than recalculating from token counts and a hardcoded price sheet.
  • How often should I poll these APIs? Daily is enough for budgeting; hourly if you're trying to catch a runaway agent process before it burns through a monthly budget. Both APIs support 1-day and finer buckets, so your polling cadence doesn't have to match your bucket width.

Ready to Get Started?

Join hundreds of companies already saving up to 30% on their monthly AI costs.

Start Optimizing Your AI Costs