Codex CLI and the Responses API: why most relays 404
OpenAI's Codex CLI doesn't call the classic Chat Completions API — it speaks the newer Responses API wire format. Most OpenAI-compatible relays only implement Chat Completions, so Codex pointed at them fails with 404s or malformed-request errors even though the same key works in curl. Router One implements the Responses wire format natively (wire_api = "responses"), so Codex works with a two-minute config change.
The one-line root cause
Codex sends requests to /responses-style routes with a request schema that Chat Completions servers don't recognize. A relay that only speaks Chat Completions answers with 404 (unknown path) or 400 (unknown fields). No amount of key or model fiddling fixes a wire-format mismatch — the gateway itself has to support it.
The working configuration
Point Codex at Router One in ~/.codex/config.toml and export your key in the same shell that runs codex:
# ~/.codex/config.toml model_provider = "router" [model_providers.router] name = "router" base_url = "https://api.router.one/v1" requires_openai_auth = true wire_api = "responses" # in your shell: # export OPENAI_API_KEY=sk-your-router-one-key
Error checklist
If Codex still fails after the config change:
| Symptom | Cause | Fix |
|---|---|---|
| 404 on every request | base_url points at a relay without Responses API support, or has a typo | Set base_url to https://api.router.one/v1 exactly and keep wire_api = "responses". |
| 401 unauthorized | OPENAI_API_KEY isn't visible in the shell running codex | Export the key in the same session (or your shell profile), then restart the terminal and re-run codex. |
| Model not found | Model ID doesn't match the catalog | Copy the exact ID from the /models page — IDs are case-sensitive. |
| 402 insufficient balance | Wallet or key spend cap exhausted | Top up or raise the key's maxSpend in Dashboard → API Keys. |
| Config seems ignored | Codex reads a different config file than the one you edited | Confirm the file lives at ~/.codex/config.toml (Windows: %USERPROFILE%\.codex\config.toml). |
Verify from the trace
Once requests reach the gateway, every Codex call shows up in Dashboard → Logs with model, tokens, cost, and status. If the log stays empty while Codex errors, the failure is still local — config path or env var. If entries appear with 4xx, the trace names the exact limit.
FAQ
- Why does my key work in curl but not in Codex?
- curl exercises the Chat Completions surface; Codex uses the Responses API wire format. A relay can pass the curl test and still 404 for Codex. The gateway must implement the Responses wire format — Router One does.
- What does wire_api = "responses" actually do?
- It tells Codex which protocol shape to speak with the provider block. With "responses", Codex sends Responses-API-formatted requests; the endpoint on the other side has to understand them natively.
- Does the base URL need /v1?
- Yes — for Codex the OpenAI-compatible base URL is https://api.router.one/v1 including /v1. That's the opposite of Claude Code, whose Anthropic-compatible base URL has no /v1 suffix.
- Which models can Codex use through the gateway?
- Any chat-capable model in the catalog with its exact model ID — the /models page lists IDs, prices, and context windows. You're not locked to a single family.
- Does this work from Mainland China?
- Yes. The gateway is reachable from Mainland China without a VPN; the config.toml above is identical everywhere.