Reverse-engineered, undocumented API. May change without notice.
- Protocol: REST (plain JSON)
- Base URL:
https://chatgpt.com - Auth provider:
auth.openai.com(OAuth 2.0) - Client ID:
app_EMoamEEZ73f0CkXaXp7hrann - Percentages: integers (0-100)
- Timestamps: unix seconds
- Window durations: seconds (18000 = 5h, 604800 = 7d)
Returns rate limit windows, optional credits, and available on-demand rate limit resets.
| Header | Required | Value |
|---|---|---|
| Authorization | yes | Bearer <access_token> |
| Accept | yes | application/json |
| ChatGPT-Account-Id | no | <account_id> |
Both rate_limit windows are enforced simultaneously — hitting either limit throttles the user.
OpenUsage floors the remaining credit balance to a whole number and displays its fixed USD
equivalent at $0.04 per credit. For example, 820.6969075 renders as
$32.80 · 820 credits. The credit balance is unbounded; the API does not provide a maximum.
When available, OpenUsage displays the on-demand reset count as the first detail text metric,
for example 1 available.
Returns the banked reset credits ("reset stash") — use-it-or-lose-it grants that can
zero a usage window. Each credit expires independently. OpenUsage fetches this endpoint only
when /wham/usage reports rate_limit_reset_credits.available_count > 0 (no credits, no
extra request).
Same as /wham/usage (Authorization: Bearer, Accept: application/json, optional
ChatGPT-Account-Id).
{
"credits": [
{
"id": "rc_123",
"status": "available", // only "available" credits are shown
"expires_at": "2026-07-03T20:00:00Z" // ISO 8601 — when this credit lapses
}
],
"available_count": 1
}For each available credit (soonest expiry first), OpenUsage shows a row — in both the WebUI
dashboard and the ou-status CLI — with the exact expiry date and a live countdown,
colored by urgency: expired · ends today (≤1d) · soon (≤3d) · this week (≤7d) · normal. Decoding is tolerant — a malformed or unparseable
credit is skipped — and a failure of this secondary endpoint never breaks the usage card.
Codex CLI supports multiple credential storage modes:
- file (default):
CODEX_HOME/auth.json(or~/.codex/auth.jsonby default) - keyring: OS keychain/credential manager entry (service name
Codex Auth) - auto: keyring first, fallback to file
- ephemeral: memory-only (no persistence)
For keyring/auto, Codex may not keep auth.json on disk. If keyring save succeeds, Codex removes the fallback auth.json.
OpenUsage Codex plugin auth lookup order:
CODEX_HOME/auth.json(whenCODEX_HOMEis set)~/.config/codex/auth.json~/.codex/auth.json- macOS keychain service
Codex Auth(fallback)
If file-based OAuth credentials are missing, invalid, or fail with an auth/session error during refresh or usage lookup, OpenUsage tries the macOS keychain fallback. Non-auth usage failures, such as server errors or invalid responses, are shown directly.
Keychain fallback is available on macOS only.
The Linux WebUI runs the original plugins/codex/plugin.js through a local host adapter instead of rewriting the provider logic.
Because Linux WebUI does not use the macOS keychain, the adapter relies on file credential paths:
CODEX_HOME/auth.jsonwhenCODEX_HOMEis set~/.config/codex/auth.json~/.codex/auth.json
WebUI tracks multiple homes through the shared Provider Accounts feature (Settings → Provider Accounts; API /api/provider-accounts). Pick Codex, then detect or add homes.
- With no configured accounts for Codex, behavior stays a single provider id
codex. - With one or more accounts, each is registered as
codex:<slug>and probed with that home injected asCODEX_HOME. Local ccusage logs follow the same home viahomePath. - Detect scans
~/.codex,~/.config/codex, and the processCODEX_HOMEwhen those paths containauth.json.
The original plugin may refresh OAuth tokens and write the updated credential JSON back to the same file source. Browser cookies are not used.
Expected auth payload shape (file or keychain JSON value):
{
"OPENAI_API_KEY": null, // legacy API key field
"tokens": {
"access_token": "<jwt>", // OAuth access token (Bearer)
"refresh_token": "<token>",
"id_token": "<jwt>", // OpenID Connect ID token
"account_id": "<uuid>" // sent as ChatGPT-Account-Id header
},
"last_refresh": "2026-01-28T08:05:37Z" // ISO 8601
}Note: Codex also stores MCP OAuth tokens in
~/.codex/.credentials.json(or keyring), but that is separate from ChatGPT CLI auth used by this plugin.
Access tokens are short-lived JWTs. Refreshed when last_refresh is older than 8 days, or on 401/403.
POST https://auth.openai.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&client_id=app_EMoamEEZ73f0CkXaXp7hrann
&refresh_token=<refresh_token>
Response returns new access_token, and optionally new refresh_token and id_token.
{ "plan_type": "plus", // plan tier "rate_limit": { "primary_window": { "used_percent": 6, // % used in 5h rolling window "reset_at": 1738300000, // unix seconds "limit_window_seconds": 18000 // 5 hours }, "secondary_window": { "used_percent": 24, // % used in 7-day window "reset_at": 1738900000, "limit_window_seconds": 604800 // 7 days } }, "code_review_rate_limit": { // separate weekly code review limit (optional) "primary_window": { "used_percent": 0, "reset_at": 1738900000, "limit_window_seconds": 604800 } }, "credits": { // purchased credits (optional) "has_credits": true, "unlimited": false, "balance": 820.6969075 // remaining credits }, "rate_limit_reset_credits": { // on-demand resets (optional) "available_count": 1 } }