The Claude 5-hour server-side wall is three walls, not one
When a 429 hits at the 5-hour mark, three independent server-side conditions across two undocumented endpoints can have produced it. They emit the same generic error body. The Settings page renders only a slice. Here is where each layer lives in the JSON, with file and line references from the ClaudeMeter source.
The shape every other guide describes
Look up this topic and you will mostly find the same story: Claude Pro gives you about 45 messages in a 5-hour rolling window, when the utilization bar fills you get throttled, you wait about five hours, the bar drains, you are back. A single endpoint, a single field, a single timer.
That story is directionally right about layer 1 and silent about layers 2 and 3, which is exactly how you end up staring at a drained-looking 5-hour bar and eating 429s anyway.
Mental model swap, in one line
The 5-hour wall is not the condition five_hour.utilization >= 1. It is the condition (five_hour >= 1) AND NOT (overage allowed), where “overage allowed” is itself a three-flag AND across a different endpoint. ClaudeMeter polls both.
The four layers, laid out
Layer 1: the rolling 5-hour float
One weighted utilization fraction on /api/organizations/{org_uuid}/usage under five_hour. Slides continuously. Trips at >= 1.0 with a 429 from the rate limiter. resets_at slides forward as you send.
Layer 2: the overage switch
is_enabled on /overage_spend_limit. When true, requests continue after layer 1 and start consuming used_credits toward monthly_credit_limit. When false, layer 1 is a hard wall.
Layer 3a: out_of_credits
Flipped true when used_credits reaches monthly_credit_limit. Overage stops even with is_enabled true. ClaudeMeter renders 'BLOCKED' next to extra-usage.
Layer 3b: disabled_until
ISO 8601 timestamp that suspends overage until that wall-clock moment. Populated after payment failures or manual holds. Persists across 5-hour resets. Not mirrored on /usage.
The anchor fact: 0 endpoints, 0 flags, one 429 body
The full wall state on a ClaudeMeter poll is assembled from three calls running inside fetch_usage_snapshot. Each one can fail independently, each contributes a different layer:
If any of the three calls 5xx or 401, the snapshot drops that field but keeps the others. That is how ClaudeMeter can show “5-hour at 92 percent, extra-usage unknown” instead of going blank when the overage endpoint blips.
The struct that makes the wall legible
The overage response is where layers 2 and 3 live. The ClaudeMeter Rust struct is intentionally explicit about every field, so a rename from Anthropic breaks loudly instead of silently hiding a wall:
Three flags on this struct can wall you: is_enabled, out_of_credits, and disabled_until. Combined with layer 1 on the usage endpoint, that is four boolean-ish conditions feeding one 429.
How ClaudeMeter assembles the wall state
Three calls per 60-second cycle, merged into one snapshot, rendered as one menu bar badge.
One poll cycle
/usage poll
five_hour float + resets_at
/overage_spend_limit poll
is_enabled, out_of_credits, disabled_until
/subscription_details poll
next_charge_date, payment method
Merge into UsageSnapshot
one struct, three layers
Render three-layer state
menu bar + CLI --json
What every flag in the wall feeds
Flags in, wall state out
disabled_until, the field nobody else mentions
This is the stickiest layer. When populated, the server treats overage as disabled until that wall-clock moment, regardless of is_enabled or the monthly credit math. We see it set after payment failures (a declined card pushes the field forward a day or two, giving Stripe retry logic a runway) and during what we believe are Trust & Safety holds. It does not appear on the Settings page bar.
The CLI surfaces it as a “until <date>” suffix on the extra-usage line:
If your 5-hour bar drains and your next message still 429s, open the menu bar and look at the extra-usage line. If it says “until Fri Apr 26”, waiting for 5 hours will not help you. Waiting for Friday or fixing the underlying billing issue will.
Reproduce the three layers in three curls
You do not need ClaudeMeter to verify this. With a logged-in claude.ai session cookie, you can hit all three endpoints by hand:
That specific payload is the nastiest combination: quota at 100 percent, monthly credit cap hit, and overage suspended until a later date. All three walls up. The 429 body you get from the next prompt is still the same generic message, which is why reading the JSON is the only way to know which clock to watch.
Before and after
What most articles describe
You hit 100 percent of the 5-hour window, you get 429s, you wait about 5 hours, the window rolls, you work again. A single boundary with a single timer.
- Implies one endpoint, one field, one timer
- Implies waiting solves it
- Ignores overage, credit cap, and disabled_until
- Ignores that 429 messages do not name the layer
What the server actually enforces
Three layers across two endpoints. Layer 1 is five_hour.utilization on /usage. Layer 2 is is_enabled on /overage_spend_limit. Layer 3 is out_of_credits OR disabled_until on the same endpoint. A 429 can come from any one, with the same error body.
- Two endpoints minimum to reconstruct state
- Four flag fields any one of which walls you
- Independent clocks per layer
- Field names verifiable in src/models.rs and src/api.rs
The full wall traversal, step by step
Layer 1 trips: five_hour.utilization hits 1.0
The 5-hour bucket on /api/organizations/{org_uuid}/usage crossed the weighted ceiling. The Settings page bar pins. Any new request from this org gets 429 from the rate limiter. If overage is off, the request stops here and you see the familiar 'try again later' message with resets_at buried in the payload.
Layer 2 decides: overage_spend_limit.is_enabled
If is_enabled is false, layer 1 is your wall. Nothing you do below matters, you wait for resets_at. If is_enabled is true, the request continues into metered billing and used_credits starts climbing. The Settings page does not render a badge for this switch; the flag lives on the overage endpoint only.
Layer 3 gates: out_of_credits or disabled_until
Even with is_enabled true, two other flags can block overage: out_of_credits (monthly cap hit) and disabled_until (a wall-clock timestamp the server uses to suspend overage after payment failures or manual holds). ClaudeMeter flags this by appending 'BLOCKED' and 'until <date>' to the extra-usage line (format.rs lines 26 and 36).
Reset semantics differ by layer
Layer 1 slides forward as your earliest unexpired message ages out. Layer 2 resets at next_charge_date from subscription_details (the billing cycle boundary). Layer 3's disabled_until carries its own timestamp and can persist across 5-hour resets and billing cycles. The three clocks are independent.
Reading server truth means three calls, not one
ClaudeMeter polls /usage, /overage_spend_limit, and /subscription_details in the same cycle (api.rs lines 10 to 60). Local-log tools see none of them. That is why a tool that counts tokens in ~/.claude/projects can tell you what Claude Code burned on disk and still miss the wall entirely.
Why the naive mental model gets you surprised 429s
The traps a single-endpoint view creates
- A 429 at the 5-hour mark is not one event. It is whichever layer trips first, and the error body does not name the layer.
- If you only poll /usage, you cannot distinguish 'quota pinned' from 'overage disabled by payment failure'. Both return generic 429s.
- disabled_until can outlast the 5-hour reset. Your 5-hour bar drains, you still 429 because layer 3 is still armed.
- out_of_credits flips true silently when monthly overage hits the cap. Nothing in /usage reflects it.
- ccusage and Claude-Code-Usage-Monitor do not call either endpoint. They read JSONL files under ~/.claude/projects and cannot see server state.
The numbers from the implementation
Drawn from the ClaudeMeter source, not invented benchmarks.
Local-log tools vs ClaudeMeter for wall state
Why counting tokens in ~/.claude/projects cannot tell you where the wall is.
| Feature | Local-log tools | ClaudeMeter |
|---|---|---|
| Reads /api/organizations/{org}/usage | No (reads local JSONL) | Yes, every 60 seconds |
| Reads /api/organizations/{org}/overage_spend_limit | No | Yes, same cycle |
| Surfaces out_of_credits | No | Yes, shown as BLOCKED |
| Surfaces disabled_until | No | Yes, shown as 'until <date>' |
| Knows server-weighted utilization | No (local tokens only) | Yes, reads the float the rate limiter checks |
| Handles cookie paste | N/A (no cookie) | Zero, extension forwards existing session |
Common myths to drop
Why a local token counter cannot reconstruct this
ccusage and Claude-Code-Usage-Monitor read ~/.claude/projects/**/*.jsonl and sum token usage from your local Claude Code sessions. The number they produce is real, but it is the answer to a different question. It does not include the server-applied weighting (peak-hour multiplier, attachment cost, model factor, tool-call factor) that feeds the five_hour float. It does not include any state from /overage_spend_limit. It cannot see out_of_credits or disabled_until. That is the entire reason ClaudeMeter exists: the only place the three-layer wall is visible is on the two undocumented Anthropic endpoints, and you need the browser session cookies to hit them.
The honest caveat
Both endpoints (/usage and /overage_spend_limit) are internal and undocumented. Anthropic can rename fields, remove buckets, or change semantics in any release. ClaudeMeter deserializes each response into a strict Rust struct (src/models.rs), so any breaking change surfaces as a loud parse error in the menu bar instead of a silent wrong number. Until that happens, this is the shape. These are the fields. This is the wall.
Watch the three-layer wall live
ClaudeMeter sits in your macOS menu bar, polls all three endpoints every 60 seconds, and shows you which layer is binding right now. Free, MIT licensed, no cookie paste, reads what the rate limiter reads.
Install ClaudeMeterFrequently asked questions
What is the Claude 5-hour server-side wall?
It is the moment a rolling 5-hour utilization float on the claude.ai server crosses the bucket ceiling and the rate limiter starts returning 429 to your org. The field that trips it is five_hour.utilization on GET /api/organizations/{org_uuid}/usage. The wall lives on the server, not in the client. ClaudeMeter polls that endpoint every 60 seconds so you see the float move in real time instead of guessing from a local token count.
If I have overage enabled, does the wall still stop me?
Sometimes. Overage lives on a different endpoint: /api/organizations/{org_uuid}/overage_spend_limit. That response has three fields that can block you: is_enabled (master switch), out_of_credits (monthly cap hit), and disabled_until (a wall-clock timestamp when overage is suspended, independent of the other two). If any one of those blocks, the 5-hour wall is hard again. The /usage endpoint does not mirror these flags, which is why the Settings page can look healthy while your next prompt 429s.
What does disabled_until mean?
It is an ISO 8601 timestamp on the overage_spend_limit response. While Utc::now() is less than disabled_until, the server refuses overage spend even if is_enabled is true and you are under the monthly credit limit. We see it populated after payment failures and during manual Trust & Safety holds. ClaudeMeter reads it at src/models.rs line 37 and the CLI appends an 'until Fri Apr 26' suffix when it is set (format.rs lines 35 to 38).
Why does my 429 message not tell me which layer tripped?
Because the server returns the same generic message whether the 5-hour quota pinned, the overage hit its monthly cap, or the overage is suspended by disabled_until. Only the JSON from the three usage endpoints distinguishes them. A client that reads just /usage sees five_hour at 100 percent and assumes quota. A client that reads /usage plus /overage_spend_limit can tell you which layer is actually walling you off.
Why does hitting the wall feel stickier than 5 hours?
Two reasons. First, the 5-hour window is a rolling boundary, not a fixed timer, so each new message you attempt pushes the earliest-unexpired-message pointer forward and resets_at slides with it. Second, if your overage is off, on out_of_credits, or suspended via disabled_until, the 5-hour reset does not unlock you because the 5-hour bucket was never the binding constraint, the overage layer was. Both layers have to clear.
Can ccusage or Claude-Code-Usage-Monitor tell me any of this?
No. Those tools read ~/.claude/projects/**/*.jsonl and estimate token spend from local Claude Code sessions. They do not call /api/organizations/{org}/usage, they do not call /api/organizations/{org}/overage_spend_limit, and they cannot see the server-weighted utilization float the rate limiter checks. They answer a different question (what Claude Code burned locally) from the one the wall answers (what the server is counting against your org).
Where is out_of_credits exactly?
It is a boolean on the overage response. See src/models.rs line 39, `#[serde(default)] pub out_of_credits: bool,`. When the monthly credit pool is exhausted, the server sets it to true and starts 429ing overage requests. The CLI shows it as 'BLOCKED' next to the extra-usage line (format.rs line 26).
How do I read all three layers myself?
GET /api/organizations/{org_uuid}/usage returns the 5-hour and weekly buckets. GET /api/organizations/{org_uuid}/overage_spend_limit returns overage state including out_of_credits and disabled_until. GET /api/organizations/{org_uuid}/subscription_details returns payment method and next charge date, useful for guessing why disabled_until got populated. Pass your logged-in claude.ai Cookie header to each.
Why does ClaudeMeter call all three endpoints, not just usage?
Because the full wall state is not on /usage. See api.rs lines 16 to 60: three serial calls, each with its own error handling, each producing one field on the UsageSnapshot struct. Dropping any one of them produces a snapshot that can say '5-hour at 42 percent' while the next prompt still 429s.
Does the wall reset at a fixed wall-clock time?
The 5-hour layer slides continuously; resets_at is whichever oldest-message-ageing-out event is next. The weekly buckets roll at a fixed time per account, usually when the week ticks over in your billing zone. The overage layer resets at the billing cycle boundary (see subscription_details.next_charge_date), not at 5 hours. So 'when does my wall lift' depends on which layer is binding right now.
What does the 5-hour wall look like on Max 5x and Max 20x?
The same shape, different ceiling. The five_hour.utilization field is identical, weighted more generously on Max, and the wall still trips at utilization >= 1.0. Max plans also populate seven_day_opus and seven_day_sonnet more often, so you can wall on a narrower model-specific bucket while the headline 5-hour is fine. ClaudeMeter surfaces each bucket that exists on your org without needing plan detection.
Keep reading
The 5-hour quota is one float on a sliding clock, not 45 messages
Where five_hour.utilization and resets_at live in the JSON, how the rolling window actually moves, and why the 45-message number is an average over an unknown distribution.
The rolling window cap is seven windows, not one
The usage endpoint returns seven utilization buckets, not two. Five-hour is the loud one; weekly, per-model, OAuth-apps, and two internal-named buckets all trip independently.
ClaudeMeter vs ccusage
Local token counters cannot see server buckets or overage flags. They answer a different question from the one the wall answers.
Seeing a layer we do not cover?
If your overage response has a flag we did not name, or disabled_until fires on an event we did not describe, send it. We map every variant we see.