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

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

### NEW-0710-1: управление окнами пробуждения по расписанию (wake-schedules)

Новый CRUD-контракт на серверах Black Hole: `GET`/`POST /v1/infra/servers/:id/wake-schedules`, `PATCH`/`DELETE /v1/infra/servers/:id/wake-schedules/:scheduleId`. Позволяет объявить одно или несколько повторяющихся окон пробуждения (`cronExpr` + обязательная IANA-таймзона `timezone`, необязательные `label`/`lead`/`enabled`) — платформа будит спящий сервер к нужному моменту, дальше запуск задачи делает собственный cron внутри VM.

Раскатывается постепенно и пока не работает на всех порталах — до включения на конкретном портале запрос отвечает `403` с кодом `WAKE_SCHEDULE_DISABLED`. Доступно только для серверов в режиме BLACKHOLE (иначе `400 BLACKHOLE_ONLY`) и пока не поддержано для галактик (`400 GALAXY_NOT_SUPPORTED` на хосте и вложенном приложении — появится позже). Минимальный интервал между срабатываниями и лимит окон на сервер (50) заданы платформой; нарушение отвечает `400 CADENCE_TOO_LOW` и `403 WAKE_SCHEDULE_LIMIT` соответственно. Ответ создания/обновления дополнительно несёт поле `tzWarning` — предупреждение о том, что таймзона в VM могла разойтись с таймзоной окна, если сервер не переразвёртывался. **`PATCH` заменяет окно целиком (PUT-семантика): не переданные необязательные поля сбрасываются к значениям по умолчанию — `enabled`→`true`, `label`/`lead`→пусто.** Передавайте полный объект окна при обновлении.

Затронутые эндпоинты: `GET|POST /v1/infra/servers/:id/wake-schedules`, `PATCH|DELETE /v1/infra/servers/:id/wake-schedules/:scheduleId`.

### NEW-0710-2: машиночитаемый код tz-предупреждения в ответах wake-schedules (`tzWarningCode`)

Ответ создания/обновления окна пробуждения (`POST`/`PATCH /v1/infra/servers/:id/wake-schedules[/:scheduleId]`) теперь дополнительно несёт поле `tzWarningCode` рядом с существующим текстовым `tzWarning` — `"SINGLE_ZONE"` / `"MULTI_ZONE"` / `null` (когда после мутации у сервера не осталось включённых окон). Значение — машиночитаемый эквивалент того же предупреждения, чтобы клиент мог локализовать текст сам вместо отображения английской строки `tzWarning` как есть. Поле аддитивное, `tzWarning` не меняется и остаётся для обратной совместимости.

Затронутые эндпоинты: `POST|PATCH /v1/infra/servers/:id/wake-schedules[/:scheduleId]`.

### FIX-0710-3: wake-schedules: расписание запрещено на серверах «Всегда онлайн»

`POST`/`PATCH /v1/infra/servers/:id/wake-schedules` теперь отклоняют создание или обновление окна пробуждения на сервере в режиме «Всегда онлайн» (24/7) — ответ `400` с кодом `ALWAYS_ON_CONFLICT`. Такой сервер работает на невытесняемом тарифе и не уходит в авто-сон, поэтому расписание пробуждения тихо нарушило бы оплаченную гарантию постоянной доступности. Обычные засыпающие серверы Black Hole и вытесняемые агенты/боты не затронуты. Отключите «Всегда онлайн», чтобы объявлять окна пробуждения.

Затронутые эндпоинты: `POST /v1/infra/servers/:id/wake-schedules`, `PATCH /v1/infra/servers/:id/wake-schedules/:scheduleId`.

### FIX-0710-4: wake-schedules теперь можно объявлять на вложенных приложениях galaxy

**Было**

`POST`/`PATCH /v1/infra/servers/:id/wake-schedules` отвечал `400 GALAXY_NOT_SUPPORTED` для любого сервера семейства galaxy — как для самого хоста, так и для вложенных приложений (`kind=GALAXY_APP`).

**Стало**

