# codex-api > An OpenAI-compatible chat completions API. Use it exactly as you would use > https://api.openai.com/v1 — same request and response shapes, same client libraries. BASE URL: https://codex.sprigloop.ai/v1 AUTH: Authorization: Bearer MODEL: gpt-5.6-sol (default) ## Quickstart Point any OpenAI client at the base URL above and set its api_key to your key. from openai import OpenAI client = OpenAI( api_key="YOUR_CODEX_API_KEY", base_url="https://codex.sprigloop.ai/v1", ) resp = client.chat.completions.create( model="gpt-5.6-sol", messages=[{"role": "user", "content": "Explain a hash join in two sentences."}], ) print(resp.choices[0].message.content) curl: curl https://codex.sprigloop.ai/v1/chat/completions \ -H "Authorization: Bearer $CODEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5.6-sol", "messages": [{"role": "user", "content": "Explain a hash join in two sentences."}] }' ## Endpoints POST /v1/chat/completions Chat completions. Streaming and non-streaming. POST /v1/completions Legacy text completions (prompt in, text out). GET /v1/models Available models. GET /v1/models/{id} One model. GET /health Liveness and current capacity. No auth required. GET /llms.txt This document. No auth required. GET /openapi.json OpenAPI 3.1 spec. No auth required. ## Models gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4, gpt-5.4-mini Any model name is accepted. A name this backend does not have is served by the default model (gpt-5.6-sol) instead of being refused, so a client configured for another provider still works. The response's "model" field reports what actually ran. Reasoning effort: low | medium | high | xhigh | max (model-dependent). Set it with the "reasoning_effort" parameter, or as a suffix on the model name when your client cannot send that parameter: {"model": "gpt-5.6-sol:high", "messages": [...]} Precedence: reasoning_effort > model suffix > server default. ## Supported parameters messages Required. Roles: system, developer, user, assistant. Content may be a string or an array of parts. Image parts (image_url, including data: URLs) are supported. model See above. stream Boolean. Server-sent events, one chat.completion.chunk per frame, terminated by "data: [DONE]". stream_options {"include_usage": true} appends a final usage frame whose "choices" array is empty. reasoning_effort See above. response_format {"type": "text"} {"type": "json_object"} {"type": "json_schema", "json_schema": {"name": ..., "schema": {...}}} ## Refused parameters These return 400 rather than being silently ignored, because ignoring them produces a client that misbehaves with no way to see why. tools, functions codex runs its own tools inside its sandbox and never hands a tool call back to the caller, so an agent framework pointed here would loop forever waiting for one. A 400 says so immediately. tool / function role messages The other half of the same story: there are no tool calls to respond to. n > 1 codex produces one completion per turn. ## Accepted but ignored temperature, top_p, presence_penalty, frequency_penalty, logit_bias, max_tokens, max_completion_tokens, stop, seed, logprobs, top_logprobs, user, service_tier Accepted so that default client configurations work unchanged. They have no effect. Do not rely on temperature or seed for determinism, or on max_tokens for truncation. ## Differences from the OpenAI API Every request carries a large fixed prompt cost codex sends its own base instructions and tool definitions on each turn, so expect roughly 9,000–10,000 prompt tokens before your own text — even for a one-word question. Much of it comes back cached (see prompt_tokens_details.cached_tokens). This endpoint suits ordinary conversational and reasoning work; it is a poor fit for high-volume, low-latency, cost-per-token workloads. Sampling parameters do nothing temperature, top_p, seed and the penalties are accepted for compatibility and ignored. Determinism knobs in particular are NOT honoured — do not rely on seed. max_tokens does not truncate There is no output-length control. Ask for brevity in the prompt instead. No tool / function calling See the refusals above. Unknown model names fall back A model this backend does not have is served by the default model rather than refused, so a client hard-wired to another provider's model name still works. The response's `model` field always reports what actually ran — check it if you care. finish_reason is always "stop" There is no length-based truncation to report. Concurrency is limited and requests may queue Over the limit, a request waits briefly and then receives 429 with Retry-After. Back off and retry. ## Errors Standard OpenAI error envelope: {"error": {"message": "...", "type": "...", "param": null, "code": null}} 400 invalid_request_error Malformed body, or a parameter this endpoint refuses (tools, n>1, a tool-role message). 401 invalid_request_error / invalid_api_key Missing or wrong bearer key. 404 invalid_request_error Unknown route, or an OpenAI endpoint this backend does not implement. 405 invalid_request_error Wrong method for the route. 413 invalid_request_error Body over the size limit. 429 rate_limit_error All concurrency slots busy and the queue wait elapsed. Honour Retry-After. 500 server_error The turn failed, or the backend is unreachable. 502 — The backend is not currently connected. Retry shortly. When a stream has already started, a failure arrives as a frame containing an "error" object, followed by "data: [DONE]" — the HTTP status is already 200 by then. Every response carries an x-request-id header. Include it when reporting a problem. ## Rate limits and concurrency At most 4 turns run at once; beyond that, requests queue briefly and then receive 429 with a Retry-After header. Honour it. The backend runs on a personal subscription with rolling usage windows. Sustained parallel load will exhaust them. Prefer sequential requests, keep concurrency modest, and retry 429 and 5xx with exponential backoff. ## Notes for agents - Treat this as OpenAI's API. Existing OpenAI client code works unchanged apart from base_url and api_key. - Do not send "tools". Tool calling is not available. If you need the model to perform work, describe it in the prompt. - Conversation state is not stored. Send the full "messages" array every time, as the OpenAI API requires. - Expect a higher fixed prompt-token cost per request than OpenAI's API, and higher first-token latency (typically a few seconds).