
## Создать чат-комплишен

> **Ответ приходит в сыром OpenAI-формате.**
>
> Обёртки `{success, data}`, которая используется в остальных эндпоинтах Вайбкод — `/v1/deals`, `/v1/tasks` и других, — здесь нет.
>
> Так сделано для совместимости с OpenAI SDK. Если у вас единый клиент с проверкой `if (!response.success)`, добавьте для AI Router исключение.

`POST /v1/chat/completions`

Генерирует ответ AI-модели на массив сообщений. Формат запроса и ответа совместим с `POST /v1/chat/completions` из OpenAI API.

Возможности эндпоинта вынесены на отдельные страницы: [потоковая передача](./streaming.md), [гарантированный JSON-ответ](./json.md), [вызов функций](./tools.md), [анализ изображений](./vision.md) и [лимиты запросов](./rate-limits.md).

## Поля запроса (body)

| Поле | Тип | Обяз. | По умолч. | Описание |
|------|-----|:-----:|-----------|----------|
| `model` | string | нет | `auto` | ID модели или алиас. См. секцию «Алиасы» ниже. Если поле не передано или равно `auto` — запрос выполняется на модели портала по умолчанию. Список доступных моделей — [`GET /v1/models`](/docs/ai/models/list) |
| `messages` | array | да | — | Массив сообщений диалога. Минимум 1, максимум 256 |
| `messages[].role` | string | да | — | Роль: `system`, `user`, `assistant`, `tool` |
| `messages[].content` | string \| array \| null | да | — | Текст сообщения. Максимум 500 000 символов в одном сообщении или 64 элемента в массиве `content`. Для запросов с [изображениями](./vision.md) — массив с `type: "text"` и `type: "image_url"`. У `assistant` с `tool_calls` может быть `null` |
| `messages[].name` | string | нет | — | Имя отправителя (мультиагентные сценарии) |
| `messages[].tool_calls` | array | нет | — | Вызовы функций от ассистента — присутствуют в ответе модели при `finish_reason: "tool_calls"` |
| `messages[].tool_call_id` | string | нет | — | ID вызова функции — обязателен в сообщении с `role: "tool"` |
| `temperature` | number | нет | по модели | Температура генерации, диапазон `0..2`. Меньше — точнее и детерминированнее, больше — креативнее |
| `max_tokens` | number | нет | по модели | Максимум токенов в ответе |
| `top_p` | number | нет | — | Nucleus sampling, диапазон `0..1` |
| `stop` | string \| array | нет | — | Стоп-последовательности (до 4 штук, каждая до 64 символов) |
| `stream` | boolean | нет | `false` | Если `true` — ответ приходит [потоком](./streaming.md) `Server-Sent Events` |
| `response_format` | object | нет | — | Управление [форматом ответа](./json.md): `{"type": "text"}` — значение по умолчанию, `{"type": "json_object"}` — корректный JSON, `{"type": "json_schema", "json_schema": {...}}` — строгая JSON Schema, требует поддержки моделью |
| `tools` | array | нет | — | Определения [функций](./tools.md), которые модель может вызвать |
| `tool_choice` | string \| object | нет | — | `auto` (модель решает сама), `none` (запретить вызовы) или `{"type": "function", "function": {"name": "..."}}` (форсировать конкретную) |

## Алиасы моделей

Поле `model` принимает три значения, которые разрешаются в модель портала по умолчанию — сейчас это `bitrix/bitrixgpt-5.5`: `auto`, `bitrix/free` или пустая строка.

Модели `bitrix/bitrixgpt-5` и `bitrix/bitrixgpt-5-vl` помечены как устаревшие и работают до 31 июля 2026 года. После этой даты запросы к ним прозрачно перенаправляются на `bitrix/bitrixgpt-5.5` с заголовком `X-Model-Replacement` — подробнее в [жизненном цикле моделей](/docs/ai/models/lifecycle).

Кроме того, частичный `modelId` сопоставляется с каталогом по подстроке: если передан `gpt-4o-mini`, будет найдена доступная вашему ключу модель, в идентификаторе которой эта подстрока встречается.