Вложенные приложения galaxy (`kind=GALAXY_APP`) теперь принимаются — окно пробуждения можно объявить на конкретном приложении, и платформа разбудит его (и при необходимости — хост) к нужному моменту. Сам хост galaxy по-прежнему отвечает `400 GALAXY_NOT_SUPPORTED`: расписание объявляется на приложениях, а не на хосте.

Затронутые эндпоинты: `POST|GET /v1/infra/servers/:id/wake-schedules`, `PATCH|DELETE /v1/infra/servers/:id/wake-schedules/:scheduleId`.

### FIX-0710-5: sleep-now откладывает засыпание, когда пробуждение по расписанию близко

**Было**

[POST /v1/infra/servers/:id/sleep-now](/docs/infra/lifecycle/sleep-now) всегда усыплял сервер немедленно, даже если ближайшее пробуждение по расписанию наступало через минуту — сервер сразу же просыпался обратно.

**Стало**

Если у сервера есть включённое расписание пробуждения и ближайшее пробуждение наступит в пределах защитного окна, вызов не усыпляет сервер и отвечает `200` с телом `{ "success": true, "data": { "slept": false, "reason": "WAKE_IMMINENT" } }`. В остальных случаях сервер усыпляется, а планировщик разбудит его в следующее окно.

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

Блок `data` с полем `slept: false` приходит только при отказе усыпить — проверяйте его наличие, если полагаетесь на то, что после вызова сервер обязательно засыпает. При успешном усыплении ответ состоит из одного `success: true`. Старые вызовы серверов без расписания работают без изменений.

### FIX-0710-6: не-стриминговые chat/completions и embeddings больше не обрываются на 360 секундах

**Было**

Не-стриминговый (`stream:false`) запрос к `POST /v1/chat/completions` (и `POST /v1/embeddings`), генерация которого длилась дольше ~2 минут, стабильно обрывался на ~360 секундах с `{"code":"ai_provider_unavailable","message":"This operation was aborted"}` — независимо от таймаута клиента.

**Стало**

Такой запрос обрабатывается в рамках единого бюджета ~850 секунд. Если генерация всё же не укладывается в бюджет, возвращается осмысленный `503` с кодом `ai_provider_timeout`, локализованным `userMessage` и подсказкой (уменьшить объём запроса либо использовать потоковый режим `stream:true`) — без заголовка `Retry-After` (таймаут не транзиентный). Обрыв соединения клиентом теперь немедленно отменяет генерацию на стороне провайдера. Стриминговый режим (`stream:true`) этим лимитом не затрагивался.

### FIX-0710-7: requisite-presets/:presetId/fields и requisite-links: сортировка, фильтрация и валидация параметров списка

**Было**

[GET /v1/requisite-presets/:presetId/fields](/docs/entities/requisite-presets) игнорировал `sort`/`order` и любые `filter[...]` — всегда возвращал полный список в порядке Битрикс24. [GET /v1/requisite-links](/docs/entities/requisite-links) и [POST /v1/requisite-links/search](/docs/entities/requisite-links) принимали только простое равенство, а операторы (`$gte`, `>` и т.п.), `sort`/`order` и неизвестные поля молча пропускались — в результате приходила вся таблица.

**Стало**

Оба списка честно применяют `sort`/`order` (в том числе форму `order[поле]=asc|desc`) и `filter`. У requisite-links работают операторы сравнения (`$gt`/`$gte`/`$lt`/`$lte`, `$in`/`$nin`, префиксы `>=`/`>`). Неизвестное поле фильтра или сортировки теперь возвращает `400` (`UNKNOWN_FILTER_FIELD` / `UNKNOWN_SORT_FIELD`), логический оператор верхнего уровня (`$or`/`$and`) — `400 INVALID_FILTER_OPERATOR`, а фильтр по `entityId` без `entityTypeId` — `400 MISSING_ENTITY_TYPE_ID` вместо сырого «Access denied».

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

Запросы по документированным полям продолжают работать и теперь действительно сортируются/фильтруются. Если раньше вы полагались на молчаливое игнорирование неизвестного параметра, теперь он вернёт `400` — уберите опечатку или используйте поле из ответа.

