API Spec
Chat identity, usage and cost, endpoints, parameters, and errors.
Chat Identity
The API needs to know which conversation each request belongs to.
prompt_cache_key alone is not enough for that, so the thread-id header tells
conversations apart. OpenAI's Codex client identifies conversations the same way.
With only prompt_cache_key, forks, subagents, and side chats are not guaranteed
to work: the API cannot always tell which conversation a request belongs to.
Using one thread-id for different chats, or one prompt_cache_key for different
chats without thread-id, causes conversation conflicts and request errors.
Send a thread-id header with every Responses and Chat Completions request:
thread-id: UNIQUE_THREAD_ID_FOR_EACH_CHAT- Generate one ID per conversation, such as a UUID. Reuse it for every message and retry in that conversation.
- Give each subagent, side chat, and fork its own ID, even when they share a
prompt_cache_key. - The API routes requests with the same ID together, so they can reuse cached input.
- IDs apply only within your API key.
- If
thread-idis missing, the API usesprompt_cache_keyfrom the request body as the conversation ID.
Usage and cost
All amounts are in USD. The charge is the price after your discount. The API deducts it from your balance.
cost means different things in different places. In a response and in a receipt,
usage.cost is the charge. In /v1/usage, cost is the standard price before your
discount and actual_cost is the charge.
In each response
Each response ends with its final usage. The fields below are inside it.
| What you need | Chat Completions | Responses | Images |
|---|---|---|---|
| Where | Response body, or the last chunk when streaming | Response body, or response.completed when streaming | Response body, or the last .completed event when streaming |
| Actual charge with your discount | cost | cost | cost |
| Input tokens, including cached | prompt_tokens | input_tokens | input_tokens |
| Cached input tokens | cached_tokens in prompt_tokens_details | cached_tokens in input_tokens_details | — |
| Output tokens, including reasoning | completion_tokens | output_tokens | output_tokens |
| Reasoning tokens | reasoning_tokens in completion_tokens_details | reasoning_tokens in output_tokens_details | — |
| Total tokens | total_tokens | total_tokens | total_tokens |
No cost means the API did not charge the request. To get the charge later, call
GET /v1/responses/{id}/receipt with the id of the response and read usage.cost.
Totals for your key
GET /v1/usage returns totals for the API key that calls it.
| What you need | Request | Field |
|---|---|---|
| Spending | GET /v1/usage | usage.today.actual_cost for the current UTC day, usage.total.actual_cost for all time |
| Tokens | GET /v1/usage | input_tokens without cached tokens, cache_read_tokens, output_tokens, total_tokens in usage.today and usage.total |
| Spending and tokens per day | GET /v1/usage?days=7&timezone=Europe/Berlin | daily_usage[]. days is 1 to 90, default 30. timezone is an IANA name, default UTC. |
| Spending and tokens per model | GET /v1/usage?start_date=2026-10-01&end_date=2026-10-14 | model_stats[]. Dates are YYYY-MM-DD in UTC, default the last 30 days. |
| Remaining balance | GET /v1/usage | balance, shared by all keys of your account |
Endpoints
Paths are relative to https://openai.inference.cheap. All require an API key.
| Endpoint | Status | Notes |
|---|---|---|
POST /v1/responses | Supported | |
POST /v1/chat/completions | Supported | |
POST /v1/responses/compact | Supported | Compacts the input you send. |
GET /v1/models, GET /v1/models/{id} | Supported | Lists the models available to your key. |
POST /v1/files, GET /v1/files | Supported | Up to 32 MiB per file. Files belong to your API key and are stored apart from conversations. |
GET /v1/files/{id}, DELETE /v1/files/{id}, GET /v1/files/{id}/content | Supported | |
POST /v1/images/generations, POST /v1/images/edits | Supported | Requires image access for your key. See the guide. |
GET /v1/usage | Supported | Balance and spending for your key. See Usage and cost. |
GET /v1/responses/{id}/receipt | Supported | Charge for one response. See Usage and cost. |
POST /v1/responses/input_tokens | Error | Returns 400 unsupported_operation. |
GET /v1/responses/{id}, DELETE /v1/responses/{id} | Error | Returns 404. The API does not store responses. |
GET /v1/responses/{id}/input_items, POST /v1/responses/{id}/cancel | Error | Returns 404. |
/v1/conversations and its subroutes | Error | Returns 404. |
An Idempotency-Key header returns 501 unsupported_feature.
Parameter support
All models are reasoning models. The tables use three statuses:
- Supported The model receives the parameter.
- Ignored The API drops the parameter and the request still succeeds. Where a
note gives a range, the API checks it first and returns
400for values outside it. - Error The API rejects the request.
Both endpoints ignore unknown top-level fields.
Chat Completions
| Parameter | Status | Notes |
|---|---|---|
messages, model | Supported | Get model IDs from /v1/models. |
audio, modalities | Ignored | The API returns text only. |
frequency_penalty, presence_penalty | Ignored | Range −2 to 2. |
functions, function_call | Supported | The API converts them to tools and tool_choice. |
logit_bias | Ignored | |
logprobs, top_logprobs | Ignored | Responses have no log probabilities. |
max_completion_tokens, max_tokens | Supported | Minimum 16. The limit includes reasoning tokens. If you send both, max_completion_tokens applies. |
metadata, moderation, prediction | Ignored | |
n | Supported | 1 to 8. Each choice is a separate generation with its own charge. |
parallel_tool_calls, tool_choice | Supported | |
prompt_cache_key | Supported | Identifies the conversation when thread-id is missing. See Chat Identity. |
prompt_cache_options, prompt_cache_retention | Ignored | |
reasoning_effort | Supported | Allowed values depend on the model. |
response_format | Supported | text, json_object, and json_schema with strict. |
safety_identifier, user | Ignored | |
seed | Ignored | Repeated requests can return different output. |
service_tier | Supported | fast is an alias for priority. |
stop | Supported | Up to 4 strings. Generation ends at the first match, and the API estimates usage for the delivered text. |
store | Ignored | The API stores nothing. |
stream, stream_options.include_usage | Supported | An error can arrive inside the stream after HTTP 200. |
temperature, top_p | Ignored | temperature 0 to 2, top_p 0 to 1. |
tools | Supported | function and custom tools. |
verbosity | Ignored | Use text.verbosity in Responses. |
web_search_options | Ignored | Use the web_search tool in Responses. |
Responses
| Parameter | Status | Notes |
|---|---|---|
input, instructions, model | Supported | Get model IDs from /v1/models. |
background | Error | true returns 501. |
context_management | Supported | Only the compaction type. |
conversation, previous_response_id | Error | Returns 501. Send the full history instead. |
include | Supported | The API ignores message.output_text.logprobs. |
max_output_tokens | Supported | Minimum 16. The limit includes reasoning tokens. |
max_tool_calls, moderation, top_logprobs | Ignored | |
metadata | Ignored | Up to 16 string pairs. |
parallel_tool_calls, tool_choice | Supported | |
prompt | Ignored | Stored prompts are unavailable. Send input. |
prompt_cache_key | Supported | Identifies the conversation when thread-id is missing. See Chat Identity. |
prompt_cache_options, prompt_cache_retention | Ignored | |
reasoning | Supported | effort and summary. Allowed values depend on the model. |
safety_identifier, user | Ignored | |
service_tier | Supported | fast is an alias for priority. |
store | Ignored | The API stores nothing. |
stream | Supported | HTTP 200 alone does not mean success. Handle response.failed and response.incomplete. |
stream_options | Ignored | |
temperature, top_p | Ignored | temperature 0 to 2, top_p 0 to 1. |
text | Supported | format (text, json_object, json_schema with strict) and verbosity. |
tools | Supported | function, custom, web_search, and image_generation (guide). Support for other hosted tools depends on the model. file_search returns 400. |
truncation | Ignored |
Errors
| Status | What to do |
|---|---|
400 | Read error.message and error.param, then fix the request. |
401 / 403 | Check your key and access. |
404 | Check the endpoint, model, and resource IDs. |
413 | Reduce the payload. |
429 | Reduce concurrency and respect Retry-After. |
501 | Remove the unsupported feature named in the error. Retrying unchanged does not help. |
Other 5xx | Retry with bounded backoff. |
After a timeout there is no stored response to fetch and no idempotent replay. A
retry is a new execution and can be charged again. Keep the same thread-id and
resend the full context.