A few months ago I got bitten by the thing every OpenAI API developer dreads: a retry loop I didn't catch in time turned into an overnight bill that was way bigger than it should've been. Nothing was hacked, nothing was leaked - just a bug, running unattended, for hours.

The annoying part wasn't the bill. It was realizing afterward that the information to catch it early was sitting right there in the usage dashboard the whole time. I just wasn't looking at it.

Dashboards don't save you

A dashboard only helps if you remember to open it. For a side project or a key you handed to a script, you won't. What you actually want is the inverse: don't make me check anything, tell me when something's wrong.

The actual mechanism

OpenAI's Admin API exposes a /usage endpoint that reports spend by day, scoped to an Admin key. The key detail that makes this safe to automate: you can issue that key with read-only usage access - it can't touch billing, can't touch other keys, can't touch org members. It can only tell you a number.

So the whole system is three pieces:

  1. A scheduled job (I used a Cloudflare Worker on a cron trigger, but any scheduler works) that calls the usage endpoint once a day.
  2. A stored threshold - the monthly $ ceiling you set once.
  3. A comparison against 50/80/100% of that ceiling, firing an email the first time each threshold is crossed in a billing period.

Roughly:

const usage = await getMonthlyUsage(adminKey); // read-only scope const pct = usage / ceiling; for (const threshold of [0.5, 0.8, 1.0]) { if (pct >= threshold && !alreadyNotified(threshold)) { await sendEmail(`You've hit ${threshold * 100}% of your $${ceiling} ceiling`); markNotified(threshold); } } 

That's genuinely most of it. The fiddly parts are billing-period boundaries (OpenAI's usage windows don't always line up cleanly with calendar months) and making sure alreadyNotified survives across cold starts if you're running this on something stateless.

If you'd rather not run the cron yourself

I packaged this exact workflow as a small tool called Fusebox - connect a read-only key, set a ceiling, get the three emails. Free tier covers it: https://fusebox.sifatsrk.workers.dev

Mostly wanted to write up the mechanism here in case it's useful even if you just build your own version - the scoped-key part is the piece I'd actually recommend copying regardless of whether you use a packaged tool for it.