Chat completions
The main endpoint, field by field.
Endpoint
1POST https://api.sothe.net/v1/chat/completionsThe request and response follow OpenAI's Chat Completions schema, so an OpenAI SDK works unchanged.
Request fields
| Field | Notes |
|---|---|
model | Required. An id from the model list, or @preset/<slug>. |
messages | Required, non-empty. See below. |
stream | true switches to server-sent events. See Streaming. |
stream_options | { include_usage: true } appends a final chunk carrying token counts and cost. |
max_tokens | 1–1,000,000. max_completion_tokens is accepted as an alias. Defaults to 8,192, and is lowered automatically when your remaining balance cannot cover that many output tokens. |
temperature | 0–2. |
top_p | 0–1. |
stop | A string, or an array of up to four. |
tools, tool_choice | See Tool calling. |
n | Only 1. Any other value is rejected rather than quietly ignored. |
Messages
| Role | Notes |
|---|---|
system, developer | Instructions. Both are treated the same and lifted out of the conversation. |
user | A string, or an array of parts for media. |
assistant | Previous replies, including any tool_calls they made. |
tool | The result of a call. Must carry the tool_call_id it answers. |
Consecutive messages with the same role are merged, because some providers require strictly alternating turns. That is invisible to you, but it means two adjacent user messages arrive at the model as one.
Fields we ignore
These are accepted without error and change nothing. They are listed here so you do not discover it by debugging:
response_format, seed, frequency_penalty, presence_penalty, logprobs, logit_bias, user.
Passing response_format does not make the model return JSON. Until it is implemented, ask for JSON in the prompt and validate what comes back, or use a tool call — a forced function gives you a schema the model must fill in.
Response
1{2 "id": "gen-...",3 "object": "chat.completion",4 "created": 1789862588,5 "model": "anthropic/claude-haiku-4-5-20251001-v1:0",6 "choices": [{7 "index": 0,8 "message": { "role": "assistant", "content": "Hello!" },9 "finish_reason": "stop"10 }],11 "usage": { "prompt_tokens": 9, "completion_tokens": 3, "total_tokens": 12, "cost": 0.000041 }12}Two additions to the OpenAI shape: usage.cost is the price of the request in USD, and a message carries reasoning when the model produced any. finish_reason is one of stop, length, tool_calls or content_filter.
A non-streaming request that takes a long time receives spaces before its JSON body, to stop proxies closing an idle connection. Every JSON parser ignores them.