How to monitor AI API spend before it becomes a surprise

Token spend accrues invisibly inside loops. By the time the invoice arrives you cannot tell which feature caused it — which is why the fix is not a fancier dashboard, it is logging usage per request.

In short: You cannot control what you do not measure, and token spend is invisible by default. Three levels matter: the provider dashboard for totals, per-request usage logging for attribution, and a threshold alert for surprises. Logging input_tokens and output_tokens separately is what makes the data actionable.

Three levels of monitoring

LevelTells youLimitation
Provider dashboardAccurate totals, per modelNo attribution to features or customers
Per-request loggingWhich feature and model drove itRequires one wrapper in your code
Threshold alertsThat something changed todayOnly useful if the baseline is right

Most teams have the first and assume it is enough. It is not — it tells you the bill went up, not why.

The one wrapper that does most of the work

import time, json

def tracked_call(client, model, feature, **kwargs):
    t0 = time.time()
    resp = client.messages.create(model=model, **kwargs)
    usage = resp.usage
    log({
        "ts": time.time(),
        "feature": feature,
        "model": model,
        "input_tokens": usage.input_tokens,
        "output_tokens": usage.output_tokens,
        "latency_ms": int((time.time() - t0) * 1000),
    })
    return resp

Log input_tokens and output_tokens separately. Output costs several times more per token, so a blended figure hides exactly the signal you need.

Turn tokens into money

RATES = {                      # USD per 1M tokens — keep in config, not in code
    "claude-sonnet-5": (1.0, 5.0),
    "claude-haiku-4-5": (0.5, 2.5),
}

def cost_of(model, in_tok, out_tok):
    i, o = RATES.get(model, (0, 0))
    return in_tok / 1_000_000 * i + out_tok / 1_000_000 * o

Check the current numbers on the price index — rates move, so hard-coding them in your billing code is how cost reports silently drift out of reality.

Alert on change, not on totals

A fixed threshold ("alert above $500/month") only fires when it is already expensive. Alert on day-over-day change instead — a 3x jump on a Tuesday is the shape of a bug, and it is worth knowing about even when the absolute number is small.

Cost note. The two configurations that prevent most horror stories: a top-up ceiling at the account level, and a max_tokens on every request. Neither replaces monitoring, but together they bound the damage.

What to review weekly

FAQ

Why is API spend so hard to control?

Because it is invisible by default. Unlike a subscription, cost accrues per token inside a loop, and by the time the invoice arrives you cannot tell which feature caused it. Logging usage per request is the only fix.

What should I log?

Input tokens and output tokens separately, plus model, feature or endpoint name, and a request ID. Separate is important: output costs several times more, so a blended number hides the thing you most need to see.

How do I catch a runaway bill early?

Alert on day-over-day change rather than a fixed threshold. A 3x jump on a Tuesday matters even if the absolute number is still small — that is the shape of a bug, not of growth.

Is the provider dashboard enough?

It gives accurate totals but weak attribution. You will see the bill went up, not that it was the new extraction job on model X. Per-request logging is what turns a total into an answer.

What is the cheapest way to start?

Wrap your client in one function that logs usage, and aggregate into a daily table. That single change covers most of what teams need before they reach for a dedicated observability tool.

Related

Get API access