Responses
POST/v1/responses
The same pipeline in the OpenAI Responses shape, for clients such as the Codex CLI that speak only that wire.
POST /v1/responses takes the OpenAI Responses request and answers in its objects and events. Behind it is the same pipeline as chat completions: the same routing, memory, connector tools, agent mode and allowances. It exists because some clients speak only this wire, the Codex CLI among them.
Memtro keeps no conversation state against a response id: send the whole input every turn, which is what these clients do anyway.
Example
Against https://platform.memtro.com, with your key in MEMTRO_API_KEY.
curl https://platform.memtro.com/v1/responses \
-H "Authorization: Bearer $MEMTRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"instructions": "Answer in one line.",
"input": "Who owns the billing migration?"
}'
from openai import OpenAI
client = OpenAI(base_url="https://platform.memtro.com/v1", api_key="sk-memtro-…")
response = client.responses.create(
model="auto",
instructions="Answer in one line.",
input="Who owns the billing migration?",
)
print(response.output_text)
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://platform.memtro.com/v1", apiKey: process.env.MEMTRO_API_KEY });
const response = await client.responses.create({
model: "auto",
instructions: "Answer in one line.",
input: "Who owns the billing migration?",
});
console.log(response.output_text);
A non-streaming reply.
{
"id": "resp-9cTz…",
"object": "response",
"created_at": 1794470400,
"status": "completed",
"model": "anthropic/claude-opus-5",
"output": [
{
"id": "resp-9cTz…-msg",
"type": "message",
"status": "completed",
"role": "assistant",
"content": [{ "type": "output_text", "text": "Priya owns it.", "annotations": [] }]
}
],
"output_text": "Priya owns it.",
"usage": { "input_tokens": 3120, "output_tokens": 9, "total_tokens": 3129 },
"memtro": { "mode": "chat", "routing": { "requested": "auto", "model": "anthropic/claude-opus-5", "complexity": 1, "method": "heuristic", "reason": "…", "fallbacks": ["…"], "kind": "general" } }
}
Authentication
An API key, as Authorization: Bearer or x-api-key.
- Every reply, errors included, carries
x-request-idandrequest-idheaders with the same id, startingresp-. Quote it to support. - Browsers may call it from any origin: it answers CORS preflights and allows the
Authorization,x-api-keyand Anthropic version headers.
Request body
JSON, with Content-Type: application/json.
modelstringOptionalA model id or routing id; see Model ids. The older
brainalias for thememtrofield is not read on this wire.inputstring or array of objectsRequiredA string (one user turn), or an array of items. Items that are not turns (
reasoning,item_reference, a built-in tool's call, a compaction marker) are skipped, which is what a client replaying its own history sends.5 fields of
inputtypestringOptionalmessage(or absent),function_callorfunction_call_output.rolestringOptionalFor a message.
contentstring or array of objectsOptionalFor a message: text, or parts of type
input_text,output_text(withtext) orinput_image(withimage_url, a URL string or{url}; adata:URI or absolute http(s) URL).name, arguments, call_idstringOptionalFor a
function_call: the tool, its arguments as a JSON string, and the call's id (idis read whencall_idis absent).outputanyOptionalFor a
function_call_output, with itscall_id: your tool's result.
instructionsstring or nullOptionalBecomes a system message.
toolsarray of objectsOptionalFunction tools,
{"type": "function", "name", "description", "parameters"}, returned to you asfunction_calloutput items. Other kinds (acustomfreeform tool, built-ins such asweb_search) cannot be carried and are left out of what the model is offered, without an error.tool_choicestring or objectOptionalnone,auto,required, or{"type": "function", "name": …}.streambooleanOptionalAnswer as named server-sent events. See Streaming.
temperaturenumber or nullOptionalPassed to the provider.
top_pnumber or nullOptionalPassed to the provider.
max_output_tokensinteger or nullOptionalA ceiling on the answer's tokens. An answer cut short by it ends
incomplete.reasoningobject or nullOptionaleffortis read as chat completions'reasoning_effort.1 field of
reasoningeffortstring or nullOptionalhigh,xhigh,max,mediumorlow.
store, previous_response_idanyOptionalAccepted and ignored: nothing is stored against a response id.
memtroobjectOptionalMemtro's options, the same keys as on chat completions; see the
memtroobject.
Response
200application/json
A response object.
idstringOptionalresp-…, the same id as thex-request-idheader.object"response"OptionalAlways
response.created_atintegerOptionalUnix time, in seconds.
statusstringOptionalincompletewhenmax_output_tokenscut the answer short.modelstringOptionalThe model that was picked.
outputarray of objectsOptionalA
messageitem withoutput_textcontent, and afunction_callitem (name,call_id,arguments) for each call to your tools.output_textstringOptionalThe answer's text, joined.
usageobjectOptionalinput_tokens,output_tokens,total_tokens.incomplete_detailsobjectOptionalWhen incomplete:
{"reason": "max_output_tokens"}.memtroobjectOptionalAs on chat completions; see What comes back.
200text/event-stream
With stream: true: named events, each also carrying type and a sequence_number. See Streaming.
Streaming
Every event has an event: line and a data: line whose JSON repeats the name as type, with a sequence_number. The run opens with response.created and response.in_progress; the answer comes as response.output_item.added, response.content_part.added, response.output_text.delta events, then response.output_text.done, response.content_part.done and response.output_item.done. A call to one of your tools is its own output item, with response.function_call_arguments.delta and .done. In agent mode, progress arrives as a reasoning item's response.reasoning_summary_text.delta events. The stream ends with response.completed, response.incomplete (status: "incomplete", incomplete_details.reason: "max_output_tokens") or response.failed, whose error has the code upstream_error.
event: response.created
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp-9cTz…","object":"response","status":"in_progress","output":[],…}}
event: response.in_progress
data: {"type":"response.in_progress","sequence_number":1,…}
event: response.output_item.added
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"resp-9cTz…-msg","type":"message","status":"in_progress","role":"assistant","content":[]}}
event: response.content_part.added
data: {"type":"response.content_part.added","sequence_number":3,…}
event: response.output_text.delta
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"resp-9cTz…-msg","output_index":0,"content_index":0,"delta":"Priya owns it."}
event: response.output_text.done
data: {"type":"response.output_text.done","sequence_number":5,…,"text":"Priya owns it."}
event: response.content_part.done
data: {"type":"response.content_part.done","sequence_number":6,…}
event: response.output_item.done
data: {"type":"response.output_item.done","sequence_number":7,…}
event: response.completed
data: {"type":"response.completed","sequence_number":8,"response":{"id":"resp-9cTz…","status":"completed","output_text":"Priya owns it.","usage":{"input_tokens":3120,"output_tokens":9,"total_tokens":3129},…}}
Errors
In the OpenAI envelope, {"error": {"message", "type", "param", "code"}}. What each code means and what to do about it is in the error catalogue.
| Status | Code | When |
|---|---|---|
| 400 | none | The body failed validation, or an image URL cannot be used. |
| 400 | invalid_as_of |
|
| 400 | routing_unavailable |
|
| 400 | provider_not_configured | No key for the provider the model needs. |
| 400 | invalid_provider_base_url | An OpenAI-compatible endpoint's base URL cannot be used: not a URL, not |
| 400 | provider_base_url_not_allowed | An OpenAI-compatible endpoint's host is not approved for the organisation, is private or internal, does not resolve, or redirected, whether refused before the request or during it. |
| 401 | invalid_api_key | The key is missing, malformed, revoked or expired. |
| 402 | subscription_inactive | The organisation has no active subscription. |
| 404 | model_not_found | Unknown model id. |
| 429 | allowance_exhausted | The month's allowance for the request's level is spent. |
| provider's | upstream_error | The provider returned an error. |
| 503 | engine_unavailable | The CLI a |
| 500 | none | An internal error. |