POST /v1/chat/completions
Основной метод шлюза. Совместим с OpenAI на уровне полей: библиотека openai работает с ним без правок, достаточно поменять base_url и ключ.
Минимальный запрос#
curl https://nirastudio.org/v1/chat/completions \
-H "Authorization: Bearer $NIRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.6",
"messages": [{ "role": "user", "content": "Привет" }]
}'Обязательных полей два: model и messages. Всё остальное имеет разумные значения по умолчанию — их задаёт сама модель, а не шлюз.
Поля запроса#
| Поле | Тип и смысл |
|---|---|
model | Строка. Идентификатор из каталога |
messages | Массив, от 1 до 400 сообщений. Роли: system, user, assistant, tool |
stream | Логическое. true — ответ приходит событиями SSE |
stream_options | Объект. include_usage: true добавляет в конец стрима кусок со счётчиком токенов |
temperature | Число 0…2. Выше — разнообразнее, ниже — предсказуемее |
top_p | Число 0…1. Обрезание по вероятности; вместе с temperature обычно не используют |
max_tokens | Целое 1…200 000. Предел длины ответа. Синоним max_completion_tokens — если пришли оба, действует max_tokens |
stop | Строка или массив до 8 строк. Генерация прервётся на любой из них |
tools | Массив до 128 инструментов. См. инструменты |
tool_choice | Как выбирать инструмент: auto, none, required или конкретное имя |
functions | Устаревшая форма tools. Принимается для старых клиентов, вместе с tools не нужна |
response_format | Объект с type: json_object или json_schema — просит модель отвечать разбираемым JSON |
reasoning | Объект: enabled и effort. Включает рассуждение у моделей, которые его умеют |
400, а не игнорируются молча: опечатка в имени поля иначе выглядела бы как «настройка не действует».Сообщения#
content — либо строка, либо массив частей. Массив нужен, когда во входе есть картинка:
{
"role": "user",
"content": [
{ "type": "text", "text": "Что на схеме?" },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBORw0…" } }
]
}system— общие правила поведения. Ставится первым сообщением.assistant— предыдущие ответы модели; вместе сtool_calls, если она вызывала инструменты.tool— результат вызова, с тем жеtool_call_id, что пришёл вtool_calls.
Подробности по картинкам — в отдельном разделе: не каждая модель их принимает.
Ответ целиком#
{
"id": "chatcmpl-…",
"object": "chat.completion",
"created": 1770000000,
"model": "anthropic/claude-sonnet-4.6",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Привет!" },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 8, "completion_tokens": 3, "total_tokens": 11 }
}finish_reason
| Значение | Почему генерация закончилась |
|---|---|
stop | Модель закончила мысль сама или наткнулась на stop-строку |
length | Кончился max_tokens. Ответ обрезан на полуслове — стоит повторить с бо́льшим пределом |
tool_calls | Модель хочет вызвать инструмент. Ответа для пользователя тут нет, см. инструменты |
Стрим#
С stream: true ответ приходит цепочкой кусков chat.completion.chunk: сначала кусок с ролью, затем дельты текста, затем кусок с finish_reason. Разбор событий и порядок — в разделе про стриминг.
data: {"choices":[{"index":0,"delta":{"role":"assistant"}}], …}
data: {"choices":[{"index":0,"delta":{"content":"При"}}], …}
data: {"choices":[{"index":0,"delta":{"content":"вет"}}], …}
data: {"choices":[{"index":0,"delta":{},"finish_reason":"stop"}], …}
data: [DONE]Ответ в JSON#
Когда результат нужен машине, а не человеку, попросите разбираемый JSON — так не придётся выковыривать объект из окружающего текста:
{
"model": "anthropic/claude-sonnet-4.6",
"messages": [{ "role": "user", "content": "Разбери адрес: Тверская 7, Москва" }],
"response_format": { "type": "json_object" }
}Рассуждение#
{
"model": "anthropic/claude-opus-5",
"messages": [{ "role": "user", "content": "Найди ошибку в этом доказательстве…" }],
"reasoning": { "enabled": true, "effort": "high" }
}effort — low, medium или high. Модели, которые рассуждать не умеют, поле просто игнорируют: 400 не будет.