Chat completions

One-shot and conversational chat against any EU-hosted chat model.

POST /v1/chat/completions is the workhorse endpoint. It follows the OpenAI chat-completions spec — request body, response shape and streaming format are all interchangeable with the OpenAI SDK.

At a glance

EndpointPOST /v1/chat/completions
PricingPer 1M input/output tokens — varies per model
Default model in our examplesmistral/mistral-small-3.2
StreamingYes — see Streaming

One-shot completion

chat.ts
import { createCleverRouter } from '@cleverrouter/sdk';

const cr = createCleverRouter({
  apiKey: process.env.CLEVERROUTER_API_KEY!,
});

const res = await cr.chat({
  model: 'mistral/mistral-small-3.2',
  messages: [
    { role: 'system', content: 'Reply in one sentence.' },
    { role: 'user', content: 'Why pick an EU-hosted AI gateway?' },
  ],
  max_tokens: 200,
});

console.log(res.choices[0]?.message.content);
console.log(res.usage); // { prompt_tokens, completion_tokens, total_tokens }
chat.ts
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.CLEVERROUTER_API_KEY!,
  baseURL: 'https://api.cleverouter.eu/v1',
});

const res = await client.chat.completions.create({
  model: 'mistral/mistral-small-3.2',
  messages: [
    { role: 'system', content: 'Reply in one sentence.' },
    { role: 'user', content: 'Why pick an EU-hosted AI gateway?' },
  ],
});
chat.py
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["CLEVERROUTER_API_KEY"],
    base_url="https://api.cleverouter.eu/v1",
)

res = client.chat.completions.create(
    model="mistral/mistral-small-3.2",
    messages=[
        {"role": "system", "content": "Reply in one sentence."},
        {"role": "user", "content": "Why pick an EU-hosted AI gateway?"},
    ],
)
print(res.choices[0].message.content)
curl https://api.cleverouter.eu/v1/chat/completions \
  -H "Authorization: Bearer $CLEVERROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistral/mistral-small-3.2",
    "messages": [
      { "role": "system", "content": "Reply in one sentence." },
      { "role": "user", "content": "Why pick an EU-hosted AI gateway?" }
    ]
  }'

Multi-turn conversation

Carry the whole messages array on each call — the gateway is stateless, just like OpenAI.

multi-turn.ts
const messages = [
  { role: 'system', content: 'You are a Berlin-based travel guide.' },
  { role: 'user', content: 'Where should I have dinner tonight?' },
];

const first = await cr.chat({
  model: 'mistral/mistral-small-3.2',
  messages,
});
messages.push(first.choices[0]!.message);

messages.push({ role: 'user', content: 'Something vegetarian.' });
const second = await cr.chat({
  model: 'mistral/mistral-small-3.2',
  messages,
});

Request body parameters

Prop

Type

JSON mode

Force a JSON response from any chat model that supports it:

const res = await cr.chat({
  model: 'mistral/mistral-small-3.2',
  messages: [
    { role: 'system', content: 'Reply with valid JSON only.' },
    { role: 'user', content: 'List 3 EU cities and their countries.' },
  ],
  response_format: { type: 'json_object' },
});

const data = JSON.parse(res.choices[0]!.message.content!);

Response shape

interface ChatCompletion {
  id: string;
  object: 'chat.completion';
  created: number;
  model: string;
  choices: Array<{
    index: number;
    message: { role: 'assistant'; content: string | null; tool_calls?: ToolCall[] };
    finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter';
  }>;
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
    completion_tokens_details?: { reasoning_tokens?: number };
  };
}

The response also carries headers worth inspecting:

X-CleverRouter-Provider: scaleway
X-Request-Id: 0193…

Common errors

HTTPWhen this happens
400Empty messages, malformed model id, bad response_format
401Missing or revoked Bearer key
404Model id not in the registry
410Model deprecated — pick a successor
429RPM exceeded — see Rate limits

Full taxonomy: Errors.

Need to stream?

Set stream: true and consume the SSE chunks — full pattern in Streaming.