> Markdown mirror of https://router.one/blog/llm-api-key-leak-spend-cap for AI assistants and crawlers. Router One is a unified, OpenAI-compatible LLM API gateway.
> Published: 2026-10-23 · Author: Router One Team

# Leaked API Key or Runaway Agent: What Actually Caps the Bill

_Leaked API key or runaway agent: what stops the bill. 2026 spend limits at OpenAI, Google, Cloudflare and OpenRouter vs Router One, and a first-hour runbook._

If an LLM API key leaks or an agent loops all night, only something that refuses the next request limits the bill: a spend limit enforced as requests run, prepaid funds that don't refill themselves, and a key you can delete. An alert reports money already spent, and a cap the platform can raise for you is not your cap. On Router One, a key's spend cap (maxSpend) is set by you, never raised automatically, and checked against in-flight reservations before each wallet-billed request runs; it does not cover requests your plan quota pays for, so on a plan account, deleting the key is what stops everything.

In 2026, OpenAI, Google Cloud, Cloudflare AI Gateway and OpenRouter all offer limits that block requests, and most of them document that spend can run past the limit before enforcement catches up.

This post is about the incident: what bounds the damage when a key is out or an agent is running away, and what to do in the first hour. For setting up per-key caps and attribution day to day, see [LLM cost tracking](https://router.one/llm-cost-tracking) and [one key per app, agent and environment](https://router.one/blog/track-llm-api-costs-per-key).

> **As of 2026-10-23**
>
> - OpenAI, Google Cloud, Cloudflare AI Gateway and OpenRouter all have spend limits that block requests. OpenAI's, Google's and Cloudflare's docs each say spend can run past the limit before enforcement catches up.
> - Google raises a Gemini API account's tier spending cap automatically once the account qualifies for the next tier.
> - Router One's wallet is prepaid, with no auto-recharge and no top-up API. Plans paid by card renew monthly at a fixed price until canceled.
> - A Router One key's spend cap is cumulative, set by you, and checked against in-flight reservations before a wallet-billed request runs. Requests covered by plan quota do not count toward it.
> - Deleting a key refuses new requests on it, which stops wallet and plan use alike.

> **Who this fits**
>
> - You run agents, scripts or a backend on LLM APIs and want the worst case of a leak or a loop bounded by money you chose to put in.
> - You can give each app, environment and agent its own key, and you would rather a request fail with HTTP 402 than keep billing.
>
> **Look elsewhere if**
>
> - You need a limit that resets every day, week or month on its own: a Router One key cap is cumulative. OpenAI and Google Cloud spend limits reset each month, and OpenRouter key limits and Cloudflare spend limits reset on a window you choose.
> - You need one limit for a group of keys: Router One limits spend per key, and the wallet balance is the only account-wide ceiling.
> - Your company must buy model access directly from OpenAI, Google or another vendor: use their limits in the table below, set below what you can afford to lose.

## Two 2026 incidents, and what failed

**€54k in about 13 hours (April 2026).** A Firebase browser key with no API restrictions was used for Gemini requests. Per the developer's [post on Google's AI developer forum](https://discuss.ai.google.dev/t/unexpected-54k-billing-spike-in-13-hours-firebase-browser-key-without-api-restrictions-used-for-gemini-requests/140262) (2026-04-15), an €80 budget alert and a cost anomaly alert both fired a few hours late; costs were around €28,000 by the time they reacted and settled above €54,000 as delayed cost reporting caught up. Google Cloud support denied their request for a billing adjustment. A Google staff member then asked them to send the details by email, and as of 2026-10-23 the thread shows no outcome. ([Hacker News discussion](https://news.ycombinator.com/item?id=47791871))

**About $18,000 overnight (April 2026).** Per [Tom's Hardware](https://www.tomshardware.com/tech-industry/artificial-intelligence/google-cloud-customer-wakes-up-to-usd18-000-bill-despite-usd7-budget-thanks-to-forgotten-public-api-key-attacker-put-in-60-000-requests-and-blasted-through-usd1-400-spending-cap) (2026-04-22), citing the developer's own posts, an attacker found a Cloud Run service he had published from AI Studio months earlier and sent requests through its public URL; the service called Gemini with his API key, stored in the container. The bill came to A$25,672.86, about US$18,400. The account had a budget of A$10 that only sent alerts, and during the incident Google automatically moved the account up a Gemini tier once its spend crossed the threshold, which raised its spending cap. Tom's Hardware reported that the charge appeared to have been waived. ([Hacker News discussion](https://news.ycombinator.com/item?id=47866293))

Google's own documentation explains both failures. Its [budgets page](https://docs.cloud.google.com/billing/docs/how-to/budgets) says: "Setting an alerts-only budget doesn't automatically cap Google Cloud or Google Maps Platform usage or spending." Its [Gemini API billing page](https://ai.google.dev/gemini-api/docs/billing) says that when an account meets the next tier's criteria, "you will be automatically upgraded to the next tier (subject to processing times)."

Two lessons follow. An alert tells you about spend that already happened. And a cap the platform can raise for you is not your cap: the limit that protects you is one that only you can raise, checked before the next request runs.

## Spend controls in 2026, side by side

The common claim that the big providers "only send alerts" is out of date: every platform below now has a limit that blocks requests. The differences are when it is checked, what it covers and who can lift it. Each row was checked against the vendor's own docs on 2026-10-23.

| Control | Can it stop spend? | When it is checked | Scope | Who can raise it | Says spend can overshoot? |
| --- | --- | --- | --- | --- | --- |
| OpenAI spend limit | Yes: requests get HTTP 429 with `organization_spend_limit_exceeded` or `project_spend_limit_exceeded` | Not instantaneous | One organization or one project, per monthly cycle | Anyone with permission to manage that organization or project | Yes: recorded spend "can slightly exceed the configured amount" |
| Gemini API tier cap (Google) | Yes: service paused for every project on the billing account until the next cycle | Against the billing account's monthly spend | A billing account, monthly | Google, automatically, when the account qualifies for the next tier | Not stated for tier caps; for its experimental project caps in AI Studio, Google says overages can happen |
| Google Cloud spend cap (announced as Public Preview, 2026-07-29) | Yes: new usage of the service is paused for the rest of the month unless you lift the cap | On estimated costs; enforcement "isn't instant" | One project and one eligible service (the Gemini API is one), per calendar month | Users with the spend-cap permission, such as a billing account administrator | Yes: "any cost overages are billed as normal" |
| Cloudflare AI Gateway spend limit | Yes: HTTP 429 by default, or a fallback model you configure | Before the request goes to the provider, against spend recorded so far; cost is recorded after each request completes (eventually consistent) | Per gateway rule, by provider, model or a custom metadata key, on a fixed or rolling window | Whoever manages the gateway's settings | Yes: a burst of concurrent requests "can briefly exceed the limit" |
| OpenRouter key limit and guardrails | Yes: the first limit reached blocks the request (403 at a guardrail cap) | At request time: workspace budgets first, then guardrails | A key's credit limit, optionally reset daily, weekly or monthly; guardrails per member or per key | The key's owner for key limits; the account owner or an organization admin for guardrails | For workspace budgets, spend "can run slightly over"; nothing stated for key limits |
| Router One wallet | Yes: HTTP 402 `INSUFFICIENT_BALANCE` on every key when the balance can't cover a wallet-billed request | Before each wallet-billed request runs | The whole account | Only a top-up you make; there is no auto-recharge | No: a request's charge never takes the balance below zero |
| Router One key cap (maxSpend) | Yes for wallet-billed requests: HTTP 402 `API_KEY_SPEND_CAP_EXCEEDED`; plan-covered requests don't count | Before each wallet-billed request runs, against the key's remaining cap minus in-flight reservations | One key, cumulative, never resets | You, in Dashboard → API Keys; nothing raises it automatically | No: a charge above the reservation is taken only from what the key has left |

Sources and exact wording, all checked 2026-10-23:

- **OpenAI.** Per OpenAI's [spend limits guide](https://developers.openai.com/api/docs/guides/spend-limits), an organization limit "applies to API traffic across all projects in the organization", a project limit "applies only to API traffic billed to that project", the limit resets with the next monthly cycle, and "Enforcement is not instantaneous, so recorded spend can slightly exceed the configured amount." OpenAI Support [confirmed on 2026-09-07](https://community.openai.com/t/project-limits-not-being-respected/1300634) that project limits are now supported.
- **Gemini API tiers.** Per Google's [Gemini API billing page](https://ai.google.dev/gemini-api/docs/billing) (last updated 2026-09-28), "Each tier has a maximum monthly spend limit", the caps are enforced "at the billing account level", and reaching one pauses service "for all projects linked to that billing account until the start of the next billing cycle". The same page offers experimental project caps in AI Studio and warns: "You may experience overages beyond your project cap if billing data hasn't processed before more charges are accrued."
- **Google Cloud spend caps.** Google [announced them in Public Preview on 2026-07-29](https://cloud.google.com/blog/topics/cost-management/new-early-anomalies-and-spend-caps-on-google-cloud-budgets), with the Gemini API among the eligible services. Per the [spend cap docs](https://docs.cloud.google.com/billing/docs/how-to/budgets-spend-caps), a cap covers "a single Google Cloud project and a single eligible service", its budget period is monthly, usage of that service is "paused for the remainder of the budget period" unless you lift the cap manually, and "the enforcement of spend caps isn't instant and any cost overages are billed as normal."
- **Cloudflare AI Gateway.** Spend limits shipped on [2026-06-05](https://developers.cloudflare.com/changelog/post/2026-06-05-spend-limits/). Per the [spend limits docs](https://developers.cloudflare.com/ai-gateway/features/spend-limits/), limits are evaluated before a request is sent to the provider, a blocked request gets a 429, "Spend limits are eventually consistent", and "a burst of concurrent requests can briefly exceed the limit before enforcement catches up."
- **OpenRouter.** Per OpenRouter's [spend controls guide](https://openrouter.ai/docs/guides/best-practices/spend-controls) and its [post on governing AI spend](https://openrouter.ai/blog/insights/governing-team-ai-spend) (updated 2026-09-24), a key's credit limit can reset daily, weekly or monthly, guardrails apply per member or per key, and "the first limit reached blocks the request"; per its [guardrails docs](https://openrouter.ai/docs/guides/features/guardrails), a guardrail budget block returns HTTP 403.
- **Router One.** Checked against the gateway's billing code on 2026-10-23; the details follow.

## How Router One bounds a leaked key or a runaway agent

### The wallet is prepaid and never refills itself

Wallet-billed requests draw down a balance you topped up. There is no auto-recharge and no top-up API, so a leak cannot pull in more money than you have already put in. A request's charge never takes the balance below zero: when the balance can't cover a wallet-billed request, that request gets HTTP 402 on any key of the account instead of building a debt. Plans are the one recurring charge. A plan paid by card renews each month at its fixed price until you cancel it, and a plan paid from the balance runs for one cycle; neither grows with usage.

### A cap you set on each key

A key's spend cap (maxSpend) limits what that key can charge to your wallet: once its cumulative wallet charges reach the cap, its wallet-billed requests return HTTP 402. Requests covered by your plan's quota draw from the account's shared plan quota and do not count toward any key's cap.

Three details matter in an incident:

- **It is yours.** You set, raise or clear it in Dashboard → API Keys, and nothing in the platform raises it for you, however much the account spends. Lowering it applies from the key's next request.
- **It is cumulative.** It counts everything the key has charged to the wallet since it was created and never resets on a calendar, so a leaked key does not get a fresh allowance next month.
- **It is checked before the request runs.** For each wallet-billed request, the gateway first reserves funds and checks the reservation against what the key has left: its cap, minus what it has already been charged, minus what its other in-flight requests have reserved. Parallel agent calls therefore can't all spend the same remainder. A request the key can't cover is refused with HTTP 402 before any model is called. When a request settles, the unused part of its reservation is released, and any cost above the reservation is charged only from what the key and the wallet still have left.

### What the client sees

A key at its cap answers with HTTP 402 and error type `billing_error`; on the OpenAI-style endpoints the code is `API_KEY_SPEND_CAP_EXCEEDED`, and on every endpoint the message starts with `api key spend cap reached` and says that topping up the wallet does not lift it. An empty wallet answers with HTTP 402 and the code `INSUFFICIENT_BALANCE`. When the response carries an `X-Billing-Funds-Reason` header, it tells the two apart. Both are 402s rather than 429s, so a client that backs off and retries on 429 does not treat a spend stop as a reason to keep trying. See [API error codes](https://router.one/llm-api-error-codes).

### Rate limits slow a loop; they don't cap it

Each key and each account also run under default request-per-minute and token-per-minute limits. They slow a runaway loop down, but over a night they do not bound what it spends. They are platform defaults rather than a per-key setting, and support raises them on request.

### Expiry dates

A key can carry an expiry date, after which it is refused. Give one to every key for a test, a demo or a short engagement, so a key that leaks later is already dead. An expired key still counts toward the account's active-key limit until you delete it.

## On a plan account, the cap is not the whole story

Pro, Max and Ultra quotas belong to the account, and every key on it draws from them. Requests the plan covers are not wallet charges, so they don't count toward any key's cap, and they keep working on a key whose cap is used up or while the wallet is empty. A leaked key on a plan account can therefore use up quota your own work was counting on. The money at risk is still bounded: the plan price you already paid plus the wallet balance. Lowering the cap does not stop plan-covered requests; deleting the key does.

## Spotting a leak or a runaway loop

- **Usage by key.** Dashboard → Usage ranks your keys by spend, tokens and requests for the chosen range. A key you don't expect near the top is the first sign.
- **Logs by key.** Filter Dashboard → Logs by the API key and look for models you never call, traffic at hours nobody works, or a run of near-identical requests seconds apart: an agent stuck in a loop.
- **Cap notices.** The console sends an in-app notice when a key reaches 80% of its maxSpend and again when it hits the cap. Key-cap notices are in-app only, and there are no webhook alerts.
- **Your own monitor.** A server can poll `GET /v1/balance` with any key on the account; a balance falling faster than your usual run rate is a signal. It reports the wallet only, not per-key spend or plan quota (see the [balance monitoring guide](https://router.one/blog/llm-api-balance-monitoring)).
- **What Logs won't show.** Requests refused before any model is called have no row: a 401 for a deleted or expired key, a 402 at a cap or with an empty wallet, a 429 from your own limits. After you delete a leaked key, a quiet log means the refusals are working.

## The first hour: an emergency runbook

1. **Delete the key** in Dashboard → API Keys. New requests on it are refused; requests already running finish and are billed. On a plan account, deleting is the only step that also stops plan-covered use; lowering the cap won't.
2. **Issue a replacement** with its own cap and, if the work is temporary, an expiry date. Put it in your secret store or server environment and redeploy, never back into client code.
3. **Read the damage.** Filter Dashboard → Logs by the deleted key for the incident window and export the rows to CSV: request IDs, models, tokens, costs and times are your incident record. Export the wallet ledger for the same range.
4. **Find the hole.** Check where the key lived: a front-end bundle, a mobile app, a public repository or its history, CI logs, a shared `.env` file, or a public endpoint that calls a model for anyone who finds it. Rotate every key that was stored in the same place.
5. **Check the wallet** with `GET /v1/balance` or the dashboard, and top up only after the leak is closed.
6. **Tell support** at support@router.one if you see charges you can't match to your own traffic, with the key name, the time window and the request IDs.

## Prevention: make the next leak small

- **Keep keys off clients.** Never ship a key in browser code, a mobile app or a public repository. A server-side key is only as private as the endpoint that uses it: the second incident above ran through the public URL of a service that held the key, so put authentication and your own per-user limits in front of anything that spends your key.
- **One key per app, environment and agent,** each with a cap sized to what that workload may spend before someone looks. A loop in staging then stops at the staging key's cap while production keeps running.
- **Expiry on short-lived keys:** tests, demos, CI jobs, a hackathon.
- **Limits inside the agent:** a cap on iterations, `max_tokens` on each call, and a stop on repeated identical tool calls. See [running AI agents in production](https://router.one/blog/ai-agents-production-guide).
- **Delete keys you no longer use.** An expired key still counts toward the account's active-key limit until you delete it.

Choosing a cap for each workload and reading spend per key are covered in [LLM cost tracking](https://router.one/llm-cost-tracking) and [one key per app, agent and environment](https://router.one/blog/track-llm-api-costs-per-key).

## What this does not do

- **No monthly reset.** A key's cap is cumulative. To give a workload a fresh allowance, raise its cap or rotate in a new key.
- **No limit for a group of keys.** Spend is limited per key; the wallet balance is the only account-wide ceiling.
- **No push alerts.** Key-cap notices are in-app only. There are no webhooks and no usage API, so usage data lives in the dashboard and its CSV exports.
- **No cover for plan quota.** Plan-covered requests sit outside every key's cap.
- **No refund to fall back on.** Purchased credits are non-refundable once added to your balance, except for billing errors on our side or where required by law ([refund policy](https://router.one/refund)). Usage on a leaked key is usage on your account ([terms](https://router.one/terms)), so the cap and the prepaid balance are the protection.

## FAQ

**What should I do in the first 10 minutes after an API key leaks?**
Delete the key rather than lowering its cap: a deleted key refuses new requests, while a capped key can still run requests your plan covers. Then issue a replacement from your secret store, filter Logs by the old key and export its rows to CSV, and find where it leaked before you top up again.

**Will I get a refund for usage from a leaked key?**
Don't count on one from any provider: in the €54k case above, Google Cloud support denied the developer's billing adjustment request. On Router One, usage on a leaked key is usage on your account, and purchased credits are non-refundable once added to your balance, except for billing errors on our side or where required by law. What protects you is the limit you set beforehand: a capped key and a prepaid balance.

**Does a key's spend cap stop every request on a leaked key?**
No. A key's spend cap (maxSpend) limits what that key can charge to your wallet: once its cumulative wallet charges reach the cap, its wallet-billed requests return HTTP 402. Requests covered by your plan's quota draw from the account's shared plan quota and do not count toward any key's cap. On a plan account, a leaked key at its cap can still use the plan's quota; deleting the key stops both.

**Can parallel requests or an agent loop push a Router One key past its cap?**
The gateway reserves funds for each wallet-billed request before it runs and checks them against the key's remaining cap, counting what the key's other in-flight requests have reserved, so concurrent calls can't all spend the same remainder. If a request's final cost comes in above its reservation, the extra is charged only from what the key and the wallet still have left.

**Does topping up the wallet lift a key's cap?**
No. The wallet and the key cap are separate: an empty wallet fails wallet-billed requests on every key with HTTP 402 and the code INSUFFICIENT_BALANCE, while a key at its cap returns HTTP 402 API_KEY_SPEND_CAP_EXCEEDED on its wallet-billed requests even with money in the wallet. Raise or clear the cap in Dashboard → API Keys.

**Should I rotate all my keys after one leaks?**
Rotate every key that was stored or deployed in the same place as the leaked one, such as the same repository, .env file, CI system or app build, because whatever exposed one likely exposed the rest. Keys that live elsewhere can stay; check their rows in Logs to be sure.

**Isn't a spending alert enough?**
An alert reports spend that already happened. In the €54k incident above, the alerts arrived hours late, after about €28,000 had already been charged; in the other, the budget only sent alerts, and Google raised the account's tier cap automatically during the incident. Use alerts to notice, and a limit that refuses requests to stop: a key cap only you can raise, a prepaid balance, and an expiry date on short-lived keys.

## Next steps

- Buying for a company: [Router One for companies](https://router.one/llm-api-procurement) covers payment, invoices and limits on one page.
- Rolling out coding agents with one capped key per developer: [Claude Code and Codex for a dev team](https://router.one/blog/claude-code-codex-team-rollout)
- Caps and attribution day to day: [LLM cost tracking](https://router.one/llm-cost-tracking) and [one key per app, agent and environment](https://router.one/blog/track-llm-api-costs-per-key)
- Watching the wallet from a server: [balance monitoring](https://router.one/blog/llm-api-balance-monitoring) and the [balance API reference](https://router.one/docs/account/getBalance)
- Reading 402 and 429 responses: [API error codes](https://router.one/llm-api-error-codes); how keys are stored: [security](https://router.one/security); plans and rates: [pricing](https://router.one/pricing)

Create your keys at [router.one](https://router.one/) and give each one a cap before you need it.

## See also

- Canonical page: https://router.one/blog/llm-api-key-leak-spend-cap
- For companies and builders: https://router.one/llm-api-procurement
- All blog posts: https://router.one/blog
- Models and per-model token rates: https://router.one/models (markdown: https://router.one/models.md)
- Pricing: https://router.one/pricing
- API docs (markdown): https://router.one/docs.md
- Company facts: https://router.one/facts/company.md
