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?"
}'
- Python
- TypeScript
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)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.mindshub.ai/v1",
apiKey: process.env.MINDSHUB_API_KEY,
});
const response = await client.responses.create({
model: "sonnet",
input: "What is the capital of Australia?",
});
console.log(response.output_text);
Request parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
model | string | yes | A model alias from Models. |
input | string or array | yes | A plain string, or an array of input items. See Input. |
instructions | string | no | System-level guidance. Becomes a leading system message. |
stream | boolean | no | Default false. See Streaming. |
tools | array | no | Function tools and web_search. See Tools. |
tool_choice | string or object | no | "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_tokens | integer | no | Output cap. |
reasoning | object | no | Only effort is read; same semantics as reasoning_effort. |
temperature, top_p | number | no | Honored 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_textis the flattened assistant text, the same convenience field the OpenAI SDK exposes.outputcarries the structured items.outputcontainsmessageitems and, when the model calls tools,function_callitems.modelechoes back the alias you sent, unlike Chat Completions, which reports the resolved provider ID.input_tokens_details.cached_tokensreports prompt cache reads. Caching is automatic on most of the catalog; the Claude family currently caches only viacache_controlbreakpoints on Messages.output_tokens_details.reasoning_tokensis always0. Reasoning bills as output but isn't broken out separately here:output_tokensincludes 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 responseContent-Typebefore parsing. - A mid-stream failure closes the stream without a
response.completedevent. 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.
Built-in web search
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:
| Header | Meaning |
|---|---|
X-MindsHub-Dropped-Params | Parameters removed for this model, e.g. top_k |
X-MindsHub-Clamped-Params | Values 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.