## Примеры

### curl — личный ключ

```bash
curl -X POST https://vibecode.bitrix24.tech/v1/chat/completions \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bitrix/bitrixgpt-5.5",
    "messages": [
      {"role": "system", "content": "Ты эксперт по продажам. Классифицируй лидов по качеству."},
      {"role": "user", "content": "ООО Вектор, 50 пользователей, бюджет 500 тысяч в месяц."}
    ],
    "temperature": 0.3,
    "max_tokens": 300
  }'
```

### curl — OAuth-приложение

```bash
curl -X POST https://vibecode.bitrix24.tech/v1/chat/completions \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bitrix/bitrixgpt-5.5",
    "messages": [
      {"role": "system", "content": "Ты эксперт по продажам. Классифицируй лидов по качеству."},
      {"role": "user", "content": "ООО Вектор, 50 пользователей, бюджет 500 тысяч в месяц."}
    ],
    "temperature": 0.3,
    "max_tokens": 300
  }'
```

### JavaScript — личный ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/chat/completions', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'bitrix/bitrixgpt-5.5',
    messages: [
      { role: 'system', content: 'Ты эксперт по продажам. Классифицируй лидов по качеству.' },
      { role: 'user', content: 'ООО Вектор, 50 пользователей, бюджет 500 тысяч в месяц.' },
    ],
    temperature: 0.3,
    max_tokens: 300,
  }),
})

const data = await res.json()
console.log(data.choices[0].message.content)
console.log('Токены:', data.usage.total_tokens)
```

### JavaScript — OAuth-приложение

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/chat/completions', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'bitrix/bitrixgpt-5.5',
    messages: [
      { role: 'system', content: 'Ты эксперт по продажам. Классифицируй лидов по качеству.' },
      { role: 'user', content: 'ООО Вектор, 50 пользователей, бюджет 500 тысяч в месяц.' },
    ],
    temperature: 0.3,
    max_tokens: 300,
  }),
})

const data = await res.json()
console.log(data.choices[0].message.content)
```

## Поля ответа

| Поле | Тип | Описание |
|------|-----|----------|
| `id` | string | Уникальный ID комплишена для отслеживания |
| `object` | string | Всегда `chat.completion` для синхронного ответа |
| `created` | number | Unix-timestamp создания комплишена |
| `model` | string | Фактически использованная модель (может отличаться от `model` запроса при автоматическом переключении на резервную модель или DISABLED-перенаправлении) |
| `choices` | array | Варианты ответа модели. Без параметра `n` в массиве один элемент |
| `choices[].index` | number | Порядковый номер варианта |
| `choices[].finish_reason` | string | Причина завершения: `stop`, `length`, `tool_calls`, `content_filter` |
| `choices[].message` | object | Сгенерированное сообщение |
| `choices[].message.role` | string | Всегда `assistant` |
| `choices[].message.content` | string \| null | Текст ответа. `null` при `finish_reason: "tool_calls"` — содержимое в `tool_calls` |
| `choices[].message.tool_calls` | array | Список вызовов функций (если модель решила их вызвать) |
| `warnings` | array | Предупреждения о том, что платформа изменила в запросе или что стоит учесть в ответе. У каждого элемента есть минимум `code` и `message`, у отдельных предупреждений — дополнительные поля. Известные коды: `MAX_TOKENS_RAISED`, `COWORK_QUOTA_FALLBACK` (несёт также `tier`, `nextTier`, `resetAt`), `THINKING_TRUNCATED`. Поле отсутствует, когда предупреждений нет |
| `usage.prompt_tokens` | number | Токены входа |
| `usage.completion_tokens` | number | Токены ответа |
| `usage.total_tokens` | number | Сумма токенов в запросе и ответе |

## Пример ответа

