Skip to content

v1.3.0: fix all-accounts Usage API 403 (deprecated /wham/usage → /codex/usage)#14

Open
Mr-V1be wants to merge 1 commit intoguard22:mainfrom
Mr-V1be:evgeniy/release-v1.3.0-codex-usage-endpoint
Open

v1.3.0: fix all-accounts Usage API 403 (deprecated /wham/usage → /codex/usage)#14
Mr-V1be wants to merge 1 commit intoguard22:mainfrom
Mr-V1be:evgeniy/release-v1.3.0-codex-usage-endpoint

Conversation

@Mr-V1be
Copy link
Copy Markdown
Contributor

@Mr-V1be Mr-V1be commented Apr 20, 2026

Summary

Live fix for "Usage API returned 403" showing up on every account in the dashboard, plus the cascading "No available accounts after filtering" loop in OpenCode's rotation.

Root cause

OpenAI deprecated GET /backend-api/wham/usage for Codex-scope OAuth tokens. It now returns 403 for every token — including active ChatGPT Pro/Business plans that chat fine through /codex/responses. The plugin interpreted those 403s as "auth invalid", flipped authInvalid: true on every account, and the rotation layer then filtered all of them out → 503 noEligibleAccounts.

Verified by direct curl with the same token that routes chat successfully:

GET https://chatgpt.com/backend-api/wham/usage    → 403 Cloudflare
GET https://chatgpt.com/backend-api/codex/usage   → 200 { plan_type: "pro", rate_limit: { primary_window: {...}, secondary_window: {...}, ... } }

The response schema on /codex/usage is a superset of what this plugin already parses (rate_limit.primary_window / secondary_window with used_percent, reset_at, etc.) — no parser changes required.

Changes

  • usage-limits: switch to /backend-api/codex/usage (live endpoint). Add originator: codex_cli_rs header — without it Cloudflare intermittently returns an HTML challenge instead of JSON.
  • usage-limits: retry up to 3× with exponential backoff when the response is a Cloudflare HTML 403 challenge (per-IP bursts trigger those; proper JSON errors are not retried).
  • usage-limits: split 401 vs 403 classification. 401 still hard-fails as auth invalid; 403 falls through to the probe path without marking the token invalid.
  • limits-refresh: auto-clear authInvalid / authInvalidatedAt on any successful refresh, so stale flags set by the pre-fix 403 storm recover themselves on the next refresh.
  • refresh-queue: lower default concurrency 20 → 5. 20 reliably trips Cloudflare's per-IP gate on /codex/usage; 5 completes a full 22-account refresh in a few seconds with zero challenges. OPENCODE_MULTI_AUTH_REFRESH_QUEUE_CONCURRENCY still overrides.
  • probe-limits: honor CODEX_CLI_BIN env var so operators can point the spawn probe at a newer codex binary (e.g. the VS Code-extension build that already has HTTP fallback when /responses WSS hits Cloudflare).

Upgrade notes

None required. Drop-in, behavior-preserving for accounts that were already healthy. Operators who bumped concurrency past 20 via env var are unaffected (cap unchanged at 20).

After installing, the dashboard's next Refresh limits (all) will clear every stale authInvalid: true flag set by pre-fix 403 classifications. Accounts that were mistakenly sidelined will re-enter rotation automatically.

Test plan

  • npm run lint (tsc --noEmit) — clean
  • npm run build — dist regenerated
  • Manual curl verification: /wham/usage 403, /codex/usage 200 with the same token
  • Dashboard "Refresh limits (all)" — 22/22 accounts reported 0 errors, real primary_window.used_percent surfaced for every account
  • OpenCode chat routing — no more "No available accounts after filtering"; rotation picks a live account on the first attempt

Fix "Usage API returned 403" across all accounts and recover rotation health.

Root cause: OpenAI deprecated /backend-api/wham/usage for Codex OAuth tokens
(returns 403 for every token, including active ChatGPT Pro). The plugin then
marked every account as authInvalid and stopped routing ("No available
accounts after filtering").

Changes:
- usage-limits: switch to /backend-api/codex/usage (live endpoint) with the
  `originator: codex_cli_rs` header to bypass Cloudflare default gating.
- usage-limits: retry up to 3 times with backoff on Cloudflare HTML 403
  challenges (per-IP bursts trigger those; proper JSON errors are not retried).
- usage-limits: split 401 vs 403 classification — 403 falls through to the
  probe path instead of marking the token as invalid.
- limits-refresh: auto-clear authInvalid / authInvalidatedAt on any
  successful refresh so stale flags from earlier 403s recover automatically.
- refresh-queue: default concurrency lowered 20 -> 5 to stay below
  Cloudflare's /codex/usage per-IP threshold. The
  OPENCODE_MULTI_AUTH_REFRESH_QUEUE_CONCURRENCY env override is unchanged.
- probe-limits: honor CODEX_CLI_BIN env var so operators can point the
  spawn probe at a newer `codex` binary.
- Rebuild dist/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant