Skip to content
kenari.

Responses

Create a model response with the OpenAI Responses format. This is a stateless subset built for coding agents such as Codex, and the official OpenAI SDKs work once you point the base URL at https://kenari.id/v1. For Codex configuration, see Codex.

POST /v1/responses

Authenticate with Authorization: Bearer kn-.... See Authentication and API keys.

kenari stores nothing between requests, so send the whole conversation in input every time.

  • A previous_response_id other than null returns 400.
  • store is accepted and ignored.
  • There are no endpoints to retrieve, list or delete a response.
FieldTypeRequiredDescription
modelstringYesA catalog id, a :free id, a route name or a byok/ id. The same values as in Chat completions.
inputstring or arrayYesA string is one user message. An array holds input items. It must not be empty.
instructionsstringNoSystem instructions. Merged with any leading developer items.
toolsarrayNoFlat function tools, each with type set to function, plus name, description and parameters. A function tool without name returns 400. kenari server tools such as {"type": "kenari:web_search"} also work. Every other tool type is dropped without an error. See Function calling and Server tools.
tool_choicestring or objectNoauto, none, required or {"type": "function", "name": "get_weather"} to force one function. Anything else returns 400.
reasoningobject or nullNo{"effort": "low"}. Levels are none, minimal, low, medium, high, xhigh and max. summary is accepted and ignored. See Reasoning.
max_output_tokensintegerNoUpper limit on generated tokens, reasoning included. Default 65,536.
temperaturenumberNoSampling temperature.
top_pnumberNoNucleus sampling.
streambooleanNoSet true to receive Server-Sent Events. See Streaming.
textobjectNoOnly {"format": {"type": "text"}} is accepted. Any other format returns 400. For JSON output, use Chat completions and see Structured output.
prompt_cache_keystringNoA stable id for one conversation, so follow-up requests reuse its cached prefix. Up to 512 bytes. Longer or blank values are ignored. See Prompt caching.
previous_response_idstring or nullNoMust be absent or null.
storebooleanNoAccepted and ignored.
includearrayNoAccepted and ignored.
metadataobjectNoAccepted and ignored.
parallel_tool_callsbooleanNoAccepted and ignored.
ItemFieldsNotes
Messagerole, contentrole is system, developer, user or assistant. type may be omitted. content is a string or an array of parts.
Function calltype set to function_call, call_id, name, argumentsA call the model made earlier. arguments is a JSON string.
Function resulttype set to function_call_output, call_id, outputThe result for a call. output is a string or an array of text parts.
Reasoningtype set to reasoning, summary (an array)Earlier reasoning, handed back to the model.

Leading system and developer messages merge into the system prompt. Unknown item types are dropped without an error, and any other role returns 400.

Message parts are input_text and output_text, plus input_image with an image_url string, which is accepted only in user and assistant messages (in a developer message it returns 400). An input_file part returns 400. For documents, use Chat completions: a file part works on any model. See Images and files as input and Read documents.

The response is a response object. Its output array holds the items the model produced, in order.

{
"id": "resp_4f1c9a2e7b3d5a60",
"object": "response",
"created_at": 1790000000,
"status": "completed",
"model": "step-3-7-flash:free",
"output": [
{
"type": "message",
"id": "msg_1",
"role": "assistant",
"content": [{ "type": "output_text", "text": "Hello! How can I help?" }]
}
],
"usage": {
"input_tokens": 9,
"output_tokens": 12,
"total_tokens": 21,
"input_tokens_details": { "cached_tokens": 0 }
}
}
Output itemDescription
reasoningThe model’s reasoning as one summary_text entry. First in the array, and only present when the model reasoned.
messageThe answer, in an output_text part.
function_callA function the model wants you to run: call_id, name and arguments as a JSON string. Run it and send a function_call_output item with the same call_id in the next request.

status is completed, or incomplete with incomplete_details.reason set to max_output_tokens when the limit cut the answer short. usage.input_tokens_details.cached_tokens counts input served from cache and is part of input_tokens.

After you run a function, send a follow-up request that carries the earlier call and its result in input:

{
"model": "step-3-7-flash:free",
"input": [
{ "role": "user", "content": "What is the weather in Jakarta?" },
{
"type": "function_call",
"call_id": "call_1",
"name": "get_weather",
"arguments": "{\"city\": \"Jakarta\"}"
},
{ "type": "function_call_output", "call_id": "call_1", "output": "31 C and sunny" }
],
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
]
}

Set "stream": true to receive the response as Server-Sent Events. The event sequence is in Streaming.

Terminal window
curl https://kenari.id/v1/responses \
-H "Authorization: Bearer $KENARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "step-3-7-flash:free",
"instructions": "You answer briefly.",
"input": "Hello!"
}'
import os
from openai import OpenAI
client = OpenAI(base_url="https://kenari.id/v1", api_key=os.environ["KENARI_API_KEY"])
response = client.responses.create(
model="step-3-7-flash:free",
instructions="You answer briefly.",
input="Hello!",
)
print(response.output_text)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://kenari.id/v1",
apiKey: process.env.KENARI_API_KEY,
});
const response = await client.responses.create({
model: "step-3-7-flash:free",
instructions: "You answer briefly.",
input: "Hello!",
});
console.log(response.output_text);

Each request is billed per token at the model’s Input, Output, Cache read and Cache write prices. :free models cost nothing. See How billing works.

Errors use the OpenAI envelope: an error object with message, type, param and code. Only the errors specific to this endpoint are listed here. The rest, such as model_not_found, context_length_exceeded and subscribers_only, are in Errors.

StatusCodeWhen
400bad_requestinput is missing or empty. previous_response_id is not null. text.format is not text. A message has an unknown role. An input_file part is present. A function tool has no name. tool_choice is not one of the supported forms.
400bad_requestThe model is not a chat model, such as an image or speech model. The message names the endpoint to use instead.