Skip to main content

Responses

POST /v1/responses implements the OpenAI Responses API. The OpenAI SDKs work against it with a base_url change, and, as everywhere else on MindsHub, any model in the catalog can serve a Responses request, not just OpenAI's. This is also the format OpenAI Codex speaks.

This endpoint is mid-upgrade. Today it accepts Responses-shaped input but returns Chat Completions-shaped output, so SDK helpers like response.output_text, streaming in the Responses event format, and Codex do not work against it yet. This page documents the full implementation as it rolls out. Today only model, input (a string or role/content messages, including input_text parts), stream, and reasoning.effort are honored; other parameters are accepted and ignored, and function_call / function_call_output input items are rejected with a 422. For production use today, call Chat Completions.

curl https://api.mindshub.ai/v1/responses \
-H "Authorization: Bearer $MINDSHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "sonnet",
"input": "What is the capital of Australia?"
}'
from openai import OpenAI
import os

client = OpenAI(
base_url="https://api.mindshub.ai/v1",
api_key=os.environ["MINDSHUB_API_KEY"],
)

response = client.responses.create(
model="sonnet",
input="What is the capital of Australia?",
)
print(response.output_text)

Request parameters

ParameterTypeRequiredNotes
modelstringyesA model alias from Models.
inputstring or arrayyesA plain string, or an array of input items. See Input.
instructionsstringnoSystem-level guidance. Becomes a leading system message.
streambooleannoDefault false. See Streaming.
toolsarraynoFunction tools and web_search. See Tools.
tool_choicestring or objectno"auto", "required", "none", or {"type": "function", "name": "..."}. On models that restrict forced choice a named or "required" choice is rewritten rather than rejected; see Chat completions → Tool calling for the per-model table.
max_output_tokensintegernoOutput cap.
reasoningobjectnoOnly effort is read; same semantics as reasoning_effort.
temperature, top_pnumbernoHonored where the target model supports them, dropped where it doesn't. See Parameter adaptation.

Accepted and ignored: store, previous_response_id, text, include, metadata, and any unknown top-level field. See Statelessness for what that means for previous_response_id.

Input

input takes a plain string, or an array of items for multi-turn conversations and richer content:

{
"model": "sonnet",
"input": [
{"role": "user", "content": "What's in this image?"},
{"role": "user", "content": [
{"type": "input_text", "text": "Describe the chart."},
{"type": "input_image", "image_url": "https://example.com/chart.png"}
]}
]
}

Supported item content types are input_text, output_text, and input_image. Tool round-trips use function_call and function_call_output items; see Tools.

Roles are system, user, and assistant. Prefer instructions over a system item for system-level guidance; both work.

The response

{
"id": "resp_9f2c1ae0b4d8",
"object": "response",
"created_at": 1785401283,
"status": "completed",
"model": "sonnet",
"output": [
{
"type": "message",
"id": "msg_1c40a2",
"role": "assistant",
"status": "completed",
"content": [
{"type": "output_text", "text": "Canberra.", "annotations": []}
]
}
],
"output_text": "Canberra.",
"usage": {
"input_tokens": 12,
"input_tokens_details": {"cached_tokens": 0},
"output_tokens": 4,
"output_tokens_details": {"reasoning_tokens": 0},
"total_tokens": 16
}
}

Notes on the shape:

  • output_text is the flattened assistant text, the same convenience field the OpenAI SDK exposes. output carries the structured items.
  • output contains message items and, when the model calls tools, function_call items.
  • model echoes back the alias you sent, unlike Chat Completions, which reports the resolved provider ID.
  • input_tokens_details.cached_tokens reports prompt cache reads. Caching is automatic on most of the catalog; the Claude family currently caches only via cache_control breakpoints on Messages.
  • output_tokens_details.reasoning_tokens is always 0. Reasoning bills as output but isn't broken out separately here: output_tokens includes it.

Streaming

Set "stream": true and you get the typed Responses event stream, with event: names matching the payload type:

event: response.created
event: response.in_progress
event: response.output_item.added
event: response.content_part.added
event: response.output_text.delta (repeated)
event: response.output_text.done
event: response.content_part.done
event: response.output_item.done
event: response.completed

The SDK's streaming helper parses this natively:

stream = client.responses.create(
model="sonnet",
input="Count to five.",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)

Tool calls stream as response.function_call_arguments.delta events between an output_item.added and output_item.done pair for the function_call item.

The final response.completed event carries the complete response object, including real token usage. Two behaviors to code around:

  • A request that fails before generation starts returns a JSON error, not an SSE stream, even with stream: true. Check the response Content-Type before parsing.
  • A mid-stream failure closes the stream without a response.completed event. A stream that ends without it was a failed generation.

Tools

Function tools use the Responses flat shape: name and parameters at the top level of the tool object, not nested under function:

{
"model": "sonnet",
"input": "What's the weather in Lisbon?",
"tools": [{
"type": "function",
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}]
}

The model's call arrives as a function_call item in output:

{"type": "function_call", "id": "fc_a91b", "call_id": "call_a91b",
"name": "get_weather", "arguments": "{\"city\": \"Lisbon\"}"}

Return the result by appending both the function_call item and a function_call_output item to input, then calling again:

{
"model": "sonnet",
"input": [
{"role": "user", "content": "What's the weather in Lisbon?"},
{"type": "function_call", "call_id": "call_a91b",
"name": "get_weather", "arguments": "{\"city\": \"Lisbon\"}"},
{"type": "function_call_output", "call_id": "call_a91b", "output": "19°C, light rain"}
],
"tools": [{"type": "function", "name": "get_weather", "description": "...", "parameters": {}}]
}

Echo call_id back exactly as received, and send the same tools array on the follow-up.

web_search maps onto the platform's web search on models where it's available:

{
"model": "sonnet",
"input": "What changed in the EU AI Act this month?",
"tools": [{"type": "web_search"}]
}

On models without search, the tool entry is dropped and the model answers from its own knowledge. Searches carry a per-search charge; see Billing. A forced tool_choice can't be applied to server-side search and is ignored when your tools array holds only web tools.

Statelessness

There is no conversation chaining on this endpoint. previous_response_id and store are accepted but not honored: chaining calls by response ID will not carry context forward, and no id ever comes back that you could chain with.

Send the full conversation in input each turn. This is what the OpenAI SDK does by default when you aren't chaining, so most code needs no change. Prompt caching makes resending history cheap on most models: repeated prefixes bill at roughly a tenth of the input rate.

Parameter adaptation

As on every MindsHub endpoint, parameters the target model doesn't support are dropped rather than rejected, and the response reports what changed:

HeaderMeaning
X-MindsHub-Dropped-ParamsParameters removed for this model, e.g. top_k
X-MindsHub-Clamped-ParamsValues adjusted to the model's range, as name=requested>applied

Neither header appears when nothing was changed. Details and boundaries in Core concepts.

Errors

Errors use the OpenAI envelope, so SDK error handling works unmodified:

{
"error": {
"message": "The model 'foo' does not exist or you do not have access to it.",
"type": "invalid_request_error",
"param": "model",
"code": "model_not_found"
}
}

Status codes and their meanings are shared across the API; see Errors.

Using Codex

Codex speaks this format exclusively, so once the upgrade above lands, wire_api = "responses" runs it on any catalog model, including Claude and Kimi. See Coding agents for the config, or MindsHub in Codex for the full guide and current status.