Codex CLI is OpenAI's terminal coding agent. It reads code, edits files, and runs commands. Many teams want to point it at a self-hosted gateway or a third-party OpenAI-compatible endpoint so they can manage keys, billing, and quotas in one place. In practice, "connecting a custom API" comes down to three settings: where requests go (Base URL), how they are authenticated (key), and which model is called (model name). What actually goes wrong most often is the auth method, protocol matching, and permission boundaries.
This guide uses common versions as of October 2026 and walks through installation, authentication, configuration, verification, sandbox approvals, team rollout, and security in that order. Codex changes quickly, so treat codex --help and the official documentation as the source of truth for commands and configuration keys.
Note: OpenAI, Codex, and ChatGPT are trademarks or registered trademarks of OpenAI. This article is a technical integration guide only and is not affiliated with OpenAI. Endpoint requirements, model identifiers, and billing rules may change between versions; refer to the official documentation and the site's model pricing.
1. Confirm the protocol and authentication method first
Custom providers in Codex CLI speak the Responses protocol, and wire_api currently accepts only responses; the older chat value is deprecated and errors out in many versions. A gateway must meet at least two requirements: it provides a compatible /v1/responses endpoint, and it supports streaming output including the terminal event response.completed. An endpoint that offers only Chat Completions needs a protocol conversion layer; you cannot simply paste its address into the configuration.
There are three authentication paths. Pick one:
| Method | Typical command or setting | Good for | Notes |
|---|---|---|---|
| ChatGPT account login | codex login |
Individual trials, temporary use | Uses account quota; not suitable for CI |
| API key login | codex login --with-api-key (reads the key from stdin) |
Individual pay-as-you-go use | Credentials are stored in auth.json or the system keychain |
| Custom provider | env_key pointing to an environment variable |
Team gateways, unified billing | The key never goes into TOML, which makes quotas and revocation easier |
Use codex login status to see the current login state and codex logout to clear local credentials. If several credential types exist at once, confirm which one is actually in effect before troubleshooting anything else.
2. Install Codex CLI
Choose one method for your system, then confirm the version:
# Official install script for macOS / Linux
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# Package managers are also available; follow the current official documentation
npm install -g @openai/codex
brew install --cask codex
codex --version
For the first launch, use an empty test repository. Do not experiment in a directory that contains production secrets, customer data, or unmasked configuration. Codex reads context from the current directory, so the cleaner the directory, the easier troubleshooting becomes.
3. Configure the Base URL, key, and model
User-level configuration lives at ~/.codex/config.toml, or %USERPROFILE%\.codex\config.toml on Windows. One very common trap: top-level keys must appear before the first table header. If you put model or model_provider after [model_providers.xxx], they are interpreted as fields of that table, and the configuration appears not to take effect.
# ~/.codex/config.toml
model = "your-model-id"
model_provider = "zsqh"
web_search = "disabled"
[model_providers.zsqh]
name = "ZSQH AI Gateway"
base_url = "https://ai.zhongshangqihang.com/v1"
wire_api = "responses"
env_key = "ZSQH_API_KEY"
What the fields mean:
model: the API identifier, not the display name on the website. It must match the pricing page exactly.model_provider: must match the provider ID below. Do not use reserved names such asopenai,ollama, orlmstudio.base_url: includes the API path, usually ending in/v1. Do not append it twice.wire_api: set this toresponses.env_key: the name of an environment variable, not the key itself.web_search: set it todisabledwhen the gateway does not support web search, so requests do not target an unavailable capability.
Then export the key in the same shell that launches Codex:
export ZSQH_API_KEY="sk-your-key"
On Windows PowerShell, use $env:ZSQH_API_KEY="sk-your-key". To make the variable persistent, add it to your shell profile or system environment variables, and confirm that editors launched from the graphical interface can also read it.
If the gateway requires custom request headers, you can use env_http_headers = { "X-API-Key" = "ZSQH_API_KEY" } instead. That approach does not use remote catalog discovery, so you also need to provide a local model catalog through model_catalog_json. If keys are issued dynamically by a secrets manager, the command field under [model_providers.zsqh.auth] can fetch a token from an external program, but it cannot be combined with env_key. If you have many model aliases, consider model_catalog_url or a local model_catalog_json; otherwise do not add the complexity.
One more thing to remember: trusted projects do load .codex/config.toml, but the model_provider, model_providers, and profile definitions inside it are ignored. Providers must be defined in the user-level configuration.
4. Verify that the connection really works
Work through these steps in order. They quickly separate "the tool is misconfigured" from "the gateway is unreachable":
- Run
codex login statusand confirm the active authentication method. Then confirm that the variable named byenv_keyis non-empty in the launch environment. Do not print the full key in a shared terminal. - Run
codex doctorto check the configuration file location, environment variables, and common configuration conflicts. - In a test repository, run
codex exec "Reply with exactly: gateway-ok". A return value ofgateway-okmeans the basic path works.codex execuses a read-only sandbox by default, which makes it suitable for smoke tests. - Enter interactive mode and run
/statusto confirm that the current model and provider match your configuration. - Check the request log in the gateway console to confirm the user, model alias, and upstream route. A reply in the client is not enough; it could come from a cache or from stale configuration.
- If it still fails, recheck the
/v1and/responsespaths in the Base URL, then check whether a proxy is rewriting or stripping theAuthorizationheader.
5. Sandbox and approval: two independent switches
Many people confuse "execute automatically" with "which files can be changed." Codex splits them into two controls: the approval policy decides when it stops to ask you, and the sandbox decides which files and network resources the process can touch.
The current version's common approval_policy value is on-request, which suits most everyday development; never is only appropriate in isolated automation environments. The old untrusted value is no longer supported, and on-failure is deprecated as well, so copying old tutorials often produces configuration errors.
sandbox_mode has three values: read-only, workspace-write, and danger-full-access. Start read-only by default; when code changes are needed, use workspace-write and limit writable directories with sandbox_workspace_write.writable_roots; danger-full-access should only appear in containers or disposable runners. If network access is required, enable sandbox_workspace_write.network_access separately instead of loosening every permission at once.
In non-interactive mode, specify the sandbox with codex exec --sandbox workspace-write; if your organization allows automatic review, add --approve-for-me. Note that --full-auto is no longer supported, so old scripts using it need updating. In interactive mode, use /permissions to view and adjust the current permissions.
6. Team rollout: start small, then standardize
Start with two or three people and one non-critical repository, then expand once it works. The goal is not "how many people installed it" but whether the configuration is reproducible and failures are easy to locate.
- One key per person, split further by project or environment. Never share a single key across the whole team.
- Set budgets, concurrency limits, and model allowlists on the gateway to stop agent loops from draining quota.
- Use managed enterprise configuration to standardize
approval_policy,sandbox_mode, andcli_auth_credentials_store;requirements.tomlcan prohibit high-risk combinations such asneveranddanger-full-access. - If you need to enforce a login method, use
forced_login_method = "chatgpt"or"api"so members do not mix credential types. - Maintain a configuration template without secrets that documents the Base URL, model identifiers, and troubleshooting commands.
- Review gateway usage monthly and look for anomalies by person, project, and model.
7. Security checklist
- Keep keys only in environment variables, the system keychain, or a secrets manager. Do not write them into
config.tomlor Git. Theexperimental_bearer_tokenfield exists in the configuration, but the official documentation does not recommend it. - Use a dedicated key for Codex so you can set quotas, expiration dates, and separate revocation.
- Use a read-only sandbox by default; when writes are needed, restrict them to the specific repository directory and revoke the permission when the task ends.
- Do not put
.env,auth.json, production configuration, or customer data into context; exclude build artifacts and dependency directories in large repositories first. - Review commands and patches generated by Codex, especially deletions, network requests, and privilege escalation.
- Pin the Codex version in team images, and validate configuration compatibility in a test environment before upgrading.
- Enable gateway usage alerts. When unusual calls appear, disable the key first, then inspect the logs.
FAQ
Does Codex CLI have to use the Responses protocol?
Yes, for custom providers. wire_api currently accepts only responses, and the old chat value is deprecated. If a gateway provides only Chat Completions, you need a protocol conversion layer or an endpoint that supports Responses.
The configuration looks right, but why do requests still go to the default address?
First confirm that you edited ~/.codex/config.toml, then confirm that the top-level keys appear before any table header and that model_provider exactly matches the provider ID. Provider definitions in project-level configuration are ignored, which is a common cause.
Can I put the key directly in config.toml?
Not recommended. Use env_key to reference an environment variable, or call an external token command through [model_providers.xxx.auth]. A plaintext key can leak through configuration backups, screenshots, or repositories.
Is ChatGPT login billed the same way as an API key?
No. ChatGPT login uses the account system, while an API key is billed per use through the API. Their quotas, invoices, and permission scopes differ, so teams should account for them separately when purchasing.
Can a team share one key?
Not recommended. A shared key makes it impossible to identify who made a call, and you cannot revoke it for a single person when someone leaves or a key leaks. Issue keys per person and per environment, together with quotas and expiration dates.
Next steps
The hard part of connecting Codex is not installation but protocol matching and permission boundaries: first confirm that the gateway supports Responses and streaming terminal events, then configure the Base URL, key, and model, and finally run a smoke test in a read-only sandbox. If you need a unified endpoint and usage management, sign up for the ZSQH AI Gateway; the model and endpoint scope follow the model pricing page.
Related reading:
