BBramaDocs
Browse documentation

Codex (ChatGPT subscription) codex

The ChatGPT-account Codex backend — the same one the Codex CLI talks to — spoken with a ChatGPT subscription from the shared pool. Routes are codex/<model> over openai-responses (not openai-chat: this backend serves the Responses API only). Who may spend the account is the entitlement decision; the account itself is a subscription. Not to be confused with openai, which is the platform API paid by the deployment's own key.

How we sign in

A ChatGPT subscription credential comes out of the auth.openai.com OAuth sign-in — a browser, SSO, a consent screen. On this fleet that browser is Weles's, on Weles's own host: Weles exposes the sign-in as POST /reauth on its worker API, drives its stored sign-in row for the account, and writes the minted grant into the Skarbiec vault at provider:codex:<subscription>. The proof is never the login's exit status — it is the vault bundle at a higher revision and a refresh that now answers refreshed.

Three callers drive it: brama subscription login codex --by weles --reason "<why>" on the host Weles runs on (cli), the renewal loop that signs refused accounts back in without a human, and Brama Desktop. A signed donation through POST /v1/subscription-pool banks a grant minted elsewhere (donation).

The grant on disk

The vault item is the same document the Codex CLI writes as its auth.json — a tokens block plus bookkeeping:

{"tokens": {
  "access_token":  "<short-lived JWT>",
  "refresh_token": "<rotating refresh token>",
  "id_token":      "<OpenID identity JWT>",
  "account_id":    "<ChatGPT account id>"
 },
 "last_refresh": "2026-08-25T21:00:00+00:00"}

The blob states no expiry field of its own: the gateway reads expiry from the access token's JWT exp claim (src/gateway/oauth_refresh.rs). On refresh the gateway rewrites access_token, refresh_token and id_token in place and stamps last_refresh. The item carries the discovery tags (brama:subscription, brama:agent:<agent>, brama:provider:codex, brama:id:<id>); the agent tag only records who banked the account. An item that loses the brama:subscription mark keeps a working credential and stops existing for every listing — /readyz reports it under unroutable_accounts.

How a request presents it

At final use the gateway redeems the vault item through the local entitlements router and presents Authorization: Bearer <access_token> — plus the headers the ChatGPT backend requires and every other provider never sees: OpenAI-Beta: responses=experimental, originator: codex_cli_rs, and chatgpt-account-id read from the grant's own tokens.account_id (authorize_provider in src/providers/adapter.rs). No copy of the token outlives the request.

Refresh

Once a token expires the gateway posts grant_type=refresh_token with the stored refresh token and the public client id app_EMoamEEZ73f0CkXaXp7hrann to https://auth.openai.com/oauth/token, form-encoded. The answer is read whole. Completion and response handling follow the core request contract. Each brama maintain pass refreshes every active credential whose stated expiry has passed, single-flighted per subscription; a token is used until that instant. OpenAI rotates the refresh token on issue, so a refreshed grant that cannot be written back to the vault is a failed refresh — the provider already invalidated the one still stored. brama subscription refresh codex --reason "<why>" forces the same path now and journals the reason. Refreshing costs no plan quota.

When the provider disowns the grant

A refused refresh is definitive only on the provider's own evidence — invalid_grant, invalid_token, revoked, unauthorized_client, or a 401/403 with no stated reason. That records credential.state: needs_reauthorization with the provider's sentence as cause, blocks the account for 30 minutes, lists it burnt, and waits for the sign-in above. Everything else is transient and left for the next sweep (subscription, runbook).

Plan usage

ChatGPT publishes a free usage report at https://chatgpt.com/backend-api/wham/usage, issued to exactly the OAuth bearer the chat route already presents — reading it costs no quota. The ledger records each window with its instant and source (subscription).

Endpoints

Chathttps://chatgpt.com/backend-api/codex/responses
Model discoveryhttps://chatgpt.com/backend-api/codex/models, widening the pinned rows gpt-5.6-sol, gpt-5.6-luna, gpt-5.6-terra, gpt-5.5, gpt-5.3-codex-spark
Token endpointhttps://auth.openai.com/oauth/token (form wire)
Usage reporthttps://chatgpt.com/backend-api/wham/usage
Trusted hostchatgpt.com
Base URL overrideBRAMA_PROVIDER_CODEX_BASE_URL, validated with the refusals in provider