First: a full window is not always a refusal
The funding decision is made once per call, in this order:- The plan pays while neither window is full.
- The wallet pays when a window is full and there is money in it — at list prices, as extra usage.
- Nothing pays, and the call is refused.
The refusal
A request refused by the gate answers429 with the whole quota in the body —
the same object Usage renders, so a client can show somebody
exactly what happened without inventing wording:
Retry-After on the response carries the same number of seconds as
retry_after_seconds. It is the latest reset among the limited windows, not
the earliest: clearing the 5-hour window while the weekly one is also full only
buys you a second refusal, so the wait quoted is the one that actually ends it.
The figure is rounded up, so waiting exactly that long is enough.
used_percent: 104 is not a bug. Admission does not hold an estimate back
against the cap, so you get the whole cap and the last call admitted can carry
the window a little past it.
A full window cannot be produced on demand on a shared account, so the body
above is the shape the gate builds — field for field, from the server’s own
renderer and the client contract tests it is checked against — with this
account’s timestamps in it rather than a captured response.
In the app
A refused request raises one warning toast, titled with the window that refused (5-hour limit reached) and reading “You are going faster than your plan
allows. Resets 12:19 PM UTC · in 4h 5m”. No modal, no checkout button: you have
not run out of money, and offering a payment page would be both wrong and
expensive. The usage screen refreshes behind it so the bars agree with what the
gate just saw.
A burst of parallel calls all failing at once still produces one toast.
In a chat
If the window fills before a turn starts, the turn does not start and the toast is all there is. If it fills while the agent is working, the run stops where it is and the assistant’s last message is the reason, in plain words:You have used your 5-hour limit. It frees up at 12:19 UTC on 2 Sep 2026.Everything the run had already done stays: the messages, the tool calls, the files it wrote on the machine. Nothing is rolled back. Send the message again after the reset and the agent picks up from a machine that still has its work on it.
In the API
A run stopped this way is not an HTTP error — the request that started it already succeeded. The run comes back terminal, with the reason on it:usage_window_exceeded and out_of_funds are deliberately different codes. One
is fixed by waiting and the other by paying, and sending somebody with money in
their account to a checkout helps nobody. Branch on the code, not on the
sentence. Errors lists both alongside every other code the API
returns.
What lifts it
What does not
- Retrying sooner. The window has not moved; you get the same refusal.
- A new chat, a new machine, a second harness. The windows belong to the account. Nothing about where the work runs changes them.
- Topping up, on a free account. The wallet needs a paid plan before it can hold anything, so on Free the only two answers are waiting and upgrading.
- Canceling and resubscribing. The window records what the account spent, not what the subscription did. A new subscription changes the cap; it does not erase the spend inside an open window.
Refusals that look alike
The second one is about request rate and has nothing to do with your allowance;
Errors covers it.
Usage
The windows, and how to read them before they fill.
Extra usage
What pays once a window is full.

