Runtime Routes
Codex Pooler exposes a deliberately narrow runtime surface. It is not a wildcard proxy and it does not claim full OpenAI API parity. Each route below is either a Codex backend compatibility route, a backend bridge route, a translated /v1 compatibility route, an operator metadata route, or an explicit unsupported boundary.
Use this page when you need to answer three questions before wiring a client:
- Which endpoint should the client call?
- Which upstream route does Codex Pooler call after admission and routing?
- Is the request passed through as Codex backend traffic, translated into Codex work, partially supported, or blocked?
All runtime endpoints require Pool API key bearer auth unless noted otherwise. A Pool API key represents a Pool, not one upstream account. Codex Pooler still applies Pool policy, model support, limits, account health, route class admission, session continuity, and accounting before dispatching supported work upstream.
Which Runtime Route Should I Use?
Section titled “Which Runtime Route Should I Use?”Use /backend-api/codex for Codex backend-compatible clients, /v1 for selected OpenAI SDK-compatible clients, and /mcp only for operator metadata tools. Runtime work on /backend-api and /v1 uses Pool API key bearer auth. MCP uses operator-owned MCP tokens and does not accept Pool API keys.
Quick map
Section titled “Quick map”| Route family | Use it for | Auth boundary |
|---|---|---|
/backend-api/codex | Codex backend compatibility route for Codex-compatible clients | Pool API key bearer auth |
/backend-api | Backend file bridge, audio transcription, and backend usage routes | Pool API key bearer auth |
/v1 | Narrow OpenAI-compatible /v1 support for selected SDK routes | Pool API key bearer auth |
/mcp | Read-only operator MCP endpoint for metadata lookup | Operator-owned MCP bearer token |
| Usage routes | Runtime usage checks exposed on compatibility paths | Pool API key bearer auth |
Status labels
Section titled “Status labels”| Status | Meaning |
|---|---|
| Supported | The route is an active public route and enters the normal authenticated gateway path. |
| Translated | The client calls an OpenAI-shaped /v1 route, and Codex Pooler converts the request to Codex-compatible work before dispatch. |
| Partial | The route exists, but only a narrower behavior is supported than the name may imply. |
| Unsupported | The route is blocked with a deterministic unsupported response or intentionally absent from the route surface. |
Codex backend compatibility
Section titled “Codex backend compatibility”Use /backend-api/codex for Codex-compatible clients:
https://codex-pooler.example.com/backend-api/codexThese endpoints keep Codex backend semantics and do not translate through the public OpenAI SDK adapter.
| Exposed endpoint | Upstream destination | Translation | Support | Notes |
|---|---|---|---|---|
GET /backend-api/codex/models | Model metadata served from Pool/catalog state | No Codex request translation | Supported | Lists models visible to the authenticated Pool, including backend Codex metadata such as context windows and optional comp_hash. |
POST /backend-api/codex/responses | /backend-api/codex/responses, or /backend-api/codex/responses/compact for terminal compaction triggers | No; backend payload is proxied through gateway normalization | Supported | Primary Codex Responses route for JSON and SSE work. A valid terminal compaction_trigger bridges through compact handling and returns backend Responses SSE with encrypted compaction output. The compact bridge strips compact-unsupported controls such as store, stream, and include before upstream dispatch. |
GET /backend-api/codex/responses | Persistent upstream Codex websocket response session | No HTTP adapter translation | Supported | Narrow backend websocket route. It preserves websocket session continuity, uses x-codex-turn-state, and applies the admin-managed websocket_idle_timeout_ms downstream idle window. |
POST /backend-api/codex/responses/compact | /backend-api/codex/responses/compact | No | Supported | Backend compact compatibility route. |
POST /backend-api/codex/images/generations | /backend-api/codex/images/generations | No public /v1 image translation | Supported | Explicit authenticated backend image proxy route; image prompt and source fields stay image-specific. |
POST /backend-api/codex/images/edits | /backend-api/codex/images/edits | No public /v1 image translation | Supported | Explicit authenticated backend image edit proxy route. |
Backend /v1 aliases
Section titled “Backend /v1 aliases”Some Codex clients use /backend-api/codex/v1 as their base URL. Codex Pooler exposes exact aliases for that shape. These are still backend routes, not the public OpenAI-compatible /v1 surface.
| Exposed endpoint | Canonical gateway target | Translation | Support | Notes |
|---|---|---|---|---|
GET /backend-api/codex/v1/models | /backend-api/codex/models | No | Supported | Alias for backend model listing, including backend-only fields such as optional comp_hash. |
POST /backend-api/codex/v1/responses | /backend-api/codex/responses, or /backend-api/codex/responses/compact for terminal compaction triggers | No | Supported | Alias for backend Responses. Prompt-cache routing locality can apply here. Terminal compaction triggers follow the canonical compact bridge. |
GET /backend-api/codex/v1/responses | Backend websocket response session | No | Supported | Alias for the backend websocket route. Prompt-cache routing locality is excluded, and the same websocket_idle_timeout_ms downstream idle window applies. |
POST /backend-api/codex/v1/responses/compact | /backend-api/codex/responses/compact | No | Supported | Alias for backend compact. Prompt-cache routing locality is excluded. |
POST /backend-api/codex/v1/chat/completions | /backend-api/codex/responses | Chat payload is coerced to backend Responses work | Supported | Backend alias for chat-completion-shaped Codex clients. Prompt-cache routing locality can apply here. |
Backend app-server helper routes
Section titled “Backend app-server helper routes”Codex Pooler is a model-provider runtime boundary. It does not proxy Codex
account helpers, analytics posting, thread-goal helpers, memory summaries,
search helpers, realtime helper calls, safety helper calls, identity JWKS, or
reset-credit consume operations. Configure Codex clients by pointing
model_providers.*.base_url at /backend-api/codex.
Supported Responses stream event metadata is relayed on model-provider streams as upstream sends it. Codex Pooler does not synthesize app-server notifications such as turn/safetyBuffering/updated.
Backend bridge and usage routes
Section titled “Backend bridge and usage routes”These routes live under /backend-api or legacy usage paths. They are still Pool API key routes. The backend file bridge stores metadata only; file bytes stay upstream-backed.
| Exposed endpoint | Upstream destination | Translation | Support | Notes |
|---|---|---|---|---|
POST /backend-api/files | Upstream file create/upload-url flow | No OpenAI multipart translation | Supported | Accepts JSON metadata only and returns upstream file metadata plus upload URL. Codex Pooler stores metadata only. |
POST /backend-api/files/:file_id/uploaded | Upstream file finalization flow | No | Supported | Marks an upstream-backed file upload as complete. |
POST /backend-api/transcribe | /backend-api/transcribe | No public /v1 audio translation | Supported | Backend multipart transcription route. It forces the backend transcription model and preserves safe multipart fields. |
GET /api/codex/usage | Codex usage resolver | No | Supported | Compatibility usage route. |
GET /wham/usage | Codex usage resolver | No | Supported | Compatibility usage route. |
GET /backend-api/wham/usage | Codex usage resolver | No | Supported | Backend usage alias. |
The app-server JSON-RPC reset-credit method
account/rateLimitResetCredit/consume remains unsupported. Codex Pooler does
not add a wildcard backend app-server proxy for reset-credit methods.
OpenAI-compatible /v1 routes
Section titled “OpenAI-compatible /v1 routes”Use /v1 only for clients that require an OpenAI-shaped base URL:
https://codex-pooler.example.com/v1Supported work is translated into Codex-compatible requests and then routed through the same Pool policy, limit, account-selection, accounting, and session-continuity machinery as backend traffic. Codex Pooler does not provide full OpenAI API parity.
| Exposed endpoint | Gateway/upstream destination | Translated to Codex? | Support | Notes |
|---|---|---|---|---|
GET /v1/models | OpenAI-shaped model metadata from Pool/catalog state | No upstream Codex request | Supported | Returns an OpenAI-shaped model list for the authenticated Pool. Includes effective context_length when Codex context metadata is available; backend-only fields such as context_window, max_context_window, auto_compact_token_limit, and comp_hash are omitted. |
POST /v1/responses | /backend-api/codex/responses | Yes | Translated | OpenAI Responses payloads are coerced to Codex-compatible work. System/developer input-message text is lifted into top-level instructions. Encrypted type: “compaction” replay items from prior remote compaction turns are forwarded. Remote MCP tool definitions are rejected before dispatch. Streaming responses use the public Responses stream adapter, and early terminal errors emit first without synthetic success prefixes. For public HTTP SSE only, if upstream has already emitted public Responses-visible data and ends before a terminal Responses event, Codex Pooler emits a sanitized response.failed terminal with upstream_stream_error; backend raw streams and websocket surfaces are not rewritten. |
GET /v1/responses | Backend Codex websocket response session | Partial | Partial | Narrow Responses websocket compatibility only. It is not OpenAI Realtime SDK support. It uses the same downstream idle and frame guardrails as backend Codex websockets. |
POST /v1/chat/completions | /backend-api/codex/responses | Yes | Translated | Chat Completions payloads are coerced to Codex Responses work and normalized back to Chat Completions shape. Early streaming terminal errors emit one public error chunk before any assistant role chunk. |
GET /v1/usage | Codex usage resolver | No upstream Codex work request | Supported | OpenAI-compatible usage read surface for the authenticated Pool. |
GET /v1/files | Codex Pooler file metadata | No | Supported | Lists metadata for upstream-backed files visible to the Pool. |
POST /v1/files | Upstream-backed file metadata create flow | Partial | Partial | Creates metadata for Codex-compatible upstream file storage. Backend /backend-api/files remains JSON-only; this is the OpenAI-compatible file-create surface. |
GET /v1/files/:file_id | Codex Pooler file metadata | No | Supported | Retrieves metadata only. |
GET /v1/files/:file_id/content | No upstream content read | No | Partial | Checks ownership, records an unsupported operation, then returns an OpenAI-shaped unsupported endpoint response. File bytes are not served by Codex Pooler. |
DELETE /v1/files/:file_id | No upstream delete | No | Partial | Checks ownership, records an unsupported operation, then returns an OpenAI-shaped unsupported endpoint response. |
POST /v1/audio/transcriptions | /backend-api/transcribe | Yes | Translated | OpenAI-style multipart transcription request dispatched through the backend transcription path. |
POST /v1/images/generations | /backend-api/codex/responses | Yes | Translated | OpenAI image generation request is converted to Codex Responses-compatible image work. |
POST /v1/images/edits | /backend-api/codex/responses | Yes | Translated | OpenAI image edit request is converted to Codex Responses-compatible image work. |
POST /v1/responses accepts reasoning.context only for auto,
current_turn, and all_turns after trimming and lowercasing. Unknown, empty,
or non-string context values fail before dispatch with
param: "reasoning.context".
Reasoning effort values can come from the client request or API-key policy. The policy is derived from its configured fields:
- Unrestricted preserves the current route behavior. Omission stays absent, and any currently accepted explicit effort, including a custom value, passes through this policy.
- Allow up to permits only known efforts at or below the selected ceiling:
none,minimal,low,medium,high,xhigh,max, andultra. The selected model’s effective known levels narrow the permitted set. An omitted effort resolves to the permitted model default, or the highest permitted known effort. - Always use applies the legacy exact configured effort. It remains compatible even when the configured effort is absent from model metadata.
Allow up to never clamps or downgrades a request. An above-ceiling, unknown, or
custom effort, or an omission with no permitted effort, returns 400 with code
reasoning_effort_not_allowed and message
reasoning effort is not available for this API key before reservation or
upstream dispatch. Responses, backend Responses, and compact routes return
param: "reasoning.effort"; Chat Completions returns
param: "reasoning_effort". API-key model denial remains first and returns the
existing 403 model_not_allowed response.
The same policy runs after websocket upgrade for every response.create frame.
A forbidden frame uses the existing websocket error frame with the same status,
code, message, and route-native parameter. The connection is not rejected at
upgrade time.
Authenticated backend Codex model metadata reflects the policy. Unrestricted
keeps the current levels and default. Allow up to filters to permitted known
levels and a permitted default. Always use advertises its singleton only when it
is model-effective, otherwise it returns no levels and no default. Models stay
visible, and public /v1/models remains unchanged.
minimal and ultra remain distinct for policy evaluation. Backend Codex
compatibility rewrites them to low and max respectively before upstream
dispatch. Safe reasoning summaries retain requested, applied, and effective
values.
Non-strict function tool schemas are lowered before local validation and
upstream dispatch for backend Responses HTTP, backend Responses websocket
response.create, and public /v1/responses compatibility paths. Lowering is
limited to function tools, including nested function tools inside accepted
namespace tools. Strict function tools and strict structured-output schemas stay
on the strict validation path and are not made looser.
Catalog revision and final Responses envelope
Section titled “Catalog revision and final Responses envelope”The authenticated backend model routes return the same effective catalog body
for the same Pool and catalog snapshot. Both
GET /backend-api/codex/models and GET /backend-api/codex/v1/models attach a
deterministic weak ETag derived from that policy-visible body.
Successful backend Responses streams expose the same token as
X-Models-Etag. It appears on HTTP SSE response headers for the canonical and
backend-alias POST routes, and on websocket upgrade headers for the matching
GET routes. The token is produced by Codex Pooler, not relayed from upstream.
It is not exposed by compact, public /v1, usage, or unauthenticated routes.
Catalog convergence across replicas is eventual, so clients should compare a
successful Responses token with a later authenticated backend models token.
Every non-compact request that reaches the backend Responses destination has a
reasoning object and exactly one reasoning.encrypted_content entry in
include after final normalization. This applies to canonical backend HTTP and
websocket traffic, backend /v1 Responses and Chat Completions aliases, and
translated POST /v1/responses, GET /v1/responses, and
POST /v1/chat/completions traffic. Compact dispatch is excluded and keeps its
narrow compact request shape.
When upstream returns a valid parameter path with an error, failed attempt
detail may expose it as upstream_error_param. The value is limited to a
bounded field or numeric-index path. Invalid values and successful attempts
omit the field, and raw upstream error messages or rejected values are never
projected through it.
Unsupported /v1 Responses request shapes
Section titled “Unsupported /v1 Responses request shapes”These POST /v1/responses request shapes return OpenAI-shaped invalid_request before gateway dispatch, not unsupported_endpoint:
- top-level
tools[].type = "mcp" - nested
input[].type = "additional_tools"withtools[].type = "mcp"
Routed but unsupported /v1 endpoints
Section titled “Routed but unsupported /v1 endpoints”These routes are deliberately present so clients receive deterministic OpenAI-shaped unsupported endpoint errors before gateway admission or upstream dispatch.
| Exposed endpoint | Upstream destination | Translated to Codex? | Support | Notes |
|---|---|---|---|---|
POST /v1/responses/compact | None | No | Unsupported | The backend compact route exists under /backend-api/codex; the public /v1 compact route returns unsupported_endpoint. |
POST /v1/images/variations | None | No | Unsupported | Image variations are not implemented. |
POST /v1/embeddings | None | No | Unsupported | Embeddings are outside the Codex Pooler route surface. |
POST /v1/batches | None | No | Unsupported | Batch jobs are not dispatched by Codex Pooler. |
POST /v1/moderations | None | No | Unsupported | Moderations are not implemented. |
POST /v1/fine_tuning/jobs | None | No | Unsupported | Fine-tuning jobs are not implemented. |
GET /v1/responses/:response_id | None | No | Unsupported | Response retrieval by id is not part of the public compatibility surface. |
POST /v1/responses/:response_id/cancel | None | No | Unsupported | Response cancellation by id is not part of the public compatibility surface. |
DELETE /v1/responses/:response_id | None | No | Unsupported | Response deletion by id is not part of the public compatibility surface. |
Intentionally absent /v1 route families
Section titled “Intentionally absent /v1 route families”/v1/realtime and OpenAI Realtime SDK websocket/session routes are intentionally outside the public route surface. A client calling those paths should treat Codex Pooler as not supporting OpenAI Realtime. Use GET /v1/responses only for the narrow Responses websocket compatibility route documented above.
MCP endpoint
Section titled “MCP endpoint”The operator MCP endpoint is rooted at /mcp, not under /backend-api or /v1.
| Route | Meaning |
|---|---|
POST /mcp | JSON-RPC Streamable HTTP endpoint |
GET /mcp | Routed endpoint, but stateless SSE is unavailable today |
OPTIONS /mcp | Allowed MCP methods response |
MCP uses operator-owned bearer MCP tokens. It doesn’t accept Pool API keys, browser sessions, cookies, query tokens, invite tokens, upstream tokens, or custom headers as authentication.
MCP output is metadata-only and scoped by the operator’s owner or assigned-Pool visibility. It is an operator inspection endpoint, not a runtime client endpoint.
The root /mcp operator endpoint is not a bridge for /v1/responses remote MCP tools.
Prompt-cache and continuity boundaries
Section titled “Prompt-cache and continuity boundaries”Prompt-cache routing locality is a local routing hint. It can apply on POST /backend-api/codex/responses, POST /backend-api/codex/v1/responses, POST /backend-api/codex/v1/chat/completions, POST /v1/responses, and POST /v1/chat/completions. It is excluded from websocket, compact, file, audio, image, usage, and app-server helper routes. Locality is always a heuristic: it can improve the chance that compatible work reaches a reusable upstream connection, but it never guarantees a provider cache hit or cached-token accounting.
When a Pool enables the upstream websocket bridge, an eligible streaming POST /v1/responses request keeps HTTP SSE as its downstream contract while first attempting upstream dispatch through the continuity owner’s websocket. Internal upstream events remain buffered and do not commit the bridge. The bridge commits only when the first event that public Responses normalization would expose is forwarded downstream.
Any bridge failure before that commit boundary falls back to plain HTTP on the same candidate and attempt, with one settlement. After a public event has committed the websocket transport, Codex Pooler does not replay the turn over HTTP; a later upstream websocket failure ends the request as failed. Reusing an owner websocket is a cache-locality heuristic, never a cache guarantee.
During a mixed-release transition, native websocket attachment keeps its two-argument compatibility path against a previous-release owner. The bridge’s option-carrying three-argument attachment is unavailable there and fails closed to HTTP before commit. Previous-release owners also retain the legacy five-minute post-detach window and omit connection lifecycle metadata; new or recovered owners use the current 30-minute default.
Websocket Guardrails
Section titled “Websocket Guardrails”Backend Codex websocket routes and the narrow public GET /v1/responses websocket route use bounded downstream guardrails. websocket_idle_timeout_ms controls the downstream websocket idle close window for new upgrades. It also bounds owner-forwarded full-turn submit waits for new websocket requests, so healthy long turns are not limited by upstream receive timeout. Its default is 1_800_000 ms, and accepted values are 60_000..3_600_000 ms.
websocket_owner_idle_timeout_ms is separate. It controls post-detach owner retention after no downstream or active turn remains, not downstream idle closure. It has the same 1_800_000 ms default and 60_000..3_600_000 ms bounds. Each new or recovered owner captures its node-local value at startup, and existing owners retain the value they captured.
Inbound websocket frames are also bounded by the configured gateway request body limit. Operators should treat reason_class=max_frame_size_exceeded as an oversized client frame, reason_class=timeout as downstream websocket idle close, and upstream receive timeout errors as separate upstream-side failures. These classifications are metadata-only and must not include raw websocket frames or request bodies.
Request compression boundaries
Section titled “Request compression boundaries”Request compression is a per-Pool routing option named request_compression_enabled. It is disabled by default. When enabled, Codex Pooler may compress upstream-bound Responses tool-output content before dispatch. This is request-side only: raw outputs and upstream response bodies are not stored, and CCR/retrieval is not implemented.
Supported input shapes are explicit. Search-result compression accepts classic
path:line[:column]: text, grouped heading output when a path-like heading has
enough line matches below it, and portable NUL-delimited output shaped as
path\0line[:column]: text. Diff compression requires a hunk header and accepts
additions-only, deletions-only, replacement, minimal unified, combined unified,
and long-preamble diffs without a leading diff --git header. Log-output
compression keeps every discovered failure block when a summary reports
failure/error counts, or skips the rewrite. Malformed NUL fragments, prose
headings, ordinary prose with plus/minus lines, and incomplete failure-summary
logs stay text/skip.
Protected exact-output tool results stay byte-for-byte upstream-bound before
rewriting. This includes default function tools Read, Glob, Grep, Write,
Edit, WebSearch, WebFetch, web_search, and web_fetch, plus external
retrieval outputs. Output-only function tool results fail closed as protected
when the tool name is unavailable. Metadata records aggregate skip counts only.
Eligible route families are exact:
| Family | Eligible routes |
|---|---|
| Backend Responses | POST /backend-api/codex/responses |
Backend /v1/responses | POST /backend-api/codex/v1/responses |
| Translated chat completions | POST /backend-api/codex/v1/chat/completions and POST /v1/chat/completions |
Public /v1/responses | POST /v1/responses |
| Compact backend routes | POST /backend-api/codex/responses/compact and POST /backend-api/codex/v1/responses/compact |
| Responses websocket | backend and narrow public websocket response.create payloads that dispatch to backend Responses |
Unsupported surfaces are multipart, file, audio, image, admin, MCP, usage, and other non-Responses routes. POST /v1/responses/compact remains unsupported because the public compact route has no upstream dispatch.
Compression is fail-open. Scanner, tokenizer, compression, and limit errors preserve the original upstream request body and record safe payload_compression metadata. JSON request bodies over 1 MiB skip before scanning, and a dispatch processes at most 50 output candidates. Token counting is local and in-process with tokenizer data shipped by the application; it does not call OpenAI or load a local model.
Request logs show safe aggregate savings only. They prefer saved tokens and token savings percent when token counts are available, and fall back to saved bytes and byte savings percent when token counts are unavailable.
Continuity headers are also local routing inputs. Codex Pooler chooses them in this order:
x-codex-window-idx-codex-session-idsession-idx-session-idx-session-affinitysession_idx-codex-conversation-id
session-id, x-session-id, and x-session-affinity are not forwarded upstream. If a pinned continuation points at an upstream account that now requires reauthentication, /v1/responses HTTP and websocket requests fail closed with a recovery hint to restart with full context and remove stale continuation anchors.
Related references
Section titled “Related references”- Routing Strategies explains Pool routing policy, account selection, and prompt-cache locality.
Frequently Asked Questions
Section titled “Frequently Asked Questions”Is /v1 the same as the OpenAI API?
Section titled “Is /v1 the same as the OpenAI API?”No. /v1 is narrow OpenAI-compatible support for selected SDK routes. Supported requests are translated into Codex-compatible work and routed through Pool policy. Unsupported routes are either intentionally absent or return deterministic OpenAI-shaped unsupported endpoint errors when explicitly routed.
Is GET /v1/responses OpenAI Realtime support?
Section titled “Is GET /v1/responses OpenAI Realtime support?”No. GET /v1/responses is narrow Responses websocket compatibility. It is not /v1/realtime support, and OpenAI Realtime SDK websocket or session routes are outside the Codex Pooler route surface.
Can a Pool API key call /mcp?
Section titled “Can a Pool API key call /mcp?”No. Pool API keys authenticate runtime clients for /backend-api and /v1. The root /mcp endpoint is for operator metadata only and requires an operator-owned MCP bearer token.
Does Codex Pooler store uploaded file bytes?
Section titled “Does Codex Pooler store uploaded file bytes?”No. The backend file bridge stores file metadata and uses upstream-backed upload or download URLs. Raw file bytes, upload URLs, prompts, response bodies, media bodies, credentials, and websocket frames are not stored or exposed as public docs evidence.