API reference
Kymo exposes an OpenAI-compatible chat completions API. Any OpenAI-compatible SDK works by changing the base URL to /api/public/v1.
Quickstart
Create an API key on the API keys page, then call the endpoint:
curl https://kymo.volarishq.uk/api/public/v1/chat/completions \
-H "Authorization: Bearer $KYMO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kymo-large",
"messages": [
{ "role": "system", "content": "You are a concise assistant." },
{ "role": "user", "content": "What can you do?" }
],
"temperature": 0.7
}'Or with the OpenAI Python SDK:
from openai import OpenAI
client = OpenAI(
api_key=os.environ["KYMO_API_KEY"],
base_url="https://kymo.volarishq.uk/api/public/v1",
)
completion = client.chat.completions.create(
model="kymo-pro",
messages=[{"role": "user", "content": "Write a haiku about latency."}],
)
print(completion.choices[0].message.content)Authentication
Send your key as a bearer token: Authorization: Bearer kymo_…. Keys are stored only as SHA-256 hashes, so the full value is shown exactly once at creation. Revoked keys immediately return 401.
Chat completions
POST /api/public/v1/chat/completions
model— required, see Models.messages— required array of system/user/assistant messages.temperature,top_p,max_tokens,stop— optional sampling controls.stream— boolean, emits server-sent events.response_format—{ "type": "json_object" }for JSON mode.
GET /api/public/v1/models lists the available models in OpenAI format.
Streaming
Set stream: true to receive incremental deltas as SSE. The stream ends with data: [DONE].
const res = await fetch(BASE_URL + "/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KYMO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "kymo-large",
messages: [{ role: "user", content: "Count to five." }],
stream: true,
}),
});
// Server-sent events: data: {...}\n\n ... terminated by data: [DONE]
const reader = res.body!.getReader();JSON mode
JSON mode guarantees syntactically valid JSON. Describe the exact shape you want in a system message, and avoid combining it with streaming.
{
"model": "kymo-large",
"response_format": { "type": "json_object" },
"messages": [
{ "role": "system", "content": "Reply with JSON: { title, tags[] }" },
{ "role": "user", "content": "Summarise the article about GPUs." }
]
}Vision
Vision-capable models accept an array content block with image URLs or base64 data URLs. Up to 5 images per request, 20 MB each.
{
"model": "kymo-vision",
"messages": [{
"role": "user",
"content": [
{ "type": "text", "text": "What is in this image?" },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
]
}]
}Models
kymo-largeGeneral-purpose workhorse. Fast, strong at reasoning and long-form text.
kymo-proOur largest open-weight model for demanding reasoning and code tasks.
kymo-visionMultimodal: image understanding, OCR, captioning and visual Q&A.
kymo-agentAgentic system with built-in web search, page visits and code execution.
kymo-agent-miniSingle tool call per request, roughly 3x lower latency than Kymo Agent.
Rate limits & errors
Each API key is limited to 60 requests per rolling 60-second window. Exceeding it returns 429.
400— invalid body or unknown model.401— missing, invalid or revoked key.429— rate limit exceeded.502— upstream inference error.
Every request is recorded on your usage dashboard, including failures.