Chat completions
POST /v1/chat/completions takes a conversation and returns the assistant’s
next message. The request and response shapes are OpenAI’s; this page covers
what siema_ai does with each field.
Minimal request
Section titled “Minimal request”from openai import OpenAIimport os
client = OpenAI(base_url="https://api.siema-ai.pl/v1", api_key=os.environ["SIEMA_API_KEY"])
r = client.chat.completions.create( model="polish-pro", messages=[ {"role": "system", "content": "Jesteś asystentem działu obsługi klienta sklepu z elektroniką."}, {"role": "user", "content": "Klient pyta, czy może zwrócić otwarte słuchawki po 10 dniach. Odpowiedz uprzejmie."}, ], max_tokens=300, temperature=0.3,)print(r.choices[0].message.content)print(r.usage) # prompt_tokens, completion_tokens, total_tokensSet your HTTP client’s own timeout to 180 seconds or more — the gateway’s own budget for a cold start (see Streaming). A shorter client timeout can abandon the request before the model has answered; you’re still charged the estimated input tokens for it, and if your SDK retries on timeout (twice by default), that cost repeats on every retry.
Parameters
Section titled “Parameters”| Field | What siema_ai does |
|---|---|
model |
Required. An alias from GET /v1/models. An alias that doesn’t exist returns 404 model_not_found. An alias that exists but doesn’t have the chat capability (for example embed) returns 400 invalid_request with param: "model". |
messages |
Required, a non-empty array. Roles system, user, assistant, tool. content is a string, an array of content parts, or null — an assistant message that carries only tool_calls has null content. |
stream |
false returns one JSON object; true returns server-sent events. See Streaming. |
stream_options.include_usage |
When true, the final stream chunk carries usage. The gateway always fetches usage from the model server for billing; this flag only controls whether you see it. |
max_tokens, max_completion_tokens |
Either name works and both mean the same thing: an upper bound on generated tokens, an integer of at least 1 (anything else is 400 invalid_request). A value above the model’s max_output_tokens is clamped silently to that ceiling. Omit the field, or send JSON null, and the model’s ceiling is used. This null-is-absent handling is specific to these two fields: a null model or messages is 400 invalid_request, and every other field’s null is forwarded as sent. Whichever name you send, the value forwarded upstream is always max_tokens. |
n, best_of |
Forwarded unmodified, with no limit applied by siema_ai. The model server may return more than one choice; the output tokens of every choice returned are billed, not just the first. |
temperature, top_p, stop, user |
Forwarded to the model unchanged. |
| Anything else | Forwarded unchanged: tools, tool_choice, response_format, seed, logprobs, presence_penalty, frequency_penalty, and so on. If the model server rejects a field, you get its error back, typically as 400 invalid_request. |
finish_reason
Section titled “finish_reason”| Value | Meaning |
|---|---|
stop |
The model finished or hit one of your stop sequences. |
length |
Generation hit max_tokens. If you asked for more than max_output_tokens, this is the clamped ceiling, not your number. Ask for a shorter answer or continue the conversation. |
tool_calls |
The model wants to call a tool; see message.tool_calls. |
content_filter |
The model server stopped generation. Rare with open models. |
tools and tool_choice pass straight through to the model server unchanged.
Whether a given alias actually returns tool_calls in practice isn’t something
we promise or have verified for every alias — test tool calling with the
alias you plan to use before relying on it in production. If the model server
doesn’t support the fields you send, you get its error back as
400 invalid_request.
Images
Section titled “Images”Image content parts are forwarded to the model server unmodified and
unvalidated by the gateway. Only a model whose capabilities include
vision understands an image_url part — and no V1 alias has vision
today (check GET /v1/models before you build against this). Send images the
same way once a vision-capable alias is available:
r = client.chat.completions.create( model="<a future alias with vision in its capabilities>", messages=[{ "role": "user", "content": [ {"type": "text", "text": "Co jest na tym paragonie? Wypisz pozycje i sumę."}, {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,/9j/4AAQ..."}}, ], }],)Send an image part to an alias without vision and the model server that
receives it can’t understand the part; it rejects the request and the gateway
surfaces that as 400 invalid_request. Image bytes are forwarded to the
model server and, like all prompt content, are never stored.
Prompting in Polish
Section titled “Prompting in Polish”- A short system message in Polish (
Odpowiadaj po polsku.) is a simple way to keep the reply language consistent across all three chat aliases. - Bielik handles formal register well; say
formalnieorbezpośredniowhen it matters. - For structured output, ask for JSON and pass
response_format: {"type": "json_object"}; validate the result, as with any model.
Cost of a request
Section titled “Cost of a request”Cost in micro-PLN is ceil(prompt_tokens × input_price / 1 000 000) + ceil(completion_tokens × output_price / 1 000 000), each term rounded up
separately, at the price in force when the request started. For example, on
polish-pro’s current placeholder prices, 2 000 prompt tokens and 500
completion tokens cost 3 000 + 1 500 = 4 500 micro-PLN.
The usage object in the response is what you’re billed for when the model
server reports it. When it doesn’t — for instance a stream that breaks before
reaching a final usage chunk — siema_ai estimates the tokens instead and marks
the request estimated in the console; see Streaming.
See Billing for the full picture.