OpenAI Codex wham/usage API — Unofficial Reference
Disclaimer: This is an undocumented internal API used by the Codex CLI and related tools. It is not part of the OpenAI Platform API, carries no stability guarantee, and may change without notice.
GET https://chatgpt.com/backend-api/wham/usage
Requires a ChatGPT OAuth access token from ~/.codex/auth.json (written by codex login).
Authorization: Bearer <access_token>
ChatGPT-Account-Id: <account_id>
account_id can be extracted from the https://api.openai.com/auth claim inside the JWT id_token, or read directly from tokens.account_id in auth.json.
Token refresh endpoint:
POST https://auth.openai.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&client_id=app_EMoamEEZ73f0CkXaXp7hrann&refresh_token=<token>
{
"used_percent": 9, // 0–100; null when not tracked
"limit_window_seconds": 604800, // duration: 18000 = 5 h, 604800 = 7 d
"reset_after_seconds": 584279, // seconds until reset (from request time)
"reset_at": 1784530149 // absolute unix timestamp of reset
}Do not assume primary_window = 5-hour and secondary_window = weekly.
Use limit_window_seconds to identify the type:
limit_window_seconds |
meaning |
|---|---|
18000 |
5-hour rolling window |
604800 |
7-day (weekly) window |
Plan shape varies by subscription. For example:
- Plus / Pro:
primary_window= 5-hour (18000 s),secondary_window= weekly (604800 s) - Team:
primary_window= weekly (604800 s),secondary_window= null
This means secondary_window may be null for plans that only enforce a weekly cap.
Treat the window duration as the server's declared limit duration, not as proof of a calendar- or fixed-period reset. On one Team-plan account observed in July 2026, the 7-day window behaved as follows:
- While
used_percentwas zero,reset_after_secondsstayed close to 604800 andreset_atadvanced with every poll, always remaining about seven days ahead. - After usage resumed,
reset_atbecame a nearly fixed timestamp. used_percentsubsequently dropped from 55% to 0%, and later from 61% to 0%, only hours apart—not one week apart.
The reason for this server-side behavior is unknown. used_percent, allowed, and limit_reached remain useful for the current enforcement state, but clients should not derive a fixed next weekly reset, send rollover alerts, or promise a seven-day usage budget solely from reset_at / reset_after_seconds. Keep local history if a longer-term usage view is needed.
GET https://chatgpt.com/backend-api/wham/rate-limit-reset-credits
Authorization: Bearer <access_token>
ChatGPT-Account-Id: <account_id>
Returns the inventory of banked rate-limit resets (credits that can be used to unblock an exhausted window early). The same data appears as rate_limit_reset_credits.available_count in the main usage response.
- The Codex CLI polls this endpoint roughly every 60 seconds during active sessions.
- The endpoint is also used by
codex app-server(JSON-RPC viaaccount/rateLimits/read). - When
allowedisfalse, the account is blocked regardless of window percentages. used_percentcan exceed 100 in edge cases; clamp to [0, 100] before display.
These open-source projects reverse-engineered this endpoint:
- steipete/CodexBar — macOS menu bar app;
docs/codex.mdis the most complete existing documentation - fberbert/codex-widget — Linux desktop widget; cleanest Python implementation of window-type detection
- timm-u/pi-usage — pi coding agent extension; TypeScript interface definitions for the full response shape
{ "user_id": "user-...", "account_id": "...", "email": "user@example.com", "plan_type": "team", // "free" | "plus" | "pro" | "team" | "enterprise" "rate_limit": { "allowed": true, // false when the account is blocked "limit_reached": false, "primary_window": { // see Window shape below "used_percent": 9, "limit_window_seconds": 604800, "reset_after_seconds": 584279, "reset_at": 1784530149 // unix timestamp }, "secondary_window": null // null when plan has only one window }, // Per-model caps (e.g. "Codex Spark 5-hour", "Codex Spark Weekly"). // null when no model-specific limits apply. "additional_rate_limits": [ { "id": "codex-spark", // stable id "title": "Codex Spark 5-hour", "primary_window": { /* Window */ }, "secondary_window": { /* Window */ } } ] | null, // Separate limit for the Codex code-review feature. "code_review_rate_limit": { "primary_window": { /* Window */ } } | null, "credits": { "has_credits": false, "unlimited": false, "overage_limit_reached": false, "balance": null, // string or null, e.g. "$4.20" "approx_local_messages": null, "approx_cloud_messages": null }, "spend_control": { "reached": false, "individual_limit": null }, // Banked rate-limit resets (see companion endpoint below). "rate_limit_reset_credits": { "available_count": 3 }, "rate_limit_reached_type": null, // unknown enum; non-null when limit_reached "promo": null, "referral_beacon": null }