# Изменения API: 17 июля 2026

[← Журнал изменений](/docs/changelog) · [Июль 2026](/docs/changelog/2026-07)

### FIX-0717-1: деплой на спящий galaxy-хост отвечает раньше клиентских таймаутов

**Было**

[POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy) на спящем общем хосте удерживал соединение открытым до ~6,5 минут, пока хост просыпался. HTTP-клиенты с типовым таймаутом ожидания заголовков (~300 секунд — дефолт Node fetch) обрывали соединение раньше ответа платформы: деплой выглядел как сетевой сбой `fetch failed` без кода ошибки и рекомендаций. Неудачное пробуждение к тому же возвращало хост в сон, и каждый повтор начинал загрузку хоста заново.

**Стало**

Платформа будит хост в фоне и ждёт подключения не дольше ~4 минут. Хост успел подключиться — деплой выполняется одним вызовом, как раньше. Не успел — сразу возвращается повторяемый `502 GALAXY_HOST_UNREACHABLE` с `hint` (повторить тот же запрос через 1–2 минуты, слот не удалять), а хост продолжает просыпаться в фоне — повторный деплой подхватывает уже идущую загрузку вместо новой. В `deployment.galaxyApp._rules` и `deployment.standalone._rules` (GET /v1/me) добавлена рекомендация держать таймаут HTTP-клиента не ниже 690 секунд — строго выше платформенного окна в 660 секунд.

**Влияние на интеграторов**

Изменений в запросах не требуется. Если деплой на спящий galaxy-хост раньше завершался у вас сетевой ошибкой без ответа платформы — теперь придёт либо успех, либо 502 с инструкцией повторить.

### NEW-0717-2: поиск сотрудников на сервере подсказывает причину пустого списка

Эндпоинт [GET /v1/infra/servers/:id/b24-users](/docs/infra/access/b24-users) теперь возвращает дополнительное поле `hint`, когда список пуст из-за отсутствия доступа к Битрикс24 — приложение ещё не авторизовано на портале или ключ отозван. Прежние вызовы работают без изменений: поле аддитивное и отсутствует при успешной выдаче.

### NEW-0717-3: справочники полей каталога сообщают о nullable-полях

Справочники [GET /v1/catalog-prices/fields](/docs/entities/catalog-prices/fields), [GET /v1/catalog-sections/fields](/docs/entities/catalog-sections/fields) и [GET /v1/catalog-products/fields](/docs/entities/catalog-products/fields) теперь добавляют ключ `"nullable": true` полям, которые могут вернуть `null`: у цен это `quantityFrom`, `quantityTo` и `extraId`, у разделов — `iblockSectionId`, `xmlId`, `code` и `description`, у товаров — `iblockSectionId`, `code`, `weight`, `purchasingPrice`, `purchasingCurrency`, `quantity` и `quantityReserved`. Тот же признак приходит в `data.entities[].fieldsDetailed` ответа [GET /v1/guide](/docs/keys-auth/guide), который читается ключом OAuth-приложения без сессии, а в машинной спеке [GET /v1/openapi.json](/docs/cli) такие поля описаны union-типом вида `["number", "null"]`. Клиент, который строит типизированную модель по справочнику, теперь получает верную nullability и не падает на первом же `null`. Набор полей, их типы и значения в ответах не изменились.

### NEW-0717-4: EXEC_BUSY подсказывает, через сколько повторить

Ответ `409 EXEC_BUSY` (другая операция держит блокировку сервера) на [POST /v1/infra/servers/:id/exec](/docs/infra/deploy/exec) и `POST /v1/infra/servers/:id/deploy` теперь несёт retry-подсказку: HTTP-заголовок ответа `Retry-After` (в секундах) и два новых поля в теле ошибки — `retryable: true` и `retryAfter` (в секундах). Значение `retryAfter` — короткий интервал опроса (повторяйте с ним, пока не пройдёт), а не полное время до автоматического снятия блокировки; полный верхний предел по-прежнему в `error.hint.autoExpiresInSeconds`. Изменение аддитивное: код, поле `message` и `hint` не меняются, клиенты, читающие `error.code`, продолжают работать без правок.

### FIX-0717-5: деплой galaxy-приложения со слишком большим архивом отдаёт 413, а не «хост недоступен»

**Было**

[POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy) с `source.content`, превышающим лимит загрузки, возвращал `502 GALAXY_HOST_UNREACHABLE` — с текстом про недоступность хоста и советом «повторить, когда хост переподключится». Хост при этом был полностью доступен, а повтор того же архива давал тот же результат: интегратор оказывался в бесконечном цикле бесполезных попыток.

**Стало**

Тот же случай возвращает `413 GALAXY_UPLOAD_TOO_LARGE` со структурированным `error.hint`. Причина детерминирована (архив слишком большой), а не транзиентна, поэтому повтор без изменений не поможет. `hint` подсказывает уменьшить архив — исключить `node_modules`, `.git` и артефакты сборки (зависимости платформа ставит на хосте). У galaxy-приложения источник — только встроенный `source.content` (`source.url` отклоняется с `400 GALAXY_DEPLOY_CONTENT_ONLY`), поэтому уменьшить архив — единственный способ восстановления. Отдельный смежный случай: тело запроса, превышающее жёсткий внешний лимит платформы (500 МБ на base64-тело ≈ ~375 МБ бинарного архива), теперь отклоняется на краю кодированным `413 PAYLOAD_TOO_LARGE` (на Vibe-REST `/v1/`-маршрутах — deploy/upload/create; OpenAI-совместимые AI-роуты отдают ошибку в своём конверте) вместо сырого HTML — раньше клиент получал недекодируемый ответ.

