Connect a third-party API to Codex without ChatGPT sign-in

Start with visual setup in CC Switch. When manual setup is needed, this page covers API keys, Base URLs, Client and CLI, plus 401, 404, and stale-route checks.

Independent setup notes, not affiliated with OpenAI. Field meanings follow public config conventions; verify against your local Codex version.

Choose your situation first — do not mix all three paths

Many 401 and no-effect reports come from mixed auth methods. Follow only the path that matches what you have.

First: ChatGPT login vs API key

Only one credential is active at a time. CLI and Client share it; logging out of one clears both.

CompareChatGPT loginAPI key
How you sign incodex login (browser)printenv … | codex login --with-api-key
BillingCodex allowance on your ChatGPT planAPI / gateway usage (separate from plan credits)
Best forSubscription allowance, no custom gatewayCI, custom base_url, compatible gateways, this site
Is export alone enough?N/ANo — export does not auto-login; use explicit login or a provider

Check the active credential with codex login status. Clear with codex logout.

Three ways to attach a key

Platform keys or compatible gateway keys both work. Custom routes need a Responses-capable endpoint (since Feb 2026, wire_api only supports responses).

CLI: pipe into login (most common)

Feed the key on stdin. It lands in the credential store and later sessions bill as API usage. Avoid echoing secrets into shell history when you can.

export OPENAI_API_KEY="sk-..."
printenv OPENAI_API_KEY | codex login --with-api-key
codex login status

auth.json / OS keyring

file mode writes ~/.codex/auth.json; keyring uses the OS store. CLI and Client share the cache. Treat it like a password.

{
  "OPENAI_API_KEY": "sk-your-key"
}

Custom model_providers in config.toml

Third-party / self-hosted / this site’s gateway: define base_url + env_key (or requires_openai_auth) in user-level config. Never put the raw secret in TOML.

CLI: login through verification

Suggested order: export → pipe login → status → start codex. In CI, pipe from secrets — never print the key.

export OPENAI_API_KEY="sk-..."
printenv OPENAI_API_KEY | codex login --with-api-key
codex login status
codex

Setting OPENAI_API_KEY alone is not a login. For the built-in openai route, explicit --with-api-key (or a custom provider with env_key) is the reliable path.

Where credentials live: file / keyring / auto

Control with cli_auth_credentials_store in user-level ~/.codex/config.toml. Check this when login “worked” but nothing reads it.

file

Writes $CODEX_HOME/auth.json (default CODEX_HOME=~/.codex). Easy to inspect — also easy to leak into git.

keyring

OS credential store. Safer; can be awkward over SSH or headless sessions.

auto

Prefer keyring; fall back to auth.json.

cli_auth_credentials_store = "file"

auth.json is sensitive. Keep permissions tight; don’t sync it as plain text to shared drives.

Client: same login cache as the CLI

Desktop/app Clients read the same user-level cache. Logging out of one clears the other. Fully quit and reopen after config changes — closing a window is often not enough.

  1. 1

    Confirm the user-level directory

    Default ~/.codex. CODEX_HOME relocates it — CLI and Client must agree on the path.

  2. 2

    Log in via CLI or finish the provider block

    Clients rarely need a separate pipe-login; they reuse what the CLI already wrote.

  3. 3

    Fully quit the Client, then reopen

    Forces a reload of auth.json and config.toml. If it still looks old, check user vs project scope next.

User-level vs project-level: providers belong in user config

One of the most common “I edited config and nothing changed” failures. Project .codex/config.toml can load when trusted, but provider-related keys are ignored.

User-level ~/.codex/config.toml

Put model_provider, model_providers, openai_base_url, and credential-related keys here.

Project-level .codex/config.toml

Fine for workflow prefs — but model_providers / model_provider / openai_base_url are ignored (often with a startup warning). Gateway edits in the project folder do nothing.

Use profiles for multiple routes

Keep profile-name.config.toml under the user home and launch with --profile profile-name instead of rewriting the default file.

config.toml: custom compatible gateway

Custom providers cannot reuse reserved ids: openai, ollama, lmstudio. model_provider must match the [model_providers.xxx] table name.

  1. 1

    Edit only the user-level file

    Path: ~/.codex/config.toml (or $CODEX_HOME/config.toml).

  2. 2

    env_key is a variable name, not the secret

    Example: env_key = "OPENAI_API_KEY", then export the real value in your shell.

  3. 3

    Write base_url the way your gateway documents it

    Many compatible hosts end with /v1 and no trailing slash. Azure shapes differ (/openai vs /openai/v1) — follow what you were given.

  4. 4

    Restart the session to verify

    New terminal for CLI; fully quit the Client. Or let CC Switch write the files, then restart the same way.

