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

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

### FIX-0707-1: smart-processes: linkedUserFields принимает Y/N и булевы значения

**Было**

[POST /v1/smart-processes](/docs/entities/smart-processes/create) и [PATCH /v1/smart-processes/:entityTypeId](/docs/entities/smart-processes/update) с `linkedUserFields` работали только когда значение флага было строго `"true"`/`"false"`. Значение в конвенции `"Y"`/`"N"` (как у всех остальных полей смарт-процесса) или булево `true`/`false` молча игнорировалось: запрос возвращал `success: true`, но отображение в пользовательском поле не включалось.

**Стало**

Значения `linkedUserFields` нормализуются так же, как вложенный флаг `relations[].isChildrenListEnabled`: `true`/`"Y"`/`"yes"`/`1` → включено, `false`/`"N"`/`"no"`/`0` → выключено. Прежние вызовы с `"true"`/`"false"` продолжают работать без изменений.

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

Ничего менять не нужно — вызовы, которые раньше «молча не срабатывали» с `"Y"`, теперь применяются корректно.

### BC-0707-2: Нормализация вложенных полей карточки заказа

> Поддержка старого формата до: 06.01.2027

**Было**

`GET /v1/orders/{id}` отдавал вложенные массивы `clients`, `payments`, `basketItems` в сыром виде Bitrix24: булевы поля строками `"Y"` и `"N"` (`payments[].paid`, `clients[].isPrimary`, `basketItems[].vatIncluded` и другие), даты внутри `payments` и `basketItems` со смещением `+03:00`, а поле `companyId` со значением `0`, когда компания не задана. Поле `accountNumber` при создании и обновлении молча игнорировалось.

**Стало**

Вложенные Y/N-поля приходят как boolean (`true` или `false`); вложенные даты нормализованы к UTC (оканчиваются на `Z`); `companyId` при отсутствии компании приходит `null` вместо `0`; `accountNumber` стал полем только для чтения — попытка задать его при создании или обновлении возвращает `400` с кодом `READONLY_FIELD`.

**Что делать интеграторам**

Читать вложенные Y/N-поля как boolean, а не сравнивать со строкой `"Y"`; трактовать `null` вместо `0` как признак «компания не задана»; не передавать `accountNumber` в теле создания и обновления — номер присваивается автоматически.

### FIX-0707-3: Спека /v1/openapi.json приведена к фактическому рантайму

**Было**

Машинная OpenAPI-спека генерировалась из статической метаданной сущностей и расходилась с реальными ответами: ни одно поле не помечено nullable, вложенные массивы карточки заказа типизировались как строка, у списочных методов не описаны `filter` и `select`, у операций объявлены только успешные коды и `403`.

**Стало**

Спека теперь отражает контракт. Nullable-поля выводятся в форме `type: ["<тип>", "null"]`. Объектные и массив-объектов поля типизируются честно, включая вложенные `clients`, `payments`, `basketItems`, `propertyValues` у `GET /v1/orders/{id}`. На списочных методах описаны query-параметры `filter` и `select`. Операции несут стандартные коды ошибок `400`, `401`, `404`, `422` в едином конверте `{ success:false, error:{ code, message } }`. Схемы `*Input` объявляют обязательные при создании поля. Дополнительно `GET /v1/orders/fields` отдаёт `clients` как массив вместо object. SDK, сгенерированный из спеки, получает корректную типизацию.

### BC-0707-4: /search: авто-оконный поиск при полном отказе отдаёт настоящую ошибку Bitrix24

> Поддержка старого формата до: 07.09.2026

**Было**

Любой неуспешный авто-оконный `POST /v1/{entity}/search` возвращал `502 { "error": { "code": "WINDOWED_SEARCH_FAILED" } }` с общим советом «добавьте autoWindow:false».

**Стало**

Ответ совпадает с тем же запросом на узком диапазоне — реальный код и сообщение: отклонённое поле фильтра/сортировки → `400 UNKNOWN_FILTER_FIELD` / `400 INVALID_PARAMS`; нет прав → `403`; лимит запросов / перегрузка очереди → `429` + `Retry-After`; таймаут → `503`; недоступность Bitrix24 → `502 BITRIX_UNAVAILABLE`. Частичный отказ окон (статус `200`) теперь несёт `meta.windowErrorSample` `{ code, message }`.

**Что делать интеграторам**