### FIX-0710-8: Сортировка банковских реквизитов по id учитывает направление

**Было**

Запрос списка банковских реквизитов ([GET /v1/bank-details](/docs/entities/bank-details/list)) с сортировкой по `id` по убыванию (`?sort=-id`) возвращал записи по возрастанию — направление сортировки молча игнорировалось.

**Стало**

`?sort=-id` (и `?sort=id`) сортирует по идентификатору в запрошенном направлении.

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

Изменений в коде не требуется — запросы, полагавшиеся на сортировку по `id`, теперь возвращают ожидаемый порядок.

### NEW-0710-9: GET /v1/quotes/fields — объявлены ~26 полей предложения с человеческими названиями

Схема сущности «предложения» (quotes) пополнена ~26 полями, которые Битрикс24 возвращал, но которые не были объявлены: `quoteNumber`, `updatedBy`, `lastActivityBy`, `lastActivityTime`, `content`, `terms`, `leadId`, `storageTypeId`, `storageElementIds`, `personTypeId`, `webformId`, `lastCommunicationTime`, `contactIds`, `contacts`, `locationId`, `taxValue`, `actualDate`, `mycompanyId`, `utmSource`/`utmMedium`/`utmCampaign`/`utmContent`/`utmTerm`, `lastCommunicationCallTime`/`lastCommunicationEmailTime`/`lastCommunicationImolTime`/`lastCommunicationWebformTime`. Теперь они видны в [GET /v1/quotes/fields](/docs/entities/quotes/fields) с читаемыми названиями (вместо служебных `STORAGE_TYPE_ID`/`UTM_SOURCE`), а их значения приводятся к типам (числа, даты в ISO) в ответах list/get. Названиями снабжены также ранее необъявленные `stageId`, `opened`, `closed`.

### FIX-0710-10: PATCH без единого записываемого поля отклоняется явной ошибкой

**Было**

`PATCH /v1/{entity}/:id` с пустым телом — или с телом, в котором нет ни одного распознанного записываемого поля (например из-за опечатки в имени поля) — доходил до Битрикс24, который молча игнорировал такой запрос и отвечал успехом. Обёртка возвращала `200` с неизменённым объектом, и клиент считал, что правка применилась, хотя на деле ничего не менялось — риск тихой рассинхронизации, особенно у AI-агентов. Это касалось всех трёх поверхностей обновления: одиночного `PATCH /v1/{entity}/:id`, пакетного `POST /v1/{entity}/batch` и общего `POST /v1/batch`.

**Стало**

Обновление с пустым телом возвращает `400 EMPTY_UPDATE_BODY` (в пакетных вызовах — ошибку элемента) на всех трёх поверхностях, до обращения к Битрикс24. Для `/v1/catalog-products/:id` добавлена строгая проверка: `PATCH`, в котором нет ни одного распознанного записываемого поля, возвращает `400 NO_RECOGNIZED_UPDATE_FIELDS`. Осмысленное обновление всегда несёт хотя бы одно поле — передайте распознаваемое поле (пользовательские свойства `propertyNNN` и поля `UF_*` тоже принимаются). Сущности, у которых уже была проверка полей, ведут себя как прежде.

Дополнительно у товаров каталога в `GET /v1/catalog-products/fields` появились и стали доступны для явного `select`, фильтра и сортировки поля из контракта обновления товара — `code`, `xmlId`, `sort`, `vatId`, `height`, `length`, `width`, `previewText`, `detailText` и другие (раньше фильтр по ним отвечал `400 UNKNOWN_FILTER_FIELD`). Надёжно фильтровать и сортировать стоит по индексируемым полям (`code`, `xmlId`, `sort`, `vatId`, размеры); по полнотекстовым (`previewText`, `detailText`) Битрикс24 фильтр может игнорировать. Ответы списков без явного `select` не изменились.

### FIX-0710-11: leads, companies, quotes — поля дат в /fields теперь createdTime и updatedTime

**Было**

