OpenFill is in development. Inference is off, but is tested end to end, and will switch on at launch. All data currently on the site is for live testing: it will be erased at launch.

Skip to content
openfill

Responses API

The OpenAI Responses shape, translated at the edge onto the same order pipeline as chat. A request here is priced, queued, charged, logged and replayed exactly as a chat request; only the wire differs. It keeps no state between calls, so each turn resends its input.

Create a response

POST /v1/responses
curl https://api.openfill.ai/v1/responses \  -H "Authorization: Bearer $OPENFILL_API_KEY" \  -H "Content-Type: application/json" \  -d '{"model": "market-preview", "input": "hi", "price_limit": 0.10}'

Request body

The Responses fields first, then the OpenFill extensions, which carry the same names and rules as on chat, except store. Unlisted fields pass through unless the adapter drops them as described below.

FieldTypeDefaultMeaning
modelstringthe default modelA served model id or alias.
inputstring or arrayrequiredA string is one user message. An array holds message items with role user, assistant, system or developer and text parts, with input_image parts on a user message (image_url as a base64 data URL, or an http or https URL fetched as on chat), function_call items, function_call_output items and reasoning items, in conversation order.
instructionsstring or arraynoneA string becomes the first system message. An array takes the same items as input and is prepended to it.
toolsarraynoneFunction tools in the Responses shape, name and parameters at the top level. Every other tool type (web_search, namespace, file_search, mcp and the rest) is dropped without error, since Codex sends some by default and this market runs none of them; the model sees the function tools alone.
tool_choicestring or objectautonone, auto, required, or a named function. allowed_tools becomes auto or required from its mode; a choice naming a dropped tool falls back to auto.
max_output_tokensintegerthe model's max outputThe output cap, clamped down to the model's max output length.
temperature, top_pnumbernone0 to 2, and 0 to 1.
text.formatobjectnonejson_object and json_schema become response_format for the model; text is the default.
reasoning.effortstringnoneForwarded to the model as reasoning_effort. Summary settings are dropped.
parallel_tool_callsbooleannoneForwarded.
metadataobjectnoneUp to 16 string pairs, echoed on the live response and on an idempotent replay. Metadata is removed from the translated request that is stored or logged; a collected order result carries an empty object.
storebooleannoneAccepted and echoed. Storage here follows the account's data storage setting; retention_days below is the per-request switch.
streambooleanfalseServer-sent events, in the Responses event vocabulary. Terminal success events always carry usage.
text.verbosityas sentnoneEchoed in text; it does not change generation.
userstringnoneEchoed and kept on our side; removed before the model request.
stream_options, include, prompt_cache_key, safety_identifier, client_metadata, service_tier, max_tool_calls, context_management, access_programs, top_logprobs, prompt_cache_optionsas sentnoneAccepted and dropped by the adapter. They do not change generation or storage.
price_limitnumberkey or accountThe most you will pay, in USD per 1M input tokens at the reference mix. On a market model, none anywhere is 400 missing_price_limit. The X-Price-Limit header carries it for a tool with no body field. Ignored on a fixed-price model.
price_lockbooleanaccount settingBid the lower of the published quote and price_limit, and start within the execute window or expire with 429 capacity_unavailable. Ignored on a fixed-price model.
max_waitintegeraccount settingSeconds an unlocked order may wait. Alias expires_after; the X-Expires-After header carries it too.
retention_daysintegeraccount settingKeep this request's data for fewer days. 0 keeps nothing durable.

Price, wait and output bounds follow the chat request rules. Metadata has the same key, value and count bounds as batch metadata.

Refused with 400

SentWhy
previous_response_id, conversationThis endpoint keeps no state. Resend the full input each turn.
background: trueUse detached on POST /v1/chat/completions and poll the order.
promptServer-side prompt templates do not exist here; send the text in input.
truncation: autoThe input reaches the model unchanged, so it cannot be honoured.
detached: trueThe stored result is chat-shaped, so the detached path is POST /v1/chat/completions.
input_file and input_audio parts, and input_image by file_idAn image travels in image_url as a base64 data URL, or an http or https URL fetched as on chat. Nothing is charged.
item_reference and every hosted-tool call itemThey need server-side state or a tool the market does not run.

