PL Log inOpen Studio
Preview version. Model catalog, prices, calculator and docs are live. Generation goes live at launch.

Chat completions

Docs: every page

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 idMade by
claude-opus-5.5Anthropic
claude-sonnet-5Anthropic
claude-fable-5.1Anthropic
gpt-6-solOpenAI
gpt-6-lunaOpenAI
gpt-6-astraOpenAI
gemini-3.6-flashGoogle
deepseek-v4-flashDeepSeek
glm-5.2Zhipu
kimi-k3Moonshot

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

http
POST https://kadraris.com/v1/chat/completions
Authorization: Bearer sk-kd-...
Content-Type: application/json
FieldTypeRequiredMeaning
modelstringyesOne of the ids listed above
messagesarrayyesThe conversation as OpenAI-style {role, content} objects; roles are system, user, assistant and tool
streambooleannoSend true to get Server-Sent Events; false by default
max_tokensintegernoCap on how many tokens the model may produce
temperaturenumbernoSampling temperature
toolsarraynoFunctions the model may call, OpenAI format
tool_choicestring or objectnoauto, none, required, or one named function

A first request

bash
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?"}
    ]
  }'
python
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)
javascript
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:

python
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

json
{
  "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].

bash
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."}]}'
text
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]
python
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)
javascript
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:

  1. The model replies with tool_calls instead of text.
  2. Your code runs each requested function.
  3. You append the results as tool messages and call the endpoint again for the final answer.
python
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)
javascript
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