August 5, 20269 min read

How to track OpenAI API costs (per project, per model, per feature)

The OpenAI dashboard tells you what you spent, not why. Three levels of cost attribution, the DIY playbook in full, and the point where a tool earns its keep.

Your OpenAI invoice is one number. The questions people ask you about it are not.

"Which feature is driving this?" "What does the summarization pipeline cost per customer?" "Why did Tuesday cost 4x Monday?" The invoice answers none of these, and the usage dashboard answers maybe half of one. What follows is the full map: what OpenAI gives you for free, what you can build yourself, and the point at which building it yourself stops being worth an engineer's time. We sell a tool that does this, so read the DIY sections critically — but we've written them to actually work, because a reader who builds the pipeline and outgrows it is a better future customer than one who got a sales pitch dressed up as a how-to.

What the OpenAI dashboard gives you — and where it stops

The usage page on the OpenAI platform is better than most API vendors'. You get daily spend, broken down by model and by project, with token counts split into input, output, and cached input. For a solo developer or a single-product team, this may genuinely be enough.

Here's where it stops. The dashboard knows what OpenAI knows: an API key made a request, with this many tokens, against this model. It does not know your feature called it, or which customer triggered it, or that the request was a retry. OpenAI's billing surface is built for accounts payable. The moment someone asks a question with the word "why" in it, you've left the territory the dashboard covers.

That gap is the whole subject here. There are three levels of attribution, and each one costs more effort than the last.

Level 1: Projects — the attribution you get for free

If you do only one thing after reading this, do this: stop using one API key for everything.

OpenAI lets you split an organization into projects, each with its own keys, its own usage reporting, and its own limits. Map projects to whatever unit you'll be asked to report on — one per product surface, one per environment, one per team. It's an afternoon of key rotation, and it converts "our OpenAI bill" into "the chatbot costs $X, the extraction pipeline costs $Y, staging costs $Z — and why does staging cost $Z?"

Two rules that save pain later:

  • Prod and non-prod never share a project. A load test that burns $800 of tokens should be visible as a load test, not smeared into the product's unit economics.
  • Name projects for the answer, not the org chart. "team-platform" tells finance nothing; "doc-extraction-prod" answers the question before it's asked.

The ceiling on Level 1: projects are as granular as your keys. If one service powers six features through one key, the dashboard sees one blob. That's Level 3's problem.

Level 2: Pull the numbers instead of reading them

The dashboard is a screen; sooner or later you need the data. OpenAI exposes usage and costs endpoints for exactly this — daily figures by project and model that you can pull with an admin key on a schedule and land in a warehouse table.

This matters for three reasons. First, retention: your warehouse remembers what any vendor dashboard eventually ages out. Second, joins: once spend sits next to your product analytics, "cost per active user" is a query, not a project. Third, alerting: a nightly job that compares today's pull against a trailing average is a crude but real anomaly detector — crude catches the 4x day, and the 4x day is the one that matters.

What Level 2 still can't do: anything below a project-day. The granularity is OpenAI's, not yours.

Level 3: Per-feature, per-customer — the DIY playbook

There is exactly one way to get attribution OpenAI doesn't have: record it yourself, at the call site. The pattern is a decade old — it's just structured logging.

Wrap the client once. Every OpenAI call in your codebase goes through one internal function. It takes a mandatory attribution object — feature, customer_id, environment at minimum — and refuses to run without it. Enforce it in code review or with a lint rule. Optional tags rot; within a quarter, half your spend is tagged "unknown."

Log one line per request. The response already carries token usage. Emit a record of timestamp, model, feature, customer_id, input tokens, output tokens, cached tokens, and computed cost to wherever your logs already go.

Compute cost at aggregation time, not log time. Store tokens raw and join against a rates table in the warehouse. Prices change; hardcoded rates in a logging wrapper are a bug you'll find months later, embedded in every historical row. Keeping a current rates table is itself a chore — our LLM pricing explorer, linked below, exists partly because we needed one.

Reconcile weekly against the costs endpoint. Your computed total will not match the invoice. Streaming responses, retries you logged twice, cache discounts you modeled wrong, a price change mid-month — a 2–5% gap is normal and fine. The reconciliation isn't there to hit zero; it's there so the gap stays boring. The week it jumps to 15% is the week your wrapper stopped seeing some traffic.

A worked example, because vague playbooks are worthless. Say you run 40M input and 8M output tokens a month through a mid-tier model. Your wrapper data shows the support-summarizer feature is 60% of spend, and — the actual finding — that its prompts average 4,000 input tokens against 150 output. That input:output ratio is the expensive shape: you're paying to re-send a mostly-static system prompt thousands of times a day. Prompt caching or a trimmed context could cut that feature by a third. That is what attribution is for. The dashboard could never have told you; it doesn't know the summarizer exists.

The honest cost of DIY

Everything above works. We'd stake our reputation on it, since we've now told several thousand readers to do it. Here's what it costs, from teams we've watched run it:

  • It's a product, not a project. The wrapper needs an owner. New models, new token types, new discount mechanics, new endpoints someone integrated without the wrapper — each one silently degrades your data until someone notices the reconciliation drifting.
  • It's single-provider. The week someone adds Claude for one feature — and there's at least one moment a year when that's clearly worth doing — you're building it again, against a different usage model with different cache mechanics.
  • It stops at the API bill. Your AI feature also costs compute, storage, and vector-database queries. Attribution that ends at OpenAI's invoice answers the engineering question and leaves the CFO's question — what does this product actually cost to run? — hanging.

None of this says don't build it. A single-provider engineering team with warehouse skills should build Levels 1 through 3 and stop reading here. It says: know which of these costs you're signing up for.

When a tool earns its keep

The switch usually flips on one of three events. Finance asks for AI spend inside the cloud cost report, not next to it. A second provider shows up. Or an anomaly gets through — nobody was watching the reconciliation job the week a retry loop ran hot.

That set of problems — one ledger, many providers, someone watching while you sleep — is what CloudQuell is. Connect an admin API key and OpenAI spend lands per-project and per-model in the same ledger as your AWS, Anthropic, and Snowflake cost, with per-service anomaly baselines watching it and allocation rules routing it to the same cost centers as everything else. Flat monthly price, free under $10K/month of spend. Setup is minutes, not a sprint — the connector docs, linked below, are short.

What we don't do: per-request traces. If your question is "show me the prompt that cost $3," that's an observability problem — Helicone and Langfuse are built for it and good at it. If your question is "put every AI dollar next to every cloud dollar and tell me the day something breaks," that's us.

Can I set a hard spending cap on the OpenAI API?

You can set budget limits and alert thresholds per project — check current platform docs for whether enforcement is a hard stop or a notification at your tier. Treat caps as a backstop, not a strategy: a cap that halts a production feature mid-request is an outage you scheduled in advance. Alerting on anomalies catches the runaway loop without taking your product down with it.

Do cached and batch tokens show up in usage reporting?

Cached input tokens are reported separately and billed at a discount; batch traffic is discounted too. Verify the current rates rather than trusting any blog post — including this one. If you're computing costs yourself, this is the most common source of reconciliation drift.

How do I attribute one request that serves multiple customers?

Pick a rule and write it down — split by tokens consumed per customer if you can measure it, evenly if you can't. An imperfect, documented rule beats a perfect argument. This is the same shared-cost problem cloud allocation has had for a decade, and the same answer applies.

Cloud and AI cost management on one ledger — OpenAI, Anthropic, AWS, and Snowflake. Free under $10K/month.

Try CloudQuell
← Back to all posts