POST /v1/chat/completions
The OpenAI Chat Completions wire. Base URL for OpenAI clients: https://sator-api.princep.org/v1.
Request#
curl https://sator-api.princep.org/v1/chat/completions \
-H "Authorization: Bearer $SATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [
{"role": "system", "content": "Be brief."},
{"role": "user", "content": "Say hi"}
],
"max_tokens": 64,
"stream": false
}'| Field | Notes |
|---|---|
model | Required. An id from Models. Unknown → 404 model_not_found. |
messages | Required. system, developer, user, assistant and tool roles. |
max_tokens, max_completion_tokens | Optional. Either caps output; a value above the model's max output is lowered to it. |
stream | true for server-sent events. See Streaming. |
stream_options.include_usage | Always treated as true: the final streamed chunk carries usage whether or not you asked. |
temperature, top_p, frequency_penalty, presence_penalty, seed, stop | Sampling, passed through. |
tools, tool_choice, parallel_tool_calls | See Tool calling. |
response_format | text, json_object or json_schema. See Tool calling. |
reasoning_effort | Passed through to models that take it. |
prompt_cache_key | Your own conversation key, up to 256 characters. See Prompt caching. |
user | Passed through. |
Content parts: text, and images as image_url with a base64 data URL — a remote https:// image URL is not fetched on this wire. Bodies over 5 MB are rejected 413.
Response#
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1787593841,
"model": "deepseek-v4-flash",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"message": {"role": "assistant", "content": "Hi! How can I help you today?", "tool_calls": []}
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 9,
"total_tokens": 21,
"prompt_tokens_details": {"cached_tokens": 0}
}
}usage.prompt_tokens_details.cached_tokens is how many input tokens were served from cache and billed at the cache-read rate. Some models also return reasoning_content on the assistant message.
Every response carries an x-request-id header. Quote it to support; it is the id your debit is recorded under.
Streaming#
With "stream": true the body is text/event-stream: data: lines carrying chat.completion.chunk objects, a final chunk with usage and an empty choices array, then data: [DONE].
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"deepseek-v4-flash","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"deepseek-v4-flash","choices":[{"index":0,"delta":{"content":"Hi! How can I help"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"deepseek-v4-flash","choices":[{"index":0,"delta":{"content":" you today?"},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"deepseek-v4-flash","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":9,"total_tokens":21}}
data: [DONE]Tool-call deltas are forwarded exactly as the model emits them. See Streaming for disconnects and billing.
Errors#
The OpenAI envelope, {"error": {"message", "type", "param", "code"}}. Every status and code is in Errors.