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¶
| Chat | https://chatgpt.com/backend-api/codex/responses |
| Model discovery | https://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 endpoint | https://auth.openai.com/oauth/token (form wire) |
| Usage report | https://chatgpt.com/backend-api/wham/usage |
| Trusted host | chatgpt.com |
| Base URL override | BRAMA_PROVIDER_CODEX_BASE_URL, validated with the refusals in provider |