# Запросы и ответы

Общие правила всех методов: формат тела и ответа, идентификаторы, списки, совместимость с
SDK OpenAI и кеширование.

## Формат

- Тело запроса — JSON (`Content-Type: application/json`), кроме загрузки файла и
  транскрибации: там `multipart/form-data`.
- Ответ — JSON, кроме синтеза речи (байты звука), транскрибации в форматах `text` и `srt`
  и потока событий (`text/event-stream`).
- Время — RFC 3339 в UTC (`2026-09-25T12:00:00Z`); `created` у чата и задачи — unix-секунды.
- Деньги — целые микроединицы рядом с `currency` — [Цены и баланс](https://souz.ai/docs/pricing.md).

## Идентификаторы

У объекта есть поле `object` (`job`, `file`, `model`, `list`…), у идентификатора — префикс: `job_…` — задача, `chatcmpl-…` — ответ чата (его итог —
`GET /v1/jobs/chatcmpl-…`), `file_…` — файл, `key_…` — API-ключ, `mem_…` — участник,
`user_…` — аккаунт. Секрет подписи вебхуков начинается с `whsec_`.

Каждый ответ API несёт заголовок `X-Request-Id`: у запроса, который создал задачу, — её id
(`job_…`, у чата — `chatcmpl-…`), у остальных, в том числе у отказов до задачи (400, 401,
402, 429, 503), — `req_…`. Пришлите его в поддержку — по нему находится запрос.

## Списки

Список — `{"object": "list", "data": [...]}`. Постранично отдаются файлы
(`GET /v1/files`: `?limit=` до 100 и `?after=<id последнего>`, в ответе `has_more`), история
баланса и запросов (`GET /v1/balance/history`, `GET /v1/usage`: `?limit=` до 1000 и
`?before=`, в ответе `next_before`). Каталог и список ключей приходят целиком.

## Лишние, пустые и «ничего не меняющие» поля

- `null` в необязательном поле значит то же, что его отсутствие: умолчание модели или
  настройка ключа.
- Поле, которого у метода нет, — `400 invalid_request` с
  `{"path": "<поле>", "reason": "unsupported_field"}`.
- Значение, которое у модели ничего не меняет, **принимается молча**: её умолчание,
  `auto`, поле, которого у модели нет, со значением, которое она и так даёт. Простой запрос
  работает с любой моделью той же модальности.
- Значение, которое изменило бы результат или цену, но модели недоступно, —
  `400 capability_mismatch` со списком допустимых в `detail[].allowed`.

## Совместимость с OpenAI

Чат — контракт OpenAI Chat Completions. `models.list` и `models.retrieve`,
`images.generate`, `videos.create` и `videos.retrieve`, `audio.transcriptions.create`,
`audio.speech.create`, `files.*` SDK OpenAI работают как есть; поля Souz API сверх
OpenAI (`routing`, `routing_options`, `callback_url`…) передаются через `extra_body`, а
заголовки — через `extra_headers`. Поле `user` SDK принимается и ни на что не влияет.

## Кеширование

`GET /v1/models`, `GET /v1/models/{id}`, `GET /v1/models/{id}/channels`, `GET /v1/channels`
и `GET /v1/models/{id}/stats` несут `ETag`: с `If-None-Match` того же значения — `304`
без тела. Без авторизации каталог, карточку и каналы модели можно хранить 30 секунд и
ещё 5 минут отдавать сохранённый ответ, проверяя его в фоне
(`Cache-Control: public, max-age=30, stale-while-revalidate=300`). Ответ с ценами
аккаунта — `Cache-Control: private, no-cache`: его хранит только ваш клиент и проверяет
перед каждым использованием. Ответы JSON сжимаются, если клиент передал
`Accept-Encoding: gzip`.

---

Оглавление документации: https://souz.ai/llms.txt. Всё руководство одним файлом: https://souz.ai/llms-full.txt. Справочник методов: https://souz.ai/docs/api-reference.md.