`GET /v1/leads/fields`, `GET /v1/companies/fields` и `GET /v1/quotes/fields` объявляли поля `createdAt` и `updatedAt`, хотя в ответах list/get/search Bitrix24 всегда возвращал `createdTime` и `updatedTime` — прочитать значение по имени `createdAt`/`updatedAt` было нельзя. Фильтр и сортировка при этом принимали имена `createdAt`/`updatedAt`.

**Стало**

`/fields` этих сущностей объявляют реальные ключи `createdTime` и `updatedTime` — как у contacts, invoices и items. Ключи в теле ответов те же (`createdTime`/`updatedTime` приходили всегда), но теперь значение нормализуется к ISO-8601 в UTC (`2026-04-15T07:00:00.000Z`) — раньше приходило в исходном формате Bitrix24 со смещением портала (`2026-04-15T10:00:00+03:00`). Момент времени тот же, меняется только представление.

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

Читайте даты из `createdTime` и `updatedTime` (ключи не менялись). Если вы сравниваете строку даты побайтово или кэшируете по ней — учтите переход `+03:00` → `Z` (тот же момент времени). В фильтре и сортировке используйте `createdTime`/`updatedTime`; прежние `createdAt`/`updatedAt` теперь возвращают `400 UNKNOWN_FILTER_FIELD` (фильтр) и `400 UNKNOWN_SORT_FIELD` (сортировка). На запись `createdAt`/`updatedAt` больше не отклоняются как readonly — они игнорируются как неизвестные поля (как у contacts/invoices/items); задать дату создания/изменения по-прежнему нельзя.

### FIX-0710-12: сон-настройки: флип в «Всегда онлайн» теперь запрещён при активных окнах пробуждения

`PATCH /v1/infra/servers/:id/sleep` теперь отклоняет установку `sleepAfterMinutes: null` («Всегда онлайн», 24/7) на сервере, у которого есть включённые окна расписания пробуждения — ответ `400` с кодом `ALWAYS_ON_CONFLICT`. Это обратное направление уже существующего гейта: раньше запрещалось создавать окно пробуждения на сервере «Всегда онлайн», теперь симметрично запрещён и обратный переход — иначе сервер продолжал бы засыпать по расписанию, тихо нарушая оплаченную гарантию постоянной доступности. Удалите или отключите окна пробуждения, либо оставьте таймаут сна вместо «Никогда», чтобы включить «Всегда онлайн».

Затронутые эндпоинты: `PATCH /v1/infra/servers/:id/sleep`.

### NEW-0710-13: placement.bind на коробочном Битрикс24 отдаёт понятный SESSION_REQUIRES_ADMIN для не-администратора

На коробочном (self-hosted) Битрикс24 привязка плейсмента через путь developer-key требует, чтобы пользователь ключа был администратором аккаунта. Раньше запрос не-администратора возвращал глухой `502 BITRIX_UNAVAILABLE`.

Теперь [POST /v1/placements/bind](/docs/keys-auth) распознаёт отказ доступа со стороны Битрикс24 и возвращает `403 SESSION_REQUIRES_ADMIN` с подсказкой: выполните привязку под учётной записью администратора аккаунта либо попросите администратора выдать эти права. Требование заранее видно в [GET /v1/me](/docs/keys-auth) — блок `placements.bindPrerequisite` для коробочных аккаунтов теперь включает код `SESSION_REQUIRES_ADMIN`.

### FIX-0710-14: capabilities в GET /v1/me отражают режим только для чтения (READONLY)

**Было**

Для ключа в режиме READONLY [GET /v1/me](/docs/keys-auth) отдавал `capabilities.managedBots.create`, `agents.create`, `servers.create` и `apps.*` со значением `available: true`, хотя любая операция записи блокируется с `403 WRITE_BLOCKED_READONLY_KEY`. Агент видел «можно создать» и упирался в отказ.

**Стало**

Для READONLY-ключа эти write-способности возвращаются как `available: false` с `reason: "WRITE_BLOCKED_READONLY_KEY"` и подсказкой переключить ключ в режим чтение+запись. Способности только для чтения и AI Router не меняются. Для ключей в режиме READWRITE ответ прежний.

### FIX-0710-15: автор обращения без скоупа vibe:feedback снова может отвечать на своё обращение