Если вы ветвились на `error.code === "WINDOWED_SEARCH_FAILED"` (например, чтобы повторить с `autoWindow:false`) — ветвитесь на реальные коды. Обходной путь `autoWindow:false` остался; он полезен там, где действительно помогает (подсказка `429 QUEUE_TIMEOUT` называет его). Ответ полного отказа больше не несёт блок `meta` (`autoWindowed`/`windowCount`/`windowErrors`) — сигнал теперь в самом коде/сообщении ошибки; `meta.windowErrorSample` остаётся на частичном отказе (статус `200`).

### FIX-0707-5: списки на портале без модуля стабильно отдают 409, а не 429

**Было**

На портале, где модуль «Универсальные списки» не включён, вызовы [/v1/lists](/docs/lists) отдавали понятный `409 LISTS_MODULE_NOT_ENABLED` только для первых нескольких запросов. После этого встроенная защита от циклов ошибок срабатывала и все последующие вызовы возвращали `429 ERROR_LOOP_DETECTED` — реальная причина (модуль не подключён) переставала быть видна.

**Стало**

Сигнал «метод недоступен на портале» больше не учитывается защитой от циклов, поэтому вызовы `lists.*` на портале без модуля стабильно возвращают `409 LISTS_MODULE_NOT_ENABLED` при любом числе повторов. Ответ остаётся действенным: подключите модуль на портале и повторите запрос.

### NEW-0707-6: Подсказка error.hint на 400 при создании сервера без source и без provider/plan/region

[POST /v1/infra/servers](/docs/infra/servers/create) при `400 INVALID_REQUEST` из-за отсутствующих `provider`/`plan`/`region` (и отсутствующего `source`) на портале с galaxy-размещением теперь дополнительно возвращает объект `error.hint` с полями `reason` (почему запрос отклонён на этом портале), `recovery` (рекомендованный one-shot путь и рабочая двухшаговая альтернатива) и `example` (готовый скелет тела one-shot запроса). Поля `error.code` и `error.message` не изменились — подсказка строго аддитивна; на порталах без galaxy-размещения ответ прежний, без `hint`.

Подсказка также возвращается в ветке `400 RUNTIME_PARAM_REMOVED` (создание с `runtime`, но без `source`, на портале с galaxy-размещением), а тело с `placement: "dedicated"` получает отдельный вариант подсказки — под выделенный сервер, с сохранением намерения и добавлением недостающего tuple `provider`/`plan`/`region`, без увода в galaxy-контейнер.

### FIX-0707-7: Galaxy-чек-лист деплоя в /v1/me приведён к фактическому контракту

**Было**: шаг 2 чек-листа `deployment.galaxyApp.checklist` предписывал [POST /v1/infra/servers](/docs/infra/servers/create) `{ name }` без `source` и без `provider`/`plan`/`region` — такой вызов всегда завершался `400 INVALID_REQUEST`. Правило CREATE не объясняло, что для двухшагового пути обязателен полный набор `provider`/`plan`/`region`, а `newAppPlacement.note` обещала выделенный standalone-VM там, где создание возвращает galaxy-слот с `next: "deploy"`. Favicon-гайд направлял в этот же неработающий порядок; окно уборки недеплоенного слота указывалось как «~12-20 мин» при фактических ~20-25.

**Стало**: рекомендованный путь — один вызов `POST /v1/infra/servers { name, source, runtime, start }` (`provider`/`plan`/`region` опускаются). Двухшаговый путь описан правдиво: создание без `source` требует полный `provider`/`plan`/`region` (значения для galaxy информационны — приложение наследует хост), на galaxy-размещении возвращает слот с `next: "deploy"`; недеплоенный слот убирается в ERROR после ~20 мин (проверка каждые 5 мин). Favicon: основной путь — собственный `/icon.svg` в архиве (id не нужен); платформенный URL — альтернатива через two-step или re-deploy. Шаг опроса статуса получил ветку `status=error` → `provisionError`/`buildLog` → re-deploy.

**Влияние на интеграторов**: агенты, следующие чек-листу, деплоят с первого вызова. Поведение эндпоинтов не менялось — обновлены только тексты `/v1/me` и описание в `/v1/openapi.json`; существующие интеграции продолжают работать без изменений.

### NEW-0707-8: AI-квота компании доступна через API

Новый эндпоинт [GET /v1/ai/quota](/docs/ai/consumption/quota) возвращает состояние месячной AI-квоты портала: процент израсходованного лимита (`pctUsed`, честное значение — при перерасходе больше 100), признак исчерпания (`exhausted`), дату сброса (`resetAt`, скользящее 30-дневное окно) и разбивку по моделям — количество запросов, токены и долю месячного лимита на каждую модель (`byModel[].pctOfLimit`). Абсолютные значения лимита в Вайбах не раскрываются — только проценты, как в кабинете. Требуется скоуп `vibe:ai`.
