Chat completions
This endpoint follows the OpenAI Chat Completions API, so the OpenAI SDKs and any tool built for that API can talk to it. Set the base URL to https://kadraris.com/v1, use your Kadraris key, and you can reach every chat model in the catalog here, including the ones that do not come from OpenAI.
Available chat models
| Model id | Made by |
|---|---|
claude-opus-5.5 | Anthropic |
claude-sonnet-5 | Anthropic |
claude-fable-5.1 | Anthropic |
gpt-6-sol | OpenAI |
gpt-6-luna | OpenAI |
gpt-6-astra | OpenAI |
gemini-3.6-flash | |
deepseek-v4-flash | DeepSeek |
glm-5.2 | Zhipu |
kimi-k3 | Moonshot |
Each model has a price for one million input tokens and one for a million output tokens. Find them in the model catalog or by calling GET /v1/models?category=chat (see Models). As an example, Claude Sonnet 5 is $3.24 / $16.20 per 1M tokens.
Request body
POST https://kadraris.com/v1/chat/completions
Authorization: Bearer sk-kd-...
Content-Type: application/json| Field | Type | Required | Meaning |
|---|---|---|---|
model | string | yes | One of the ids listed above |
messages | array | yes | The conversation as OpenAI-style {role, content} objects; roles are system, user, assistant and tool |
stream | boolean | no | Send true to get Server-Sent Events; false by default |
max_tokens | integer | no | Cap on how many tokens the model may produce |
temperature | number | no | Sampling temperature |
tools | array | no | Functions the model may call, OpenAI format |
tool_choice | string or object | no | auto, none, required, or one named function |
A first request
curl https://kadraris.com/v1/chat/completions \
-H "Authorization: Bearer $KADRARIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-sol",
"messages": [
{"role": "system", "content": "Keep every answer to one sentence."},
{"role": "user", "content": "What does an API gateway do?"}
]
}'import os
from openai import OpenAI
client = OpenAI(base_url="https://kadraris.com/v1", api_key=os.environ["KADRARIS_API_KEY"])
resp = client.chat.completions.create(
model="gpt-6-sol",
messages=[
{"role": "system", "content": "Keep every answer to one sentence."},
{"role": "user", "content": "What does an API gateway do?"},
],
)
print(resp.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://kadraris.com/v1",
apiKey: process.env.KADRARIS_API_KEY,
});
const resp = await client.chat.completions.create({
model: "gpt-6-sol",
messages: [
{ role: "system", content: "Keep every answer to one sentence." },
{ role: "user", content: "What does an API gateway do?" },
],
});
console.log(resp.choices[0].message.content);No SDK is needed if you prefer plain HTTP. With Python requests:
import os, requests
r = requests.post(
"https://kadraris.com/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['KADRARIS_API_KEY']}"},
json={"model": "gemini-3.6-flash", "messages": [{"role": "user", "content": "Hi"}]},
timeout=120,
)
r.raise_for_status()
print(r.json()["choices"][0]["message"]["content"])Response body
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1790500000,
"model": "gpt-6-sol",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "It routes incoming calls to the right backend service." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 24, "completion_tokens": 18, "total_tokens": 42 }
}The charge is based on usage. Prompt tokens are priced at the model's input rate and completion tokens at its output rate.
Streaming tokens
Pass stream: true and tokens arrive while the model is still writing. The response type is text/event-stream: a series of data: lines carrying OpenAI-format chunks, closed by data: [DONE].
curl -N https://kadraris.com/v1/chat/completions \
-H "Authorization: Bearer $KADRARIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "claude-sonnet-5", "stream": true, "messages": [{"role": "user", "content": "List three primary colors."}]}'data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Red"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":", blue"}}]}
data: [DONE]stream = client.chat.completions.create(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "List three primary colors."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)const stream = await client.chat.completions.create({
model: "claude-sonnet-5",
messages: [{ role: "user", content: "List three primary colors." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Function calling
Tool definitions use OpenAI's function-calling shape. The flow has three steps:
- The model replies with
tool_callsinstead of text. - Your code runs each requested function.
- You append the results as
toolmessages and call the endpoint again for the final answer.
import json
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up where an order is in shipping",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}]
messages = [{"role": "user", "content": "Has order B-2210 shipped yet?"}]
first = client.chat.completions.create(model="gpt-6-luna", messages=messages, tools=tools)
msg = first.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = {"order_id": args["order_id"], "status": "shipped"} # replace with a real lookup
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
final = client.chat.completions.create(model="gpt-6-luna", messages=messages, tools=tools)
print(final.choices[0].message.content)const tools = [{
type: "function",
function: {
name: "get_order_status",
description: "Look up where an order is in shipping",
parameters: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"],
},
},
}];
const messages = [{ role: "user", content: "Has order B-2210 shipped yet?" }];
const first = await client.chat.completions.create({ model: "gpt-6-luna", messages, tools });
const msg = first.choices[0].message;
if (msg.tool_calls) {
messages.push(msg);
for (const call of msg.tool_calls) {
const args = JSON.parse(call.function.arguments);
const result = { order_id: args.order_id, status: "shipped" }; // replace with a real lookup
messages.push({ role: "tool", tool_call_id: call.id, content: JSON.stringify(result) });
}
const final = await client.chat.completions.create({ model: "gpt-6-luna", messages, tools });
console.log(final.choices[0].message.content);
}When something fails
Error bodies here have the OpenAI shape, which means the OpenAI SDK throws the exceptions you already handle, such as AuthenticationError or RateLimitError. Each key can send 600 requests a minute by default. Full details in Errors.
See also
- Working with the Anthropic SDK or Claude Code: Anthropic Messages
- Setting up Cursor, Cline or Continue: Claude Code and IDE tools