```json
{
  "id": "chatcmpl-a1a73c6eb3f180fd",
  "object": "chat.completion",
  "created": 1777289339,
  "model": "bitrix/bitrixgpt-5.5",
  "choices": [
    {
      "index": 0,
      "finish_reason": "stop",
      "message": {
        "role": "assistant",
        "content": "Качество: ВЫСОКОЕ\n\nОбоснование:\n- Юридическое лицо (ООО) — B2B-клиент\n- Бюджет 500 тысяч в месяц — выше среднего\n- Конкретный объём (50 пользователей) — осознанная потребность\n\nРекомендация: назначить звонок в течение 24 часов."
      }
    }
  ],
  "usage": {
    "prompt_tokens": 42,
    "completion_tokens": 85,
    "total_tokens": 127
  }
}
```

## Пример ответа при ошибке

`404 ai_model_not_found` — модель не найдена или у ключа нет доступа к ней:

```json
{
  "error": {
    "message": "Model \"anthropic/claude-imaginary-x\" not found or disabled.",
    "type": "invalid_request_error",
    "code": "ai_model_not_found"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `invalid_request` | Пустой массив `messages`, неверная роль, нарушение схемы |
| 400 | `invalid_image_payload` | Некорректный `image_url` — сообщение содержит номер элемента `content` и причину. См. [анализ изображений](./vision.md) |
| 400 | `no_default_model` | У портала нет ни одной доступной для вызова модели |
| 402 | `ai_credentials_not_configured` | Для модели нет учётных данных провайдера — подключите [BYOK](/docs/ai/credentials/create) |
| 402 | `insufficient_balance` | Недостаточно средств для платной модели |
| 402 | `ai_quota_exhausted` | Месячная [AI-квота портала](/docs/ai/consumption/quota) исчерпана. Поле `reason` уточняет причину |
| 402 | `cowork_quota_exhausted` | Исчерпано одно из окон квоты подписки Cowork/Code. Тело несёт `window` (`5h`/`week`/`month`), `resetAt` и `nextTier`, заголовок `Retry-After` — число секунд до сброса окна |
| 403 | `scope_missing` | API-ключу не хватает скоупа `vibe:ai` |
| 404 | `ai_model_not_found` | Модель не найдена или отключена |
| 422 | `structured_output_truncated` | Запрос с `response_format` не дал полного JSON: генерация оборвана по `finish_reason: "length"` либо поле `content` пустое при любой причине завершения и без `tool_calls`. В режиме `json_object` есть исключение — готовый JSON, попавший в служебный канал `reasoning_content`, восстанавливается, и ответ остаётся `200`. Подробнее — [гарантированный JSON-ответ](./json.md) |
| 429 | `rate_limit_exceeded` | Превышен [лимит запросов](./rate-limits.md). Заголовок `X-RateLimit-Scope` указывает уровень — `per-key` или `per-user` |
| 429 | `ai_congested` | Пул AI-кластера перегружен. Запрос не выполнялся, списания нет, повторите его по заголовку `Retry-After`. Ответ несёт заголовок `X-AI-Admission: shed`, а не `X-RateLimit-Scope` |
| 429 | `ai_pacing_limited` | Превышено суточное или недельное окно равномерного расходования квоты. Это не исчерпание квоты — повторите запрос по заголовку `Retry-After`. Подробнее — [«Равномерное расходование»](/docs/ai/consumption/quota#равномерное-расходование-pacing) |
| 429 | `ai_provider_cooldown` | Кластер моделей временно недоступен, и платформа держит паузу, чтобы повторы его не добивали. Запрос не выполнялся, списания нет — повторите его через число секунд из `Retry-After`. Заголовков `X-RateLimit-Scope` и `X-AI-Admission` у этого ответа нет |
| 400 | `ai_provider_rejected` | Модель отклонила сам запрос (например неподдерживаемый параметр). Повторять его без изменений бесполезно. Возвращается, когда провайдер ответил `400` или `422` |
| 502 | `ai_provider_unavailable` | Внешний провайдер вернул ошибку (`401`/`403`/`5xx`) или недоступен |
| 503 | `model_unavailable` | Модель отключена, и преемник для неё не назначен. См. [жизненный цикл моделей](/docs/ai/models/lifecycle) |
| 503 | `pool_exhausted` | Платформа временно перегружена. Повторите запрос через число секунд из `Retry-After` — это 3-7 секунд со случайным разбросом |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Автоматическое переключение на резервную модель при сбое провайдера.** Если у платной модели произошла ошибка `5xx` или таймаут, синхронный запрос повторяется с моделью по умолчанию. В ответе появляется заголовок `X-Model-Fallback: <исходный modelId>`. В потоковом режиме такого переключения нет — клиент получает ошибку в последнем событии перед `data: [DONE]`.

**Исчерпанная квота Cowork/Code: ответ объявляет лимит, а не выполняет запрос.** Это отдельное состояние, не имеющее отношения к `X-Model-Fallback` выше: тот заголовок отмечает подмену модели, здесь же квота подписки исчерпана. Когда окно квоты исчерпано, а на платформе настроена резервная модель, запрос отвечает кодом `200`, но работа по нему не делается: поля `tools`, `tool_choice` и `response_format` снимаются, системные сообщения запроса не действуют, и модель сообщает, что лимит достигнут и когда он сбросится. Признаки состояния — заголовок `X-Cowork-Fallback: true` и предупреждение `COWORK_QUOTA_FALLBACK` в массиве `warnings`. В потоковом режиме предупреждения в теле нет, состояние видно по заголовку. Списания за такой ответ нет, квота не расходуется. Не ждите здесь `tool_calls` и JSON по схеме: даже с `response_format` в запросе придёт обычный текст. Если резервная модель не настроена — или настроенная сама не ответила, — приходит `402 cowork_quota_exhausted`. По коду ответа эти два случая не различаются, поэтому обрабатывайте `402` на этом эндпоинте всегда.

**Месячная AI-квота портала.** На порталах с включённым контролем квоты запрос может вернуть `402 ai_quota_exhausted`. Поле `reason` различает три случая: `breaker` — сработал часовой предохранитель расходов сверх квоты, `wallet_empty` — квота исчерпана и на балансе портала нет средств, `wallet_off` — расход сверх квоты для портала недоступен. Поле `resetAt` содержит момент, когда запросы снова начнут проходить, для `wallet_off` оно может отсутствовать. В ветке `wallet_empty` ответ может дополнительно нести строку `hint` с подсказкой и ссылку `topupUrl` на пополнение баланса — оба поля появляются, когда на платформе включены принудительный контроль квоты и подсказка о пополнении, поэтому читайте их как необязательные. Поле `hint` в этом ответе — строка. Пока расход укладывается в квоту, поведение эндпоинта не меняется. Сверх квоты, если такой расход для портала разрешён, запросы списываются с денежного баланса портала по базовой цене модели из каталога.

**Бюджет обработки синхронного запроса — около 850 секунд.** По исчерпании бюджета приходит `503 ai_provider_timeout`. Заголовка `Retry-After` в этом ответе нет намеренно: повтор того же запроса упрётся в тот же бюджет. Сократите объём запроса или перейдите на [потоковую передачу](./streaming.md) — там действует тайм-аут простоя между событиями, а не общий бюджет на весь вызов.

**Лимит размера тела запроса — 30 MiB.** Этого хватает, чтобы передать одно изображение размером до 20 MiB: после кодирования base64 оно занимает около 27 MiB.

**Передача `content` массивом.** Для текстовых моделей передавайте `content` строкой. Массив с одним элементом `text` тоже работает, но избыточен. Массив обязателен только для запросов с изображениями.

## Смотрите также

- [Потоковая передача](./streaming.md)
- [Гарантированный JSON-ответ](./json.md)
- [Вызов функций](./tools.md)
- [Анализ изображений](./vision.md)
- [Лимиты запросов](./rate-limits.md)
- [Жизненный цикл моделей](/docs/ai/models/lifecycle)
- [Список моделей](/docs/ai/models/list)
- [AI Router](/docs/ai)

