Skip to content

Latest commit

 

History

History
181 lines (136 loc) · 6.38 KB

File metadata and controls

181 lines (136 loc) · 6.38 KB

Codex

Reverse-engineered, undocumented API. May change without notice.

Overview

  • 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)

Endpoints

GET /backend-api/wham/usage

Returns rate limit windows, optional credits, and available on-demand rate limit resets.

Headers

Header Required Value
Authorization yes Bearer <access_token>
Accept yes application/json
ChatGPT-Account-Id no <account_id>

Response

{
  "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
  }
}

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.

GET /backend-api/wham/rate-limit-reset-credits

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).

Headers

Same as /wham/usage (Authorization: Bearer, Accept: application/json, optional ChatGPT-Account-Id).

Response

{
  "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.

Authentication

Credential Storage Locations

Codex CLI supports multiple credential storage modes:

  • file (default): CODEX_HOME/auth.json (or ~/.codex/auth.json by 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:

  1. CODEX_HOME/auth.json (when CODEX_HOME is set)
  2. ~/.config/codex/auth.json
  3. ~/.codex/auth.json
  4. 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.

WebUI Adapter Notes

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:

  1. CODEX_HOME/auth.json when CODEX_HOME is set
  2. ~/.config/codex/auth.json
  3. ~/.codex/auth.json

Multiple Codex Homes (WebUI)

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 as CODEX_HOME. Local ccusage logs follow the same home via homePath.
  • Detect scans ~/.codex, ~/.config/codex, and the process CODEX_HOME when those paths contain auth.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.

Token Refresh

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.