model_provider = "codexfree"
model = "gpt-5"

[model_providers.codexfree]
name = "CodexFree"
base_url = "https://YOUR-GATEWAY-HOST/v1"
wire_api = "responses"
env_key = "OPENAI_API_KEY"
env_key_instructions = "export OPENAI_API_KEY before starting Codex"
requires_openai_auth = false
request_max_retries = 4
stream_max_retries = 5
stream_idle_timeout_ms = 300000

Field cheat sheet

FieldMeaning
model_providerActive provider id — must match the table name.
modelDefault model; on Azure this is often the deployment name.
nameDisplay name in UI / logs.
base_urlAPI root. Compatible gateways often end with /v1.
wire_apiProtocol. After 2026-02 only responses; chat fails at startup.
env_keyName of the env var that holds the key — not the key string.
requires_openai_authWhen true, uses OpenAI login cache and ignores env_key.
query_paramsExtra query params (e.g. some Azure api-version values).
http_headers / env_http_headersStatic or env-injected request headers.
request_max_retries / stream_*Retries and SSE idle timeout.

Older guides saying wire_api = "chat" are outdated. Chat Completions support was removed; only Responses remains. If a gateway only speaks /chat/completions, it needs Responses on the host — or a local route that translates (see the toolkit).

Lighter option: openai_base_url only

To point the built-in openai provider at a proxy/router, set openai_base_url in user-level config. For multiple vendors, different keys, or full provider fields, use model_providers.

openai_base_url = "https://YOUR-PROXY-HOST/v1"

Pitfall matrix

Symptom → check this first.

Edited project config — no effect

Provider keys are ignored at project scope. Edit ~/.codex/config.toml.

401 / auth failures

Is env_key only a variable name? Is that var present in the same shell that starts Codex? Did requires_openai_auth ignore env_key?

404 / Unsupported endpoint

base_url path (/v1, trailing slash) and whether the gateway actually exposes Responses.

Exported a key but still looks logged out

Pipe into login for the built-in route, or use a custom provider + env_key.

Switched gateways but still on the old route

New terminal; fully quit Client; confirm model_provider matches the table; cat ~/.codex/config.toml.

CLI works, Client does not

CODEX_HOME mismatch, Client not fully quit, or file vs keyring pointing at different stores.

Do not trust the save button: verify the route in four steps

A saved file is not proof. Identity, config location, process state, and provider logs must all agree.

codex login status
printenv CODEX_HOME
cat ${CODEX_HOME:-$HOME/.codex}/config.toml
codex
  1. Check 1

    Confirm the active identity

    login status must match the ChatGPT or API-key path you chose. If not, logout and repeat only one path.

  2. Check 2

    Confirm the file being read

    Inspect CODEX_HOME. Provider settings belong in user config.toml, not project .codex.

  3. Check 3

    Fully restart both surfaces

    Open a new terminal for CLI and fully quit the Client before reopening it. Closing a window may leave the process alive.

  4. Check 4

    Send a short task and inspect upstream

    Check provider logs or balance. 401 means key, 404 means Base URL / Responses, and no record means a stale process or wrong model_provider.

Need a key first?

Request our upcoming compatible capacity, then finish wiring here — or use CC Switch in the toolkit to reduce hand-edits.

  • Leave an email on Access
  • CLI: pipe login, confirm login status
  • Custom gateway: user-level config.toml + wire_api = responses
  • Client: share ~/.codex, fully quit and reopen

FAQ

Do Client and CLI use different configs?

No. They share ~/.codex auth and config by default. Logout clears both.

Why doesn’t project-level provider config work?

For host/security boundaries, project configs ignore model_providers and related keys. Gateways belong in user-level config.

Can wire_api still be chat?

No. After February 2026 only responses is valid.

Can I put sk-… in env_key?

No. env_key is the variable name; export the secret separately.

openai_base_url vs model_providers?

Use openai_base_url to redirect the built-in openai provider; use model_providers for full multi-vendor setups.

How does this fit the free access on this site?

After you receive a key and base_url, follow the custom provider example — or Enable it in CC Switch and restart.

Also see: Free API · Tools