Response

The response object below. Its id prefixes the order id with resp_; remove that prefix or read usage.x_market.order_id before calling GET /v1/orders/{id}.

json
{  "id": "resp_<order_id>", "object": "response", "created_at": 1756800000, "completed_at": 1756800042,  "status": "completed", "error": null, "incomplete_details": null, "model": "market-preview",  "output": [    {"id": "rs_<order_id>", "type": "reasoning", "status": "completed", "summary": [],     "content": [{"type": "reasoning_text", "text": "..."}]},    {"id": "msg_<order_id>", "type": "message", "status": "completed", "role": "assistant",     "content": [{"type": "output_text", "text": "...", "annotations": []}]},    {"id": "fc_<order_id>_0", "type": "function_call", "status": "completed",     "call_id": "...", "name": "get_weather", "arguments": "{\"city\": \"Boston\"}"}  ],  "usage": {"input_tokens": 1234, "input_tokens_details": {"cached_tokens": 1000},            "output_tokens": 56, "output_tokens_details": {"reasoning_tokens": 0}, "total_tokens": 1290,            "x_market": {"order_id": "<order_id>", "pricing": "market", "level_at_execution": 0.23, "bid": 0.5, "charged_usd": 0.000446}},  "store": false, "metadata": {}}
FieldMeaning
statuscompleted on a normal finish; incomplete with incomplete_details.reason max_output_tokens when the cap stopped it, or content_filter when the model filtered it.
outputBlocking responses group reasoning, message and function calls in that order. A stream's terminal output preserves the item order and ids already sent. An item absent from the answer is absent from the list.
output[].content[].typereasoning_text carries the raw chain of thought; Codex shows it only with show_raw_agent_reasoning on.
usage.input_tokensEvery prompt token, cached ones included; input_tokens_details.cached_tokens says how many were cached.
usage.x_marketThe receipt: the order it ran as (order_id), the price it was charged at, what it bid, and the debit, with pricing and, on a fixed-price model, the prices applied, as on chat.
metadata, storeEcho the request, as do instructions, tools, tool_choice, text and reasoning.

Streaming

200 and a text/event-stream body. Every frame carries an event: line, the same name in the JSON type, and a sequence_number that starts at 0 and rises by one on every event. There is no [DONE] sentinel: the body ends after the terminal event.

a text answer, in order
event: response.createdevent: response.in_progress          <- optional keepalive during silence, or after requeueevent: response.output_item.addedevent: response.content_part.addedevent: response.output_text.delta    <- one per fragmentevent: response.output_text.doneevent: response.content_part.doneevent: response.output_item.doneevent: response.completed            <- carries the response object with usage and x_market
CaseEvents
A function calloutput_item.added with the call's name and call_id, function_call_arguments.delta per fragment, function_call_arguments.done, output_item.done.
Reasoning before the answerA reasoning item with reasoning_text.delta events, closed before the message item opens.
The output cap stopped itresponse.incomplete in place of response.completed, with incomplete_details.reason max_output_tokens.
An error after the stream openedOne response.failed event with response.error.code and message, then the body ends. The status stays 200. A settlement failure after generation can leave a recorded or uncertain charge; inspect the message and order before retrying.

The queue comment lines the chat stream writes are kept, and every keepalive also sends a response.in_progress event, during silence while queued or generating. An in-band error uses rate_limit_exceeded for a 429, order_expired for a 408, insufficient_quota for a 402, invalid_prompt for a 400, order_canceled for a 409, and server_error otherwise.

Statuses

The same statuses, envelope and charging rules as chat. An Idempotency-Key works here and a replay comes back in this shape; a streaming replay is the whole event sequence at once.