Skip to content

Responses API

POST /v1/responses, the OpenAI Responses schema, streaming and non-streaming, for every catalog model. Same key, same models, same prices as chat completions.

This is the request shape agent tools use: Codex works against Keln out of the box (setup below), and so does any SDK or tool built on the Responses schema.

curl https://api.keln.ai/v1/responses \
  -H "Authorization: Bearer $KELN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "moonshotai/kimi-k3",
    "input": "Say hello from Keln.",
    "stream": true
  }'

Stateless by design

Keln serves the stateless Responses subset: conversation state lives in your client, and each request carries the full input. That is exactly how Codex and most agent frameworks already work (they send store: false on every call). The stateful features are refused with named errors:

You send You get
store: true 400 with code store_not_supported
previous_response_id 400 with code previous_response_id_not_supported
input containing an item_reference 400 with code item_reference_not_supported

Everything else about the request either works or fails with a named error.

Parameters

Parameters Contract
model, input required. input is a string or an item array: message items (input_text / output_text / input_image parts), function_call, and function_call_output items, the standard agent turn shape
instructions honored, becomes the system context for the request
stream typed Responses event stream, see Streaming events
max_output_tokens output cap. As everywhere on Keln, the cap covers reasoning and answer together, don't set it small on a reasoning model
reasoning: {effort, summary} same contract as reasoning_effort on chat completions; summary is accepted (the reasoning trace is returned as reasoning output items either way)
tools, tool_choice the flat Responses tool shape ({"type": "function", "name": …, "parameters": …}); tool_choice supports auto / none / required / {"type": "function", "name": …}
text: {format: {type: "json_schema", …}} structured output, with the same validation contract as chat completions (details)
prompt_cache_key send it, a stable per-session value keeps a session's turns on warm capacity, so repeated context bills at the per-model cached rate and starts faster. Codex sends its session id here automatically
temperature, top_p, parallel_tool_calls, metadata, user same contracts as chat completions (metadata and user are accepted and never forwarded upstream, ZDR)
anything else accepted and ignored, or refused with a named 400 where honoring it matters, an unknown key never breaks your request

Response object

Non-streaming requests return a full response object: id, status (completed / incomplete), output (reasoning items, message items, function_call items), and usage with input_tokens, output_tokens, total_tokens, input_tokens_details.cached_tokens, and output_tokens_details.reasoning_tokens.

An output cut short by max_output_tokens comes back as status: "incomplete" with incomplete_details.reason: "max_output_tokens", the spec's shape.

Streaming events

stream: true returns the typed Responses event stream: response.createdresponse.in_progressresponse.output_item.added → content/argument deltas → response.output_item.doneresponse.completed (or response.incomplete / response.failed), each event carrying its event: line and a gapless sequence_number. usage arrives on the terminal event. A turn is over when you see response.completed, the same rule Codex applies.

Using Codex

Add Keln as a provider in ~/.codex/config.toml:

model = "moonshotai/kimi-k3"          # any /v1/models id with the Tools badge
model_provider = "keln"

[model_providers.keln]
name = "Keln"
base_url = "https://api.keln.ai/v1"
env_key = "KELN_API_KEY"              # export KELN_API_KEY=sk-keln-…

Notes that matter in practice:

  • Model choice: pick a model with the Tools badge on Models & pricing.
  • Retries and timeouts: Codex defaults are fine. Long prompts stream response.created immediately, so Codex's idle timeout only fires on a genuinely dead connection.
  • Caching: Codex stamps prompt_cache_key with its session id on every turn, so long sessions automatically bill repeated context at the cached rate.
  • The ChatGPT desktop app's Codex shares the same config.toml, the block above makes Keln models available there too.

Send OpenAI's hosted tool, { "type": "web_search" }, and Keln runs the search: a web_search_call item per search with its lifecycle events, citations on the answer, usage.web_search_requests, and action.sources when you include web_search_call.action.sources. Codex sends the tool by default, so it searches through Keln with no extra setup. Details and price on Web search.