Skip to content

Chat completions

POST /v1/chat/completions parameters, headers, response and errors.

POST /v1/chat/completions

Returns a model's reply to a list of messages, as one JSON object or as server-sent events.

Parameters

NameTypeDescription
messages requiredarrayThe conversation, oldest first. Roles system, user, assistant, tool; text content only
modelstringA model id from GET /v1/models. Defaults to qwen3.8-27b
max_tokensintegerOutput token limit, reasoning tokens included. No default; the context length bounds the output
streambooleantrue returns server-sent events. Defaults to false
stream_options.include_usagebooleantrue adds a final chunk with usage to a stream. Defaults to false
toolsarrayFunctions the model may call: {"type": "function", "function": {"name", "description", "parameters"}}
tool_choicestring or objectauto, none, required or {"type": "function", "function": {"name": "..."}}. Defaults to auto with tools
response_formatobject{"type": "json_object"}, or {"type": "json_schema", "json_schema": {"name", "schema", "strict"}}
chat_template_kwargs.enable_thinkingbooleanfalse turns thinking off. Defaults to true
temperaturenumberSampling temperature, as in OpenAI
top_pnumberNucleus sampling, as in OpenAI
stopstring or arraySequences that end the output
seedintegerSeed for repeatable sampling
presence_penaltynumberAs in OpenAI
frequency_penaltynumberAs in OpenAI

Other OpenAI chat completions fields pass to the model unchanged. The request body is limited to 32 MB. tools, response_format and enable_thinking are confirmed on qwen3.8-27b, qwen3.8-27b-fast and qwen3.8-27b-uncensored.

Headers

NameDescription
AuthorizationRequired. Bearer $ALBASTOV_API_KEY, an Albastov API key with the scope llm
Content-Typeapplication/json
X-LLM-WaitSeconds to wait for a model that is not loaded, 0 to 1800. 0 returns 503 model_loading or 503 queued at once. Without the header, a streamed request waits up to 1800 s and a non-streamed request up to 80 s
X-Request-IdRequest: an id of 16 to 64 lowercase hex characters. Response: the same id, or a new one when the request sent none or an invalid one
Retry-AfterResponse, on 429 and 503: seconds to wait before sending the request again
Cache-ControlResponse: no-store, or no-cache on a stream

A non-streamed request without a response after about 100 s fails with 524. Stream long requests, and keep X-LLM-Wait below 90 on non-streamed requests.

Request

curl

curl https://api.albastov.com/v1/chat/completions \
  -H "Authorization: Bearer $ALBASTOV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.8-27b",
    "max_tokens": 50,
    "messages": [
      {"role": "system", "content": "Answer in one line."},
      {"role": "user", "content": "Say hello in five words."}
    ],
    "chat_template_kwargs": {"enable_thinking": false}
  }'

Python

import os
from openai import OpenAI

client = OpenAI(base_url="https://api.albastov.com/v1", api_key=os.environ["ALBASTOV_API_KEY"])
reply = client.chat.completions.create(
    model="qwen3.8-27b",
    max_tokens=50,
    messages=[
        {"role": "system", "content": "Answer in one line."},
        {"role": "user", "content": "Say hello in five words."},
    ],
    extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
print(reply.choices[0].message.content)

JavaScript

const res = await fetch("https://api.albastov.com/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ALBASTOV_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "qwen3.8-27b",
    max_tokens: 50,
    messages: [
      { role: "system", content: "Answer in one line." },
      { role: "user", content: "Say hello in five words." },
    ],
    chat_template_kwargs: { enable_thinking: false },
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const reply = await res.json();
console.log(reply.choices[0].message.content);

Response

200, Content-Type: application/json, an OpenAI chat.completion object.

Response
{
  "id": "chatcmpl-b50af0eb9c5d02d9",
  "object": "chat.completion",
  "created": 1793305215,
  "model": "qwen3.8-27b",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "Hello there, my friend.", "reasoning": null},
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 18,
    "completion_tokens": 7,
    "total_tokens": 25,
    "prompt_tokens_details": {"cached_tokens": 0},
    "completion_tokens_details": {"reasoning_tokens": 0}
  }
}
FieldValue
modelThe requested model id
choices[0].message.contentAnswer text
choices[0].message.reasoningReasoning text, or null with thinking off
choices[0].message.tool_callsTool calls: id, type, function.name, function.arguments (a JSON string)
choices[0].finish_reasonstop, length or tool_calls
usage.prompt_tokensPrompt tokens
usage.completion_tokensOutput tokens, reasoning included
usage.total_tokensPrompt plus output tokens
usage.prompt_tokens_details.cached_tokensPrompt tokens reused from an earlier request with the same prefix
usage.completion_tokens_details.reasoning_tokensReasoning tokens

Responses may carry further OpenAI extension fields, most with null values. Ignore unknown fields.

Streamed response

With "stream": true: 200, Content-Type: text/event-stream. Each event is one data: line with a chat.completion.chunk object, then a blank line.

EventField
First chunkchoices[0].delta.role
Reasoningchoices[0].delta.reasoning
Answerchoices[0].delta.content
Tool callschoices[0].delta.tool_calls, fragments joined per index
Last choice chunkchoices[0].finish_reason
Usage chunkusage, empty choices; only with stream_options.include_usage
Error{"error": {...}}, then data: [DONE] or the connection closes
Enddata: [DONE]
CommentA line starting with :, such as : loading qwen3.8-27b every 15 s while the model loads

In an engine_restarted error event, code is the number 502: read type.

Errors

Errors use the OpenAI format, {"error": {"message", "type", "code", ...}}, with Content-Type: application/json. Branch on code.

StatusCodeMeaning
400invalid_jsonThe body is not a JSON object
400bad_bodyThe body could not be read
400parallel_unsupportedThe model runs one request at a time per account, and the account has one running
400too_many_parallelThe account runs max_parallel requests on the model
401missing_api_keyNo Authorization header
401invalid_api_keyUnknown or revoked key
403insufficient_scopeThe key does not carry the scope llm
404model_not_foundmodel is not an installed model
413too_largeThe body is over 32 MB
429daily_limitThe key's daily calls are used up; resets at 00:00 UTC
429rate_limitedThe key's calls per minute or per day are used up
429daily_tokensThe member's tokens for the UTC day are used up; resets at 00:00 UTC
429too_many_streamsThe member has 64 requests open
500internalServer error
502engine_restartedThe model stalled and restarted; the request ended
502llm-unavailableThe model failed to start
502edge_errorNo valid answer from the model service
503model_loadingThe model is loading
503queuedThe model load waits in the queue behind image or music jobs
503gpu-busyImage or music jobs held the queue for 900 s
503insufficient_memoryThe model cannot load now; retry after Retry-After
503device_offlineThe language model service is offline
503device_busy96 requests are open across all callers

A request the model rejects, such as a prompt over the context length, returns 400 with the model's own error type; code equals type.

503 model_loading, Retry-After: 150
{
  "error": {
    "message": "Loading qwen3.8-27b; retry in 150 s",
    "type": "model_loading",
    "code": "model_loading",
    "model": "qwen3.8-27b",
    "state": "starting",
    "retry_after_s": 150
  }
}
503 queued, Retry-After: 30
{
  "error": {
    "message": "Waiting for the GPU (1 ahead); retry in 30 s",
    "type": "queued",
    "code": "queued",
    "model": "qwen3.8-27b",
    "position": 1,
    "retry_after_s": 30,
    "reason": "waiting for the GPU: a media job is running"
  }
}
CodeExtra fields
invalid_jsonreason
model_not_foundmodel, available (installed model ids)
daily_limit, daily_tokenslimit, used
too_many_streamslimit
parallel_unsupported, too_many_parallelmax_parallel
engine_restartedmodel, reason
llm-unavailable, gpu-busyreason
model_loadingmodel, state, retry_after_s
queuedmodel, position (requests ahead), retry_after_s, reason
insufficient_memorymodel, reason

retry_after_s equals Retry-After. reason is readable text and varies. 429 and 503 responses carry Retry-After; retry model_loading, queued, gpu-busy and device_busy after Retry-After seconds.