**Влияние на интеграторов**

Ничего менять не нужно: успешные деплои не затронуты. Клиенты, которые ветвились на коде ошибки для этого сбоя, теперь видят честный `413 GALAXY_UPLOAD_TOO_LARGE` вместо вводящего в заблуждение `502 GALAXY_HOST_UNREACHABLE` — последний остаётся для настоящего обрыва туннеля во время сборки.

### NEW-0717-6: displayName и description в деплое задают карточку в каталоге Битрикс24

[POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy) принял два необязательных поля тела — `displayName` и `description`. [POST /v1/infra/servers](/docs/infra/servers/create) (создание сервера) принял необязательный `description`. Значения становятся именем и описанием карточки приложения в каталоге Битрикс24. Если деплой прошёл без `displayName` и `description`, ответ содержит `warnings: string[]` с подсказкой задать их; одношаговое создание galaxy-приложения с `source` (тело `POST /v1/infra/servers` с полем `source`) тоже возвращает `warnings` в ответе 201, когда поля не заданы. Обратная совместимость сохранена — запросы без новых полей продолжают работать как раньше.

### FIX-0717-7: деплой галактик отдаёт 503 при временной перегрузке базы

**Было**

При кратковременном исчерпании пула соединений с базой во время деплоя приложения в галактику [POST /v1/infra/servers/:id/deploy](/docs/infra/deploy/deploy) возвращал общий `502 GALAXY_APP_DEPLOY_FAILED` — тот же код, что и настоящий провал сборки. Клиент не мог отличить временную перегрузку от терминальной ошибки и часто читал ответ как окончательный.

**Стало**

Временная перегрузка базы теперь отдаётся как `503 POOL_EXHAUSTED` с заголовком `Retry-After` (число секунд для повторной попытки). Настоящий провал сборки по-прежнему `502 GALAXY_APP_DEPLOY_FAILED`.

**Влияние на интеграторов**

Ничего менять не нужно. Если ваш клиент повторяет запросы, теперь на `503` он получает явный сигнал бэкоффа через `Retry-After` вместо непрозрачного `502`.

### FIX-0717-8: фильтр и сортировка списка комментариев задачи работают на обеих карточках

**Было**

Запрос [GET /v1/tasks/:taskId/comments](/docs/entities/task-comments/list) с параметром `filter` или с сортировкой не по `ID` на портале с новой карточкой задачи возвращал `200` и пустой список, даже когда комментарии в задаче были. Ошибки не приходило, поэтому отличить «под фильтр ничего не подошло» от «фильтр не сработал» было нельзя.

**Стало**

Такой запрос возвращает подошедшие комментарии. Фильтр и сортировка работают по полям `ID`, `AUTHOR_ID` и `POST_DATE`, перед именем поля в фильтре допустим префикс `!`, `>`, `>=`, `<` или `<=`. Фильтр по `AUTHOR_NAME` и сортировка по `AUTHOR_NAME` или `AUTHOR_EMAIL` на новой карточке отвечают `400` с кодом `UNSUPPORTED_FILTER_FIELD` или `UNSUPPORTED_SORT_FIELD` и указывают на `AUTHOR_ID`, на старой карточке эти поля по-прежнему принимаются. Добавлен параметр `offset` — он учитывается на новой карточке при запросе с `filter` или сортировкой не по `ID`, на остальных путях чтения игнорируется. Код `INVALID_FILTER` теперь приходит ещё и тогда, когда `filter` — скаляр или пустой массив вместо объекта (`0`, `false`, `""`, `[]`), значение поля `ID` или `AUTHOR_ID` не число, значение `POST_DATE` не разбирается как дата, либо значение поля — объект или массив вместо скаляра. В `meta` добавлено поле `truncated` со значением `true` — просмотрено предельное окно истории, и часть комментариев осталась за его границей.

**Влияние на интеграторов**

Менять ничего не нужно: запрос, который раньше отдавал пустой список, начинает отдавать данные. Учтите три границы. Первая — фильтр по `AUTHOR_NAME` и сортировка по `AUTHOR_NAME` или `AUTHOR_EMAIL` на портале с новой карточкой вместо пустого `200` теперь отвечают `400`, переведите такой запрос на `AUTHOR_ID`, идентификатор сотрудника по имени даёт `GET /v1/users`. Вторая — `meta.total` на запросе с фильтром к новой карточке считает подошедшие комментарии в пределах просмотренного окна, а не во всей истории задачи, и при `meta.truncated: true` это неполное число. Третья — значение `POST_DATE` на новой карточке сравнивается с `createdAt` в UTC, поэтому результат на границе суток может отличаться от выборки на старой карточке. На порталах со старой карточкой поведение не изменилось.