**Было**

[POST /v1/feedback/:id/comments](/docs/keys-auth) отклонял автора обращения с `403 FEEDBACK_SCOPE_REQUIRED`, если у ключа не было скоупа `vibe:feedback` — хотя ветка автора была задокументирована. Автор не мог ответить на своё же обращение в статусе `AWAITING_USER`, и обращение зависало.

**Стало**

Проверка на автора выполняется до скоуп-гейта: автор, отвечающий тем же ключом, которым создал обращение, попадает в авторскую ветку (`authorType=USER`, правило мяча `AWAITING_USER → NEEDS_REVIEW`) даже без скоупа `vibe:feedback`. Ключ, не являющийся автором и не имеющий скоупа, по-прежнему получает `403 FEEDBACK_SCOPE_REQUIRED`.

### NEW-0710-16: Пейсинг AI-квоты: поле pacing в ответе и код ошибки 429 ai_pacing_limited

Ответ [GET /v1/ai/quota](/docs/ai/consumption/quota) дополнен полем `pacing` — состоянием равномерного расходования месячной AI-квоты (сглаживание пиков через суточный и недельный лимит поверх общего месячного лимита; включается администратором портала в кабинете `/ai`). Значение `null`, если пейсинг выключен на платформе или не настроен для портала; иначе объект `{ mode, active, day, week }`: `mode` — режим реакции на превышение (`wallet`/`block`/`ignore`), `active` — сработает ли превышение прямо сейчас в отказ (`false` в режиме наблюдения и всегда `false` при режиме `ignore` — окна считаются и только информируют, `429` не отдаётся), `day` и `week` — по `{ pctUsed, resetAt }` в процентах от собственного лимита окна. Ответ по-прежнему кэшируется на 30 секунд, поэтому состояние пейсинга может отставать на этот срок.

При срабатывании суточного или недельного лимита запросы [POST /v1/chat/completions](/docs/ai/chat/completions), [POST /v1/embeddings](/docs/ai/embeddings) и [POST /v1/audio/transcriptions](/docs/ai/audio/transcriptions) могут вернуть `429` с телом `{ success: false, error: { code: "ai_pacing_limited", type: "rate_limit_exceeded", message, reason, overageDenied, resetAt, retryAfter } }` и заголовком `Retry-After`. `reason` — какое окно пробито (`day_window` или `week_window`); `overageDenied` — причина отказа в платном превышении лимита (`wallet_empty`, `breaker`, `wallet_off`), либо `null` в режиме жёсткой блокировки. Повторять вызов раньше `Retry-After`/`resetAt` не имеет смысла — квота не станет доступнее за это время. По умолчанию пейсинг выключен — включается платформой.

### FIX-0710-17: GET /v1/pages, /v1/sites и POST /v1/{pages,sites}/search теперь учитывают offset

**Было**

Запрос списка страниц или сайтов со смещением (`GET /v1/pages?offset=50`, `POST /v1/pages/search` с `offset`) возвращал ошибку `422 BITRIX_ERROR "Unknown parameter: start"`. Первая страница (без `offset`) работала.

**Стало**

`offset` для `pages` и `sites` обрабатывается корректно: возвращается запрошенное окно `[offset, offset+limit)`, а `meta.total` и `meta.hasMore` считаются по числу строк. Менять клиентский код не нужно — вызовы без `offset` работают как раньше.

### NEW-0710-18: /fields сущностей документов, каталогов, цен, телефонных линий, позиций корзины и лидов дополнены метаданными

`GET /:entity/fields` нескольких сущностей теперь несёт более полную метаданную схемы. У документов ([GET /v1/documents/fields](/docs/entities/documents/fields)), каталогов ([GET /v1/catalogs/fields](/docs/entities/catalogs/fields)), цен каталога ([GET /v1/catalog-prices/fields](/docs/entities/catalog-prices/fields)) и телефонных линий по каждому полю добавлены человекочитаемые `label` и `description` по-русски.

У позиций корзины ([GET /v1/basket-items/fields](/docs/entities/basket-items/fields)) поля `weight`, `vatRate`, `measureCode`, `measureName`, `dimensions`, `productXmlId`, `catalogXmlId` помечены флагом `nullable` — они могут прийти пустыми. У лидов ([GET /v1/leads/fields](/docs/entities/leads/fields)) тем же флагом помечены `secondName`, `sourceDescription`, `comments`, а также объявлены ранее неописанные поля `originatorId`, `dateClosed`, `lastCommunicationTime` и метки `utmSource`/`utmMedium`/`utmCampaign`/`utmContent`/`utmTerm` — теперь по ним работают фильтр и сортировка, а `dateClosed` нормализуется к ISO-8601.

У сайтов лендингов объявлены измерения для группировки, поэтому [POST /v1/sites/aggregate](/docs/entities/sites/aggregate) с `groupBy` (`type`, `active`, `deleted`, `lang`, `tplId`, `domainId`, `createdById`, `modifiedById`) больше не отвечает `Available: .`. У документов агрегация отключена (все числовые поля — идентификаторы): [POST /v1/documents/aggregate](/docs/entities/documents/list) возвращает `404`.

Прежние вызовы работают без изменений — это дополнительные метаданные полей.

### NEW-0710-19: Идемпотентное создание сервера — заголовок Idempotency-Key

[POST /v1/infra/servers](/docs/infra/servers/create) теперь принимает необязательный заголовок `Idempotency-Key` для создания отдельного сервера (standalone). Повторный запрос с тем же ключом — например, после потерянного ответа или разрыва сети — не создаёт второй сервер: он возвращает тот же самый сервер, что и первый запрос, со статусом 201 и заголовком ответа `Idempotent-Replayed: true`. Ключ — строка 1–255 символов из набора `[A-Za-z0-9_.:-]`; область действия — ваш API-ключ.

При повторе одноразовые SSH-учётные данные (`ssh.privateKey` / `ssh.password`) НЕ выдаются повторно — в теле ответа они `null` и добавлено поле `note` с пояснением. Сохраните учётные данные из ответа первого создания.

Новые коды ошибок: `400 INVALID_IDEMPOTENCY_KEY` (ключ не проходит валидацию), `400 IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION` (ключ вместе с `graduateFrom` для выделенного сервера не поддерживается), `409 IDEMPOTENCY_KEY_ALREADY_USED` (ключ уже использован для сервера, который затем был удалён), `409 IDEMPOTENCY_CONCURRENT_RETRY` (параллельный запрос с тем же ключом ещё выполняется — повторите чуть позже).

Заголовок учитывается только для standalone-серверов. На порталах с размещением в галактике корректный ключ игнорируется без ошибки, и защита от повторного создания на этот путь не распространяется.

Дополнительно: ответ создания теперь возвращает каноническое имя сервера (с суффиксом при разрешении конфликта имён), а не имя из запроса — при совпадении имён это ранее расходилось.

### NEW-0710-20: локализованное сообщение при отказе переключения в режим OPEN

Ответы [PATCH /v1/infra/servers/:id/mode](/docs/infra/access/mode) с кодами `OPEN_MODE_DISABLED` (режим OPEN выключен на уровне платформы) и `OPEN_MODE_NOT_ALLOWED` (режим OPEN запрещён политикой портала) теперь дополнительно несут поле `error.userMessage` — локализованную человекочитаемую формулировку с подсказкой использовать [Deploy API](/docs/infra/deploy) как штатную замену прямого SSH. Поле аддитивное: `error.message` (английская техническая строка), `error.code` и HTTP-статус не меняются. Совпадает по форме с уже существующим `error.userMessage` у отказа `OPEN_MODE_REQUIRES_COMMERCIAL`. Текст `userMessage` зависит от локали владельца ключа.

### BC-0710-21: Поля конфигураций открытых линий приведены к camelCase и описаны в /fields

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

**Было**

[GET /v1/openline-configs](/docs/openlines/config/list), [GET /v1/openline-configs/{id}](/docs/openlines/config/get) и [POST /v1/openline-configs/search](/docs/openlines/config/search) возвращали большинство полей конфигурации в «родном» для Bitrix24 виде — в верхнем регистре через подчёркивание (`CRM_CREATE`, `WELCOME_MESSAGE`, `QUEUE_TIME` и другие). Справка [GET /v1/openline-configs/fields](/docs/openlines/config/fields) описывала только 6 полей, поэтому остальные не были видны для программного обнаружения.

**Стало**

Все поля конфигурации приведены к единому camelCase (`crmCreate`, `welcomeMessage`, `queueTime` и так далее), а `/fields` описывает полный набор полей с человеческими названиями (`label`) и описаниями (`description`). Фильтрация и сортировка по новым camelCase-именам работают. При записи (`create`/`update`) по-прежнему принимаются оба регистра — прежние вызовы с верхним регистром в теле не ломаются.

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

Читать поля ответа по camelCase-именам: `config.crmCreate` вместо `config.CRM_CREATE`. Соответствие имён — прямая транслитерация из верхнего регистра в camelCase (`WELCOME_BOT_ID` → `welcomeBotId`, `WORKTIME_TO` → `workTimeTo`, `LINE_NAME` → `name`). Полный перечень новых имён — в справке `/fields`.

### NEW-0710-22: Добавлен GET /v1/warehouses/fields — схема полей склада

Появился эндпоинт [GET /v1/warehouses/fields](/docs/entities/warehouses/list), возвращающий схему 19 полей склада: для каждого поля — тип (`type`), признак «только для чтения» (`readonly`), человеческое название (`label`) и описание (`description`). Склады — кастомный роут (без сущностной схемы), поэтому раньше у них не было справки полей, которая есть у автогенерируемых сущностей. Ответ — `{ success: true, data: { fields: { … } } }`. Требуется скоуп `catalog`.

### FIX-0710-23: публикация приложения восстанавливается при рассинхроне плейсмента

**Было**

При публикации ([POST /v1/apps/:id/publish](/docs/apps)) или обновлении плейсментов ([PATCH /v1/apps/:id](/docs/apps)), если плейсмент был зарегистрирован на стороне Bitrix24, но отсутствовал в приложении (дрейф после снятия с публикации), привязка падала с ошибкой «Handler already binded» и плейсмент оставался несинхронизированным.

**Стало**

При такой ошибке платформа один раз снимает устаревшую привязку и повторяет её — плейсмент синхронизируется автоматически. Восстановление срабатывает только на подтверждённом конфликте, поэтому «живой» плейсмент никогда не снимается по ошибке; плейсменты, которым нужны непереносимые OPTIONS (чат-виджеты, фоновый обработчик), из авто-восстановления исключены и по-прежнему сообщают предупреждение.

### FIX-0710-24: storage: sha256 объекта заполняется при прямой загрузке

**Было**

Поле `sha256` в ответе на загрузку объекта хранилища всегда было `null` для пользовательских объектов, хотя схема описывала его как «вычисляется при загрузке».

**Стало**

При прямой загрузке ([POST /v1/storage/objects/upload](/docs/storage), файлы до 10 МБ) `sha256` теперь содержит SHA-256-хэш содержимого объекта. По нему можно проверять целостность и находить дубликаты (одинаковое содержимое — одинаковый хэш). Для presigned- и multipart-загрузок байты идут напрямую в хранилище мимо платформы, поэтому там `sha256` пока остаётся `null`.

### FIX-0710-25: поле pacing.active в GET /v1/ai/quota больше не сообщает об активном лимите при нулевой квоте

**Было**

При включённом равномерном расходовании на портале с нулевой месячной квотой (жёсткая блокировка через переопределение `monthlyVibes = 0` или ещё не инициализированный расход) поле `data.pacing.active` возвращало `true` — хотя отказ `429 ai_pacing_limited` в этом состоянии структурно невозможен: запросы отклоняются месячным лимитом, а не оконным.

**Стало**

`data.pacing.active` возвращает `true` только когда превышение дневного или недельного окна действительно может привести к `429 ai_pacing_limited`. При нулевой квоте поле честно отдаёт `false`. Форма ответа не изменилась; клиентам, строившим backoff-логику по `active`, действий не требуется — сигнал стал точнее.
