Chat completions
POST /v1/chat/completions is compatible with the OpenAI Chat Completions API. Any OpenAI SDK or OpenAI-compatible tool works after you set the base URL to https://jantaris.com/v1 and use a Jantaris key. The same endpoint serves every chat model in the catalog, not only OpenAI ones.
Models
| Model id | Vendor |
|---|---|
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.8-flash | |
deepseek-v4.1-flash | DeepSeek |
glm-5.3 | Zhipu |
kimi-k3 | Moonshot |
qwen3.8-max | Alibaba |
grok-4.7 | xAI |
Prices per 1M input and output tokens are listed in the model catalog and returned by GET /v1/models?category=chat (Models). For example Claude Sonnet 5 costs $3.24 / $16.20 per 1M tokens.
Request
POST https://jantaris.com/v1/chat/completions
Authorization: Bearer sk-jt-...
Content-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
model | string | yes | Model id from the table above |
messages | array | yes | Conversation in OpenAI format: {role, content} with roles system, user, assistant, tool |
stream | boolean | no | true returns Server-Sent Events. Default false |
max_tokens | integer | no | Upper limit for generated tokens |
temperature | number | no | Sampling temperature |
tools | array | no | Function definitions in OpenAI format |
tool_choice | string or object | no | auto, none, required or a specific function |
Basic call
curl https://jantaris.com/v1/chat/completions \
-H "Authorization: Bearer $JANTARIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-sol",
"messages": [
{"role": "system", "content": "You answer in one sentence."},
{"role": "user", "content": "What is a webhook?"}
]
}'import os
from openai import OpenAI
client = OpenAI(base_url="https://jantaris.com/v1", api_key=os.environ["JANTARIS_API_KEY"])
resp = client.chat.completions.create(
model="gpt-6-sol",
messages=[
{"role": "system", "content": "You answer in one sentence."},
{"role": "user", "content": "What is a webhook?"},
],
)
print(resp.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://jantaris.com/v1", apiKey: process.env.JANTARIS_API_KEY });
const resp = await client.chat.completions.create({
model: "gpt-6-sol",
messages: [
{ role: "system", content: "You answer in one sentence." },
{ role: "user", content: "What is a webhook?" },
],
});
console.log(resp.choices[0].message.content);Without an SDK, using plain requests:
import os, requests
r = requests.post(
"https://jantaris.com/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['JANTARIS_API_KEY']}"},
json={"model": "gemini-3.8-flash", "messages": [{"role": "user", "content": "Hi"}]},
timeout=120,
)
r.raise_for_status()
print(r.json()["choices"][0]["message"]["content"])Response
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1790500000,
"model": "gpt-6-sol",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "A webhook is an HTTP request a service sends to your URL when an event happens." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 24, "completion_tokens": 18, "total_tokens": 42 }
}usage is what you are billed for: input tokens at the model's input price, output tokens at its output price.
Streaming
Set stream: true to receive tokens as they are generated. The response is text/event-stream with data: lines in the OpenAI chunk format, ending with data: [DONE].
curl -N https://jantaris.com/v1/chat/completions \
-H "Authorization: Bearer $JANTARIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "claude-sonnet-5", "stream": true, "messages": [{"role": "user", "content": "Count to five."}]}'data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"1"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":", 2"}}]}
data: [DONE]stream = client.chat.completions.create(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "Count to five."}],
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: "Count to five." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Tool calls
Tools use the OpenAI function-calling format. The model returns tool_calls, you run the function and send the result back as a tool message.
import json
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Returns the shipping status of an order",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}]
messages = [{"role": "user", "content": "Where is order A-1042?"}]
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"} # your code here
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: "Returns the shipping status of an order",
parameters: { type: "object", properties: { order_id: { type: "string" } }, required: ["order_id"] },
},
}];
const messages = [{ role: "user", content: "Where is order A-1042?" }];
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" }; // your code here
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);
}Errors
This endpoint returns errors in the OpenAI format, so the OpenAI SDK raises its usual exceptions (AuthenticationError, RateLimitError and so on). The default rate limit is 600 requests per minute per key. See Errors.
Related
- Using the Anthropic SDK or Claude Code: Anthropic Messages
- Cursor, Cline, Continue: Claude Code and IDE tools









