Connect Codex to third-party models through Responses
Current Codex supports the Responses protocol only. Configure the provider and API key, probe the endpoint, and learn what to do when a gateway only offers Chat Completions.
The short answer
Current Codex supports only "responses" for wire_api. "chat" was removed and causes a startup configuration error. KimiSeek provides /v1/responses, so the configuration below connects directly.
30-second decision table
| Gateway capability | What to do |
|---|---|
Provides /v1/responses | Use "responses" |
Only /v1/chat/completions | Use a Responses-compatible gateway or a translation layer exposing Responses |
| Unknown | Probe the path and inspect the response body below |
Why Codex defaults to responses
Codex sends requests to /responses and consumes its tool-call and streaming events. Chat Completions uses different request and event structures; changing wire_api cannot make current Codex use it. Model capabilities also depend on the upstream and gateway implementation. A successful endpoint probe does not validate every tool capability.
Prerequisites
- Node.js 20 or newer
- Codex CLI:
npm install -g @openai/codex - A KimiSeek API key (starts with
ks-), created in the dashboard
Step 1 · Write the config file
Edit ~/.codex/config.toml (create it if it does not exist):
model = "deepseek-v4-pro-0813"
model_provider = "kimiseek"
[model_providers.kimiseek]
name = "KimiSeek"
base_url = "https://api.kimiseek.app/v1"
env_key = "KIMISEEK_API_KEY"
wire_api = "responses"Three things that trip people up:
base_urlmust include/v1. Codex appends/responsesdirectly tobase_url. Drop the/v1and the request goes tohttps://api.kimiseek.app/responses— a 404.env_keyis a variable name, not the key itself. You writeKIMISEEK_API_KEYhere; the actual value lives in your environment.modelmust be an id that really exists in the catalog. A typo returnsmodel not found, and so does a retired model id.
Step 2 · Set the environment variable and start
export KIMISEEK_API_KEY="ks-your-key"
codexTo switch models temporarily, edit model in config.toml or pass codex --model <id>.
Step 3 · Confirm the key works
curl https://api.kimiseek.app/v1/models \
-H "Authorization: Bearer ${KIMISEEK_API_KEY:?Set KIMISEEK_API_KEY before running this command}"If you get a model list back, both the key and the network are fine. The point of this step is to separate authentication failures from protocol failures — otherwise a 404 leaves you guessing which one it was.
Step 4 · Probe responses in 30 seconds
curl https://api.kimiseek.app/v1/responses \
-H "Authorization: Bearer ${KIMISEEK_API_KEY:?Set KIMISEEK_API_KEY before running this command}" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro-0813",
"input": "Explain what a base URL is in one sentence.",
"max_output_tokens": 256,
"stream": false
}'- HTTP 200 with a JSON
outputarray → the Responses route works; next test a real task and tool calls. - HTTP 404 → check that
base_urlincludes/v1, then inspect whether the response reports a missing route or a missing model. The status alone is not enough. - HTTP 401 → return to Step 3 and check credentials.
If the gateway only offers Chat Completions
Keep wire_api = "responses". Choose a gateway providing /v1/responses, or add a compatible translation layer. Do not switch to the removed "chat" value.
Common errors
| Error | Cause | Fix |
|---|---|---|
unexpected status 401 Unauthorized: Missing bearer | The variable named by env_key is unset or misspelled | Confirm KIMISEEK_API_KEY is visible in the current shell |
unexpected status 404 Not Found | base_url is missing /v1, or the gateway has no /v1/responses | Add /v1 and inspect the error body; if Responses is absent, use a compatible gateway or translation layer |
stream disconnected before completion | The stream was cut: local proxy, corporate gateway, or timeout | Check your HTTP proxy settings and retry on another network |
model not found | Wrong model id, or a retired one | Use the full catalog id, e.g. deepseek-v4-pro-0813 |
More protocol-level errors are collected in the error reference.
Cost
Codex usage is input-heavy: every turn re-sends the context. DeepSeek V4 Pro is priced in CNY per million tokens across two bands:
| Band | Input | Cached input | Output |
|---|---|---|---|
| Off-peak | ¥4.5 | ¥0.45 | ¥13.5 |
| Peak | ¥9 | ¥0.9 | ¥27 |
Peak is exactly double. Batching large refactors into off-peak hours halves the bill. Live numbers for every model come from the pricing page, which reads the model catalog directly.
Versions and verification
Configuration checked with Codex CLI 0.154.0 on 2026-10-26. See the official configuration reference for protocol support.
FAQ
With a gateway like this, do I still need a bridge such as Codex-Bridge?
No. A bridge exists to translate Responses requests into Chat Completions locally, for gateways that only speak chat completions. KimiSeek implements /v1/responses itself, so a bridge only adds a hop and another place to fail.
Why does base_url have to include /v1?
Codex concatenates: base_url + "/responses". Write https://api.kimiseek.app and the request goes to https://api.kimiseek.app/responses, which is a web page, not an API.
Can current Codex still use wire_api = "chat"?
No. Current versions reject that value at startup. Use responses; a Chat Completions-only upstream needs a compatible gateway or translation layer.
Can one key serve both Claude Code and Codex?
Yes. Keys are account-level; the clients simply call the same key over different protocol routes. See the Claude Code guide.