Chat Completions API request shape
POST /v1/chat/completions accepts the OpenAI Chat Completions
request body. Kindo validates the core fields and forwards the rest
verbatim, which keeps the endpoint forward-compatible with new
OpenAI request fields.
Required fields
Section titled “Required fields”| Field | Type | Notes |
|---|---|---|
model | string | A model ID from GET /v1/models. |
messages | array | Must contain at least one entry. See Messages array. |
Standard fields
Section titled “Standard fields”| Field | Type | Forwarded? | Notes |
|---|---|---|---|
stream | boolean | — | Consumed by the route handler to switch into SSE mode. |
temperature | number | Yes | Sampling temperature. |
max_tokens | integer | Yes | Max tokens to generate. |
top_p | number | Yes | Nucleus sampling. |
frequency_penalty | number | Yes | |
presence_penalty | number | Yes | |
stop | string | array | Yes | Stop sequences. |
tools | array | Yes | OpenAI tool definitions (see Tool use). |
tool_choice | string | object | Yes | "auto", "none", "required", or {type: "function", function: {name: "..."}}. |
response_format | object | Yes | E.g. {type: "json_object"} or {type: "json_schema", ...}. |
user | string | Yes | End-user identifier. |
seed | integer | Yes | Determinism hint, where the upstream model supports it. |
logprobs | boolean / object | Yes | Forwarded to the upstream model. |
Anything not listed above passes through Kindo’s schema verbatim
because the validator uses passthrough(). Refer to OpenAI’s
Chat Completions spec
for full field semantics.
JSON mode
Section titled “JSON mode”Both variants of response_format are accepted:
{"type": "json_object"}— any JSON object.{"type": "json_schema", "json_schema": {...}}— forwarded whole, schema included, for models that enforce a schema.
How {"type": "json_object"} is enforced depends on the provider
backing the model you selected:
| Provider family | How it is enforced |
|---|---|
| OpenAI-format (OpenAI, Azure OpenAI, Groq, Mistral, DeepSeek, …) | Forwarded verbatim; the provider enforces JSON mode itself. |
| Gemini | Forwarded to the provider’s own JSON output mode. |
| Claude — direct, on Vertex AI, and on Bedrock | Translated by Kindo, because the provider has no schemaless JSON switch. The translation is not visible in the response. |
On those, choices[0].message.content is raw JSON you can parse
directly, with no markdown code fence, on both streaming and
non-streaming requests.
Three cases are not guaranteed:
- A provider with no JSON mode of its own — Cohere, for example.
response_formatis accepted and has no effect there, so the model may answer in prose or wrap the JSON in a markdown code fence. Parse defensively if your model group can route to one of these. {"type": "json_object"}sent together withtoolsortool_choice. On models without native JSON mode, Kindo will not suppress the tools you asked for in order to force JSON, so the response may be prose. Send ajson_schema, or omit the tools, when you need a parseable response from that combination.{"type": "json_object"}sent together with extended thinking (thinkingorreasoning_effort). Anthropic rejects the forced tool call that JSON mode is translated into when thinking is on, so on models without native JSON mode the response may be prose. Send ajson_schema, or drop the reasoning parameter, when you need a parseable response.
Stripped-on-ingress fields
Section titled “Stripped-on-ingress fields”Kindo strips these fields from the outgoing upstream request so clients can’t spoof governance metadata:
metadatalitellm_metadataproxy_server_request
Messages array
Section titled “Messages array”Each message has the following shape:
| Field | Required | Notes |
|---|---|---|
role | Yes | system, developer, user, assistant, or tool. |
content | No | String, array of content blocks, or null (for assistant messages with only tool_calls). Arrays are forwarded verbatim and support multimodal blocks. |
name | No | Author name. |
tool_calls | No | Tool calls generated by the model (present on assistant messages). |
tool_call_id | No | Required on role: "tool" messages — the ID of the tool call this message is responding to. |
developer is treated identically to system and matches OpenAI’s
own semantics.
Kindo extension fields
Section titled “Kindo extension fields”/v1/chat/completions is stock OpenAI — Kindo does not accept a
kindo request block on this surface. Kindo’s opt-in extensions
(curated system prompt, hosted tools, stateful conversations) are
available on /v1/responses; see the
Chat Actions guide.
Worked example
Section titled “Worked example”{ "model": "claude-sonnet-4-5-20250929", "messages": [ { "role": "system", "content": "You are a concise security assistant." }, { "role": "user", "content": "Summarize CVE-2024-3094." } ], "tools": [ { "type": "function", "function": { "name": "lookup_cve", "description": "Fetch CVE metadata.", "parameters": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] } } } ], "tool_choice": "auto", "max_tokens": 512, "temperature": 0.2}This is stock OpenAI Chat Completions. Kindo accepts it identically
to OpenAI’s /v1/chat/completions.
See also
Section titled “See also”- Quickstart — minimal client setup.
- Streaming — SSE protocol.
- Tool use — function-calling round trip.
- Errors — error envelope.
