Responses
The OpenAI-compatible Responses API on Zumik. Create responses with function tools and streaming, retrieve, delete, and cancel them, list input items, compact context, and count input tokens.
The Responses API is OpenAI's stateful generation surface. Zumik mirrors its shapes exactly: function tools, tool-call round trips, previous_response_id chaining, and Server-Sent Events streaming all work with the official SDK. The input field accepts either a bare string or the structured input-item array. Proprietary signal rides on response headers, never the body.
Raw input items are retained for /input_items only when the project opts into full-fidelity retention. The default is metadata-only, so input items return an empty list. See retention and QoS.
Create a response
POST https://api.zumik.ai/v1/responsesmodelstringrequiredA Zumik alias such as code.balanced, or a concrete provider model.
inputstring | arrayrequiredEither a plain string prompt, or an array of structured input items (matching OpenAI's input-item shape). Item arrays may include message items, function_call items, and function_call_output items carrying tool results back to the model.
previous_response_idstringContinue from a prior stored response instead of resending its turns. Its output — including any function_call items — is prepended as context.
toolsarrayFunction tools the model may call, in the Responses flat shape: {"type": "function", "name": "...", "description": "...", "parameters": {...}, "strict": true}. Only function tools are supported; hosted tool types (web_search, file_search, …) are rejected with a 400. See function calling.
tool_choicestring | object"auto" (the provider default), "none", "required", or {"type": "function", "name": "..."} to force one specific function. Forcing a call without tools is rejected with a 400.
temperaturenumberSampling temperature. Optional; passed through to the resolved provider.
top_pnumberNucleus sampling. Must be greater than 0 and at most 1; out-of-range values are rejected with a 400 naming the parameter.
max_output_tokensintegerMaximum tokens to generate. Optional; passed through to the resolved provider.
streambooleandefault: falseWhen true, the response arrives as Responses-API Server-Sent Events (text/event-stream) instead of a single JSON body. See streaming.
Request
curl https://api.zumik.ai/v1/responses \
-H "Authorization: Bearer zk_live_..." \
-H "Content-Type: application/json" \
-d '{"model":"code.balanced","input":"Review the latest patch."}'Response
{
"id": "resp_01jy7n3q8v6m4k2x...",
"object": "response",
"created_at": 1750000123,
"status": "completed",
"model": "code.balanced",
"output": [
{
"type": "message",
"role": "assistant",
"content": [
{ "type": "output_text", "text": "The patch looks correct; add a test for the empty case." }
]
}
],
"usage": {
"input_tokens": 6,
"output_tokens": 11,
"total_tokens": 17
}
}idstringThe response id, resp_....
objectstringAlways "response".
created_atintegerUnix timestamp (seconds).
statusstringcompleted, or cancelled after a cancel.
outputarrayOutput items. Each message item carries a role and a content array of parts (type: "output_text" with text). When the model calls a tool, the array also carries function_call items.
usageobjectinput_tokens, output_tokens, total_tokens.
Function calling
Pass tools and the model can answer with function_call output items instead of (or alongside) a message. Execute the call on your side, then send the result back as a function_call_output input item. Tool-calling requests run on the same transparent execution path as /v1/chat/completions, so they work on every provider — including Anthropic models via the built-in translation.
resp = client.responses.create(
model="code.balanced",
input="What is in src/?",
tools=[{
"type": "function",
"name": "list_files",
"description": "List the files in a directory",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
}],
)The model's call arrives as a function_call item:
{
"output": [
{
"type": "function_call",
"id": "fc_x7k2...",
"call_id": "call_x7k2...",
"name": "list_files",
"arguments": "{\"path\":\"src/\"}",
"status": "completed"
}
]
}Run the tool, then answer the call. The shortest loop chains from the stored response, so the prior tool calls don't need to be resent:
followup = client.responses.create(
model="code.balanced",
previous_response_id=resp.id,
tools=tools, # resend so the model can keep calling
input=[{
"type": "function_call_output",
"call_id": resp.output[0].call_id,
"output": "main.rs lib.rs providers.rs",
}],
)Parallel calls come back as multiple function_call items; answer each with its own function_call_output carrying the matching call_id.
Under the default metadata-only retention the input of the previous response is not stored, so a chained request rebuilds context from its stored output only. Agents that need the full conversation in view should send the item list back themselves — message, function_call, and function_call_output items in order, without previous_response_id. Both forms are accepted.
Streaming
Set stream: true to receive the response as the Responses SSE event protocol. Each event is an event: line naming the type and a data: line carrying the payload with a monotonic sequence_number. Billing is settled before the first event, so the usage in response.completed matches what you were charged — the same buffered model as chat streaming.
The event sequence for a text response:
event: response.created
event: response.in_progress
event: response.output_item.added
event: response.content_part.added
event: response.output_text.delta (one or more; deltas concatenate to the full text)
event: response.output_text.done
event: response.content_part.done
event: response.output_item.done
event: response.completedA function_call item streams as response.output_item.added, one or more response.function_call_arguments.delta events, response.function_call_arguments.done, then response.output_item.done. The terminal response.completed event carries the full final response object; there is no [DONE] sentinel — the Responses protocol ends on response.completed.
stream = client.responses.create(
model="code.balanced",
input="Stream a short answer.",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="")Retrieve a response
GET https://api.zumik.ai/v1/responses/{response_id}response_idstringpathrequiredThe resp_... id.
Returns the stored response object exactly as it was created. 404 if it does not exist for this project.
curl https://api.zumik.ai/v1/responses/resp_01jy... \
-H "Authorization: Bearer zk_live_..."Delete a response
DELETE https://api.zumik.ai/v1/responses/{response_id}{ "id": "resp_01jy...", "object": "response.deleted", "deleted": true }404 if the response does not exist for this project.
Cancel a response
POST https://api.zumik.ai/v1/responses/{response_id}/cancelMarks the response cancelled and returns the updated object. 404 if it does not exist for this project.
{ "id": "resp_01jy...", "object": "response", "status": "cancelled", "...": "..." }List input items
GET https://api.zumik.ai/v1/responses/{response_id}/input_itemsReturns the input items that produced the response, as a list.
{
"object": "list",
"data": [
{ "type": "input_text", "text": "Review the latest patch." }
],
"has_more": false
}When the project's retention is metadata-only (the default), inputs were not stored, so data is an empty list rather than a 404. A genuine unknown id returns 404.
Compact context
POST https://api.zumik.ai/v1/responses/compactFold a long prior context into a shorter, model-generated summary to stay within a context
budget. The summary is produced through the broker (degrading to a deterministic summary when no
gateway is configured) and persisted as a reusable compaction_summary artifact
you can reference later. Because it makes a model call, this endpoint is budget-gated like inference.
inputstring | arrayrequiredThe context (string or input items) to compact.
modelstringThe model to summarize with. Defaults to auto.cheapest.
{
"object": "response.compaction",
"id": "cmp_01jy...",
"artifact_id": "art_01jy...",
"model": "gemini/gemini-2.0-flash",
"summary": { "type": "compaction_summary", "text": "The agent chose Postgres, wrote the schema, ran tests, and fixed two failures." },
"original_input_tokens": 1840,
"compacted_input_tokens": 460,
"live": true
}objectstringAlways "response.compaction".
artifact_idstringThe persisted compaction_summary artifact (art_...) holding the summary, so it can be reused or referenced from a session event.
modelstringThe resolved provider/model that produced the summary.
original_input_tokensintegerToken count of the input before compaction.
compacted_input_tokensintegerToken count after compaction; never greater than the original.
livebooleantrue when a model produced the summary; false on the deterministic degrade path.
For session-aware compaction — folding a branch's older turns into a checkpoint while keeping a verbatim tail, with recovery — see compacting a branch.
Count input tokens
POST https://api.zumik.ai/v1/responses/input_tokensEstimate the token count of an input without running a generation.
inputstring | arrayrequiredThe input to count.
{ "object": "response.input_tokens", "input_tokens": 6 }Errors
| HTTP | code | When |
|---|---|---|
| 400 | (none) | top_p out of range, an unsupported tool type, or a malformed tool_choice. The error names the offending param. |
| 401 | invalid_api_key | Missing or invalid bearer key. |
| 402 | credits_required | The prepaid credit balance is empty (create only). |
| 404 | (none) | The response id does not exist for this project. |
| 429 | quota_exceeded | Budget reached (create only). |
| 502 | (none) | The upstream provider failed on a tool-calling request, which cannot degrade to a tool-less answer. Retry. |
| 504 | deadline_exceeded | A QoS deadline elapsed (create only); not charged. |
See the full error reference.
Pagination
How Zumik list endpoints return results. Lists are returned in full as a single page; the list envelope carries has_more for forward compatibility.
Chat completions
POST /v1/chat/completions. The exact OpenAI chat-completions shape, including streaming over Server-Sent Events and stream_options.include_usage.