Chat completions
The kenari chat completions endpoint is compatible with OpenAI, so it can be used as a direct replacement for https://api.openai.com/v1. Point the base URL to https://kenari.id/v1 and use the kn-... API key. Tokens are still billed from the prepaid balance in Rupiah.
Endpoint
Section titled “Endpoint”POST /v1/chat/completions
Request
Section titled “Request”Two fields are required: model and messages.
The model field accepts a model id from GET /v1/models, a :free variant (for example step-3-7-flash:free), or a route name you created yourself (for example opus-hemat, see Routing).
Other supported fields:
| Field | Type | Description |
|---|---|---|
stream | boolean | Send the response as an SSE stream. See Streaming. |
max_tokens | integer | Output token limit. |
temperature | number | Sampling randomness level. |
top_p | number | Nucleus sampling. |
stop | string or array | Text sequences that stop generation. |
frequency_penalty | number | Token frequency penalty. |
presence_penalty | number | Token presence penalty. |
tools | array | Tool definitions. See Tools. |
tool_choice | string or object | How the model chooses a tool. |
response_format | object | Output format, for example JSON. |
reasoning_effort | string | For reasoning models. See Reasoning. |
plugins | array | Pre-dispatch plugins. Today only file-parser, for reading documents. See Read documents. |
Fields not listed in the table above are forwarded as-is to the upstream model.
messages
Section titled “messages”The messages field is an array of {role, content} objects. The role value is one of system, user, assistant, or tool. The content value can be a string, or an array of parts for multimodal input: text, image_url, and file. A file part carries a PDF or document image and needs the file-parser plugin, see Read documents.
{ "model": "step-3-7-flash", "messages": [ { "role": "system", "content": "Kamu asisten yang ringkas." }, { "role": "user", "content": "Halo!" } ]}Response
Section titled “Response”The response follows the OpenAI chat.completion shape: id, object, created, model, choices[], and usage. Each choices entry has index, message{role, content}, and finish_reason. The usage object contains prompt_tokens, completion_tokens, and total_tokens. The usage.prompt_tokens_details.cached_tokens field appears when the upstream reports a cache read.
{ "id": "chatcmpl-...", "object": "chat.completion", "created": 1717000000, "model": "step-3-7-flash", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "Halo! Ada yang bisa dibantu?" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 12, "completion_tokens": 9, "total_tokens": 21 }}Examples
Section titled “Examples”OpenAI SDK Python, set base_url to https://kenari.id/v1:
from openai import OpenAIclient = OpenAI(base_url="https://kenari.id/v1", api_key="kn-...")response = client.chat.completions.create(model="step-3-7-flash", messages=[{"role": "user", "content": "Halo!"}])print(response.choices[0].message.content)OpenAI SDK TypeScript, set baseURL to https://kenari.id/v1:
import OpenAI from "openai";const client = new OpenAI({ baseURL: "https://kenari.id/v1", apiKey: "kn-..." });const res = await client.chat.completions.create({ model: "step-3-7-flash", messages: [{ role: "user", content: "Halo!" }] });console.log(res.choices[0].message.content);curl:
curl https://kenari.id/v1/chat/completions -H "Authorization: Bearer kn-..." -H "Content-Type: application/json" -d '{"model":"step-3-7-flash","messages":[{"role":"user","content":"Halo!"}]}'Streaming
Section titled “Streaming”Set "stream": true in the request to receive the response as an SSE stream token by token. Event format details and stream reading steps are in Streaming.