Чат
POST /v1/chat/completions
Создаёт чат-ответ текстовой модели. Запрос и ответ совместимы с OpenAI; вызов синхронный — ответ приходит в теле (или стримом, см. ниже). Юниты резервируются под оценку промпта плюс min(max_tokens, default_max_tokens) выходных токенов и по завершении списываются по фактическому расходу; если токены не были сгенерированы, ничего не списывается.
Заголовки
| Заголовок | Обязателен | Описание |
|---|---|---|
| Authorization | да | Bearer <API-ключ> |
| Content-Type | да | application/json |
| Idempotency-Key | нет | Idempotency-Key здесь необязателен. Повторное использование ключа возвращает 409 idempotency_key_reused. |
Тело
| Поле | Тип | Описание |
|---|---|---|
| model | string | Обязательно. Идентификатор текстовой модели из GET /v1/models, например "qwen3.8-max". |
| messages | array | Обязательно. {role: "system" | "user" | "assistant", content: string | parts[]}. Части контента (text, image_url) как в OpenAI API; image_url — только у моделей с vision: true. |
| max_tokens | integer | Потолок ответа. ≤ max_output_tokens модели; по умолчанию default_max_tokens. Токены рассуждения входят в него. |
| temperature | number | 0–2. По умолчанию — из default_params модели. |
| top_p | number | 0–1. |
| stop | string[] | До 4 стоп-последовательностей. |
| stream | boolean | По умолчанию false. true → text/event-stream, см. «Стриминг». |
| enable_thinking | boolean | Расширение. Рассуждение перед ответом, возвращается как reasoning_content. Только у моделей с thinking: true. |
| web_search | boolean | Расширение. Разрешает модели обращаться к интернету. Только у моделей с web_search: true. |
| reasoning_effort | string | none / minimal выключают рассуждение, low … xhigh включают. Только у моделей с thinking: true. |
| tools | array | Описания функций в формате OpenAI. Только у моделей с tools: true; см. Вызов инструментов. |
| tool_choice | string | object | auto · none · required · {type: "function", function: {name}}. |
| response_format | object | {type: "json_object"} или {type: "json_schema", json_schema: {name, schema}}; см. Структурированный вывод. |
Не поддерживается — отклоняется с 400 unsupported_parameter, а не игнорируется молча: n > 1, functions (legacy), logprobs.
curl -s -X POST https://api.genmux.tech/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.8-max","messages":[{"role":"user","content":"Explain idempotency keys in two sentences."}],"max_tokens":200}'Ответ 200 OK
{
"id": "0d8b6a3e-2f1c-4a5b-9c1d-7e2f3a4b5c6d",
"object": "chat.completion",
"created": 1756411279,
"model": "qwen3.8-max",
"choices": [
{"index": 0, "message": {"role": "assistant", "content": "An idempotency key is …"}, "finish_reason": "stop"}
],
"usage": {"prompt_tokens": 31, "completion_tokens": 58, "total_tokens": 89, "cost": 0.004, "cost_source": "vendor"}
}usage.cost — списанные юниты (дробное число, до 3 знаков); cost_source равен "vendor", если число токенов сообщил провайдер, и "estimated", если оно посчитано локально.
Ограничения
| Поле | Ограничение |
|---|---|
| max_tokens | ≤ max_output_tokens модели; по умолчанию default_max_tokens. Промпт, не оставляющий места для ответа, — 400 context_length_exceeded. |
| stop | До 4 строк. |
| temperature | 0–2. |
| messages | Любое число сообщений system, user и assistant в пределах окна контекста. Части image_url — только у моделей с vision: true. |
Стриминг
С "stream": true ответ приходит как text/event-stream. Каждая строка data: несёт один chat.completion.chunk; у последнего чанка пустой массив choices и блок usage (со списанными юнитами), а завершает стрим data: [DONE].
curl -sN -X POST https://api.genmux.tech/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.8-max","messages":[{"role":"user","content":"Explain idempotency keys in two sentences."}],"stream":true}'data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[{"index":0,"delta":{"role":"assistant","content":"An"},"finish_reason":null}]}
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[{"index":0,"delta":{"content":" idempotency"},"finish_reason":null}]}
…
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[],"usage":{"prompt_tokens":31,"completion_tokens":58,"total_tokens":89,"cost":0.004,"cost_source":"estimated"}}
data: [DONE]Если провайдер упал посреди стрима, вместо чанка usage приходит кадр с ошибкой, и стрим всё равно завершается [DONE]; резерв списывается по фактически сгенерированному, итоговую стоимость показывает GET /v1/generations/{id}.
data: {"error": {"code": "upstream_error", "message": "the model provider closed the connection"}}
data: [DONE]Закрытие соединения останавливает генерацию. Оплачиваются токены, сгенерированные до обрыва, и ничего больше.
OpenAI SDK
Эндпоинт говорит на диалекте OpenAI chat completions, поэтому официальные SDK работают без изменений: укажите base_url https://api.genmux.tech/v1 и передайте ключ как api_key. Идентификаторы моделей — наши (см. GET /v1/models), а не вендора.
curl -s -X POST https://api.genmux.tech/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.8-max","messages":[{"role":"user","content":"Explain idempotency keys in two sentences."}],"max_tokens":200}'import os
from openai import OpenAI
client = OpenAI(base_url="https://api.genmux.tech/v1", api_key=os.environ["API_KEY"])
completion = client.chat.completions.create(
model="qwen3.8-max",
messages=[{"role": "user", "content": "Explain idempotency keys in two sentences."}],
max_tokens=200,
)
print(completion.choices[0].message.content)
print(completion.usage.model_extra["cost"], "credits")
stream = client.chat.completions.create(model="qwen3.8-max", messages=[{"role": "user", "content": "Hi"}], stream=True)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
if chunk.usage:
print("\n", chunk.usage.total_tokens, "tokens,", chunk.usage.model_extra["cost"], "credits")import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.genmux.tech/v1", apiKey: process.env.API_KEY });
const completion = await client.chat.completions.create({
model: "qwen3.8-max",
messages: [{ role: "user", content: "Explain idempotency keys in two sentences." }],
max_tokens: 200,
});
console.log(completion.choices[0].message.content, completion.usage.cost);
const stream = await client.chat.completions.create({ model: "qwen3.8-max", messages: [{ role: "user", content: "Hi" }], stream: true });
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
if (chunk.usage) console.log(`\n${chunk.usage.total_tokens} tokens, ${chunk.usage.cost} credits`);
}Поддерживается: model, messages (system/user/assistant; части image_url у моделей со зрением), max_tokens, temperature, top_p, stop, stream, а также расширения enable_thinking и web_search как дополнительные поля тела.
Также поддерживаются: tools / tool_choice у моделей с tools: true (см. «Вызов инструментов»), response_format json_object / json_schema (см. «Структурированный вывод»), reasoning_effort. Отклоняются с 400 unsupported_parameter: n > 1, устаревшее поле functions, logprobs. Принимаются и игнорируются: stream_options, parallel_tool_calls, seed, user, metadata, store, logit_bias и name у сообщений.
Читайте usage из ответа (синхронно) или из последнего чанка (стрим): cost — списанные юниты.
Вызов инструментов
Вызов функций в формате OpenAI у моделей, у которых в каталоге указано tools: true. Передайте tools + tool_choice (auto · none · required · {type: "function", function: {name}}); ответ приходит с message.tool_calls и finish_reason tool_calls; результаты возвращайте сообщениями role: tool с соответствующим tool_call_id. Вызов функций эмулируется на стороне API — инструменты подставляются в системный промпт, а ответ разбирается обратно, — поэтому формат на проводе в точности как у OpenAI, хотя модели нативного поля tools не видят.
Модели с tools: true сейчас: doubao-seed-2-pro, doubao-seed-2-code, kimi-k3, claude-opus-5-5, claude-fable-5-1, gpt-6-astra, gpt-5.6-terra, qwen3.8-max. Запрос с tools к любой другой модели — 400 tools_unsupported.
from openai import OpenAI
client = OpenAI(base_url="https://api.genmux.tech/v1", api_key="nb_live_...")
tools = [{"type": "function", "function": {"name": "get_weather", "description": "Weather by city",
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}}}]
r = client.chat.completions.create(model="qwen3.8-max",
messages=[{"role": "user", "content": "Weather in Paris?"}], tools=tools)
call = r.choices[0].message.tool_calls[0] # call.function.name == "get_weather"
# run your function, then send the result back:
r2 = client.chat.completions.create(model="qwen3.8-max", tools=tools, messages=[
{"role": "user", "content": "Weather in Paris?"},
r.choices[0].message,
{"role": "tool", "tool_call_id": call.id, "content": "18°C, cloudy"},
])
print(r2.choices[0].message.content){
"id": "0d8b6a3e-…",
"object": "chat.completion",
"model": "qwen3.8-max",
"choices": [
{"index": 0, "finish_reason": "tool_calls", "message": {"role": "assistant", "content": null,
"tool_calls": [{"id": "call_1", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\": \"Paris\"}"}}]}}
],
"usage": {"prompt_tokens": 96, "completion_tokens": 21, "total_tokens": 117, "cost": 0.003, "cost_source": "vendor"}
}При stream: true вызов приходит чанками delta.tool_calls — сначала index, id и имя, затем аргументы фрагментами, — потом чанк с finish_reason tool_calls и обычный чанк usage.
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"id":"call_1","type":"function","function":{"name":"get_weather","arguments":""}}]},"finish_reason":null}]}
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"city\": \"Paris\"}"}}]},"finish_reason":null}]}
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]}
data: {"id":"0d8b6a3e-…","object":"chat.completion.chunk","model":"qwen3.8-max","choices":[],"usage":{"prompt_tokens":96,"completion_tokens":21,"total_tokens":117,"cost":0.003,"cost_source":"estimated"}}
data: [DONE]Ограничения
| Поле | Ограничение |
|---|---|
| tools | До 128 описаний, суммарно до 64 КиБ. Каждое описание стоит входных токенов: около 40 на инструмент плюс его JSON-схема. |
| tool_choice | auto (по умолчанию), none, required или имя функции. required и имя функции — инструкции, которым модель обычно следует; небольшие модели иногда отвечают текстом. |
| параллельные вызовы | Модели обычно делают один вызов за ход; parallel_tool_calls принимается и игнорируется. Агенты работают циклом, поэтому многошаговые задачи доходят до конца. |
| strict | Принимается и игнорируется — ограниченного декодирования у провайдера нет. |
| response_format | Не сочетается с tools в одном запросе. |
| max_tokens | Значения выше max_output_tokens обрезаются, а не отклоняются. Бюджет ответа по умолчанию у моделей с инструментами — 8192 токена. |
Структурированный вывод
Передайте response_format с {"type": "json_object"} или {"type": "json_schema", "json_schema": {"name", "schema"}} ({name, schema}, JSON Schema 2020-12) — модель получит инструкцию отвечать только JSON. Непотоковые ответы проверяются: при неудаче API один раз повторяет запрос, передав модели текст ошибки; вторая неудача — 502 json_invalid, и оплачиваются обе попытки. Потоковые ответы проходят без проверки. response_format и tools не сочетаются.
curl -s -X POST https://api.genmux.tech/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.8-max",
"messages":[{"role":"user","content":"Extract the city and the date: meet me in Paris on 3 March"}],
"response_format":{"type":"json_schema","json_schema":{"name":"event",
"schema":{"type":"object","properties":{"city":{"type":"string"},"date":{"type":"string"}},"required":["city","date"],"additionalProperties":false}}}}'{"id": "…", "object": "chat.completion", "model": "qwen3.8-max", "choices": [{"index": 0, "message": {"role": "assistant", "content": "{\"city\": \"Paris\", \"date\": \"2026-03-03\"}"}, "finish_reason": "stop"}], "usage": {…}}