Для AI-агентов: markdown этой страницы — /docs-content/changelog/2026-09-04.md индекс документации — /llms.txt
Изменения API: 4 сентября 2026
← Журнал изменений · Сентябрь 2026
NEW-0904-1: асинхронные вызовы инструментов 1С и статус операции
Появились POST /v1/onec/tools/{method}/call и GET /v1/onec/operations/{operationId}. Вызов инструмента создаёт долгоживущую операцию и отвечает 202 с operationId, status и expiresAt, а заголовок Location ведёт на адрес статуса. Статус проходит значения pending, running, succeeded, failed, cancelled, expired; у успешной операции есть result, у неуспешной — безопасный error. Результат хранится 24 часа, затем адрес статуса отвечает 410 ONEC_OPERATION_GONE. Операция доступна только исходному порталу, пользователю и API-ключу. На порталах без включённого коннектора 1С оба адреса отвечают 404.
В этом выпуске поверхность объявлена, но недоступна: механизма связи пользователя с пользователем 1С ещё нет, поэтому любой вызов инструмента отвечает 403 ONEC_USER_NOT_MAPPED, операция не создаётся, и описанный цикл 202 → опрос статуса пройти нельзя. Он заработает с выпуском связывания пользователей; до него интегрировать вызов инструмента не нужно.
NEW-0904-2: признак «Поддерживает BitrixMobile» при регистрации приложения
POST /v1/apps принимает необязательное поле mobile: boolean, по умолчанию false. При true платформа сообщает Битрикс24 признак «Поддерживает BitrixMobile» в момент регистрации приложения на аккаунте, и приложение становится видно в мобильном клиенте. Поле mobile появилось и в объекте приложения — в ответах создания, данных приложения, списка и перепривязки. У приложений, созданных раньше, значение false. Признак задаётся только при создании — PATCH /v1/apps/:id поле mobile не принимает. Если аккаунт регистрирует приложение способом, который признак не передаёт, приложение создаётся с mobile: false, а в warnings ответа создания приходит строка, начинающаяся с mobile:. Прежние запросы без mobile работают как раньше. Подробнее — Создать приложение.
BC-0904-3: код отказа для коробок переименован в SELFHOSTED_NOT_AVAILABLE
Поддержка старого формата до: не предусмотрена
Было
Отказ коробочному Битрикс24 на международной установке приходил кодом
INT_BOX_PARTNER_REQUIRED. Текст отказа объяснял, что доступ даёт партнёрская
лицензия, а по ключу партнёрская пометка не подтверждена, и предлагал
переподключить модуль на портале. Кнопка вела в документацию по подключению
коробки: details.upgradeUrl и alternatives[0].url содержали адрес страницы
/docs/connect-self-hosted-bitrix24.
Стало
Тот же отказ приходит кодом SELFHOSTED_NOT_AVAILABLE. Клиент, разбирающий
ответ по коду, обязан заменить строку — старый код больше не отдаётся ни на
одной поверхности.
Остальное в ответе не изменилось: статус по-прежнему HTTP 402, поле
details.requiredTariffs по-прежнему пустое (отказ не снимается покупкой
тарифа), набор alternatives тот же и в том же порядке.
Изменились текст и адрес кнопки. Текст больше не называет причину отказа и не
просит ничего делать на портале: коробка пока не поддерживается, доступ
открывается постепенно, серверы и данные портала сохраняются. details.upgradeUrl
и alternatives[0].url теперь содержат mailto: адреса поддержки — единственный
адрес, по которому вопрос решается.
FIX-0904-4: подсказки о trial-развёртывании учитывают пригодность galaxy-хоста
Было
GET /v1/me обещал one-shot развёртывание при наличии любого запущенного или спящего galaxy-хоста. Если хост не мог принять приложение, POST /v1/infra/servers отказывал, а подсказка предлагала two-step создание, которое затем упиралось в лимит trial-портала.
Стало
GET /v1/me показывает one-shot путь только когда известный хост выглядит пригодным для размещения, и явно отмечает прогноз как рекомендательный. Авторитетным остаётся POST /v1/infra/servers; если непригодный хост занимает trial-лимит и контроль ограничений включён, ответ больше не советует заведомо недоступное two-step создание.
Влияние на интеграторов
Перед one-shot созданием проверяйте deployment.galaxyApp, а после отказа следуйте error.hint. Для двухшагового пути дополнительно проверяйте capabilities.servers.create.available и выбирайте план из capabilities.servers.create.limits.allowedPlans того же ответа.
FIX-0904-5: карточка каталога не публикуется без привязки к порталу
Было
Публикация могла завершиться со значением SYNCED в b24CatalogSync.status, хотя карточка
каталога оставалась без привязки к отправителю. В таком состоянии уведомление о новой версии
приложения не приходило в чат, а причина не отображалась.
Стало
При вызове POST /v1/infra/servers/:id/b24-catalog/publish
такая карточка больше не создаётся. Для спаренного портала публикация завершается только после
подтверждения привязки карточки к отправителю. Пока подтверждение не получено,
b24CatalogSync.status остаётся не SYNCED, pendingOp остаётся ADD, а lastError называет
причину. Ответ по-прежнему HTTP 200, и успешная публикация возвращает то же самое, что и раньше.
Влияние на интеграторов
Менять запросы не требуется. Если интеграция отслеживает асинхронный статус, сочетание
pendingOp=ADD со статусом, отличным от SYNCED, означает, что карточка ещё не опубликована.
Следует дождаться изменения статуса или показать пользователю значение lastError.
FIX-0904-6: expiresAt предподписанных ссылок равен сроку их подписи
Было
POST /v1/storage/objects/multipart/create считал parts[].expiresAt от запрошенного срока — 24 часа для каждой части, а GET /v1/apps/{id}/sources/{versionId}/download и GET /v1/infra/servers/{id}/sources/{versionId}/download — от фиксированных 30 минут; ссылка из перенаправления GET /v1/storage/objects/{key} документировалась как действующая 10 минут. Отключённый сейчас POST /v1/storage/objects отвечает 503 STORAGE_PRESIGNED_UPLOAD_DISABLED и считал expiresAt так же. Подпись ссылки могла истечь раньше, и хранилище отвечало 403, пока expiresAt ещё оставался в будущем.
Стало
expiresAt в этих ответах берётся из подписи самой ссылки и равен её сроку. Он может быть короче 24 часов сессии составной загрузки и короче 30 минут для ссылок на скачивание; ссылка из перенаправления тоже может истечь раньше 10 минут. Для отключённого POST /v1/storage/objects ничего не меняется: он по-прежнему отвечает 503, а после включения его expiresAt тоже будет браться из подписи. Ответ остаётся HTTP 200, формат полей не меняется.
Влияние на интеграторов
Планируйте отправку и скачивание байтов по expiresAt из ответа и начинайте как можно раньше, а не по сроку сессии uploadId и не по документированным 30 минутам. Клиенты, которые уже ориентировались на expiresAt, ничего не меняют.
FIX-0904-7: латинская локаль называет пробный доступ Битрикс24 словом trial
Было
В латинских локалях пробный доступ Битрикс24 назывался demo, хотя сам Битрикс24 на международной установке называет его trial. Расхождение доходило и до контракта: GET /v1/me отдавал в data.tariff.name значение Demo period, а отказ BY_PAID_ONLY — текст Paid or demo Bitrix24 plan required (Belarus). Внутри одного сценария активации соседние сообщения расходились между собой: одно говорило trial, другое demo про тот же самый доступ.
Стало
Значение тарифа и текст отказа в латинских локалях сведены к слову trial. GET /v1/me отдаёт для этого тарифа Trial period, отказ BY_PAID_ONLY — Paid or trial Bitrix24 plan required (Belarus). Клиент, который сравнивает data.tariff.name или текст отказа со строкой, должен пересмотреть сравнение: сами коды, статусы и поля ответа не изменились, и успешный ответ остаётся успешным. Русская локаль по-прежнему говорит «демо».
Охват этой записи — контракт: значение тарифа и текст отказа. Подсказка возможности apps.bindPlacements того же эндпоинта и статьи документации на момент публикации ещё говорили demo, их перевод вышел позже — запись FIX-0907-11.
FIX-0904-8: батч-подзапрос currencies больше не отдаёт meta.total 0 при непустом data
Было
POST /v1/batch со списочным подзапросом currencies публиковал data.meta.<id>.total: 0 и hasMore: false, хотя в data.results.<id> лежали записи. Метод Битрикс24 crm.currency.list отдаёт конвертный total: 0 рядом с непустым результатом, и на батч-двери этот литеральный ноль принимался за размер коллекции. Клиент, который листает по hasMore, при limit меньше справочника читал первую порцию и считал набор исчерпанным — хвост терялся.
Стало
На считанном подзапросе ноль из конверта больше не побеждает посчитанный размер набора: data.meta.<id>.total и data.totals.<id> показывают размер до клиентского среза, а hasMore считается как offset + returned < total и остаётся true, пока хвост есть. Правило совпало с одиночными эндпоинтами, где эта особенность метода нормализовалась и раньше. Непосчитанный подзапрос (params.withTotal: false, отрицательный params.start) по-прежнему не получает total, а честный пустой справочник по-прежнему отдаёт total: 0. Ответ остаётся HTTP 200.
NEW-0904-9: партнёрское приложение отзывает свой ключ само
Добавлена ручка POST /v1/connect/revoke по RFC 7009: приложение передаёт client_id, client_secret (публичные клиенты — без него) и token и гасит ровно тот ключ, который предъявило. Место в лимите ключей пользователя на портале освобождается сразу, запросы с ключом начинают отвечать 401 KEY_INACTIVE.
Ответ 200 приходит и когда гасить было нечего — на неизвестный токен, на чужой ключ и на уже отозванный, поэтому вызов идемпотентен и по нему нельзя выяснять перебором, живы ли чужие ключи. Отсутствие client_id или token даёт 400 invalid_request, неизвестный клиент или неверный секрет — 401 invalid_client. Ключ, выданный до деактивации клиента, отозвать тоже можно.
Ручка объявлена в документе обнаружения /.well-known/oauth-authorization-server полями revocation_endpoint и revocation_endpoint_auth_methods_supported. До неё отозвать выданный приложению ключ могли только пользователь в разделе «Подключённые приложения», владелец приложения полным удалением клиента и администратор платформы; все три способа работают как раньше.
BC-0904-10: смещение в справочниках статусов и воронок работает на любой глубине
Поддержка старого формата до: не предусмотрена
Было
GET /v1/statuses возвращал одни и те же записи при offset=0,
50, 100 и 300. Метод Битрикс24, на котором работает справочник, отдаёт весь набор одним
ответом и навигацию не применяет, а обёртка резала этот ответ с начала — клиент получал первую
страницу под видом пятидесятой. При смещении, не кратном 50, окно повторялось с периодом 50:
offset=130 отдавал те же записи, что offset=30.
Обход по смещению завершался, но собирал дубли и не доходил до конца справочника: из 267 записей
через список было достижимо около 50, а meta.total при этом называл честные 267. Ошибки не
было ни на одном шаге — все ответы приходили с кодом 200. То же поведение было у
GET /v1/deal-categories и у списочных подзапросов в
POST /v1/batch.
При этом списочный подзапрос батча БЕЗ явного limit вёл себя иначе, чем тот же список за
одиночным запросом: одиночный GET /v1/statuses отдавал 50 записей
по умолчанию, а подзапрос батча — весь справочник целиком, все 267 записей одним ответом.
Стало
Окно [offset, offset + limit) вычисляется на стороне платформы Вайбкод по полному набору, в
том порядке, который вернуло ядро. offset=50&limit=5 отдаёт 51-ю…55-ю записи, limit больше
50 не обрезает хвост, meta.total равен размеру набора с учётом фильтра, а meta.hasMore
становится false на последней странице. Обход по смещению завершается и покрывает каждую
запись ровно один раз. Ответ по-прежнему приходит с кодом 200.
Списочный подзапрос батча теперь подчиняется тому же правилу по умолчанию, что и одиночный
запрос: без явного limit он отдаёт первые 50 записей и hasMore: true, а не весь справочник.
Сортировка и фильтрация по-прежнему выполняются на стороне Битрикс24, поэтому параметр sort
работает как раньше. То же поведение применяется на
POST /v1/statuses/search и в списочных подзапросах
POST /v1/batch.
Влияние на интеграторов
Циклы, которые раньше читали одни и те же записи и не доходили до конца справочника, начинают отдавать полную выборку — для них менять код не нужно.
Менять код нужно в одном случае: подзапрос POST /v1/batch со списком статусов или
воронок, у которого limit не задан явно. Раньше он отдавал весь справочник, теперь — первые 50
записей. Ошибки при этом не будет, ответ придёт с кодом 200 и с hasMore: true, поэтому
недостающие записи потеряются молча, если их не запросить.
Что делать: либо задать limit явно, либо читать справочник постранично, увеличивая offset на
размер страницы, пока meta.hasMore не станет false. Второй вариант предпочтителен — он не
зависит от размера справочника и работает на любом портале.
BC-0904-11: История рабочего дня возвращает смещение часового пояса
Поддержка старого формата до: не предусмотрена
Было
GET /v1/workday/records требовал только timeman. В записи не было обязательного tzOffset, поэтому клиент не мог надёжно получить местное время сотрудника.
Стало
Ручка требует timeman и один из скоупов user_brief, user_basic или user. Каждая запись содержит обязательный tzOffset — смещение в секундах восточнее UTC, вычисленное для момента startTime по историческим правилам текущей IANA-зоны TIME_ZONE из профиля сотрудника. Значение не доказывает, что эта зона была назначена сотруднику при создании записи. Строки startTime и endTime не изменяются. Если текущую зону профиля или смещение по ней нельзя достоверно определить, непустая страница возвращает 502 BITRIX_UNAVAILABLE; смену зоны после создания записи API обнаружить не может и 502 в этом случае не обещает.
Что делать интеграторам
Перевыпустите существующие ключи с timeman и одним user-family скоупом, затем обрабатывайте обязательный tzOffset в ответе GET /v1/workday/records.
NEW-0904-12: асинхронные вызовы учётной системы под связанным пользователем
POST /v1/onec/tools/{method}/call ставит операцию в очередь под активной связью текущего пользователя и требует scope vibe:onec. Тело задаёт только метод, колонки, фильтры и пагинацию: идентификатор и имя пользователя сервер берёт из настроек портала, без клиентского override и без fallback-учётной записи. Ответ 202 содержит operationId, а состояние и результат доступны через GET /v1/onec/operations/{operationId} тому же порталу, пользователю и ключу.
BC-0904-13: Чтение данных по сущностям получило лимит запросов на портал
Поддержка старого формата до: не предусмотрена
Было
Чтение данных по сущностям — список (GET /v1/deals и аналогичные для всех сущностей), поиск (POST /v1/deals/search), агрегаты (POST /v1/deals/aggregate, включая устаревший GET …/aggregate), описание полей (GET /v1/deals/fields), связанные записи (GET /v1/deals/{id}/contacts, …/activities), товарные позиции (GET /v1/deals/{id}/products) — и батч по сущности (POST /v1/deals/batch и аналогичные) принимали запросы без ограничения частоты — при том, что общий POST /v1/batch лимит уже нёс. Один клиент, читающий список чаще примерно десяти раз в секунду, замедлял списки и поиск для всех порталов той же площадки вплоть до обрыва по времени. Запрос HEAD к списку обслуживался как полноценный GET: данные читались целиком, а отдавались только заголовки.
Стало
На каждое такое чтение действует лимит 300 запросов в минуту на портал; все API-ключи одного портала делят один лимит, у каждой сущности и у каждой операции он считается отдельно. При превышении API Вайбкод отвечает 429 RATE_LIMITED с заголовком Retry-After; срока в теле ответа нет — берите его из заголовка. Текущее значение лимита приходит в заголовке x-ratelimit-limit. Батч по сущности ограничен строже — 30 запросов в минуту на портал, как и общий POST /v1/batch: один такой запрос разворачивается в сотни обращений к Битрикс24. Метод HEAD на этих адресах чтением больше не обслуживается — вместо него используйте GET с limit=1. Успешные ответы, коды ошибок и формат данных не изменились.
Что делать интеграторам
Обрабатывать 429 на всех чтениях по сущностям и на батче так же, как на /v1/search и /v1/batch: дождаться срока из Retry-After и повторить. Если лимит срабатывает регулярно — читать реже и крупнее (limit до 5000 за один вызов), кэшировать результаты у себя и не запускать одинаковые чтения параллельно. Если вы проверяли доступность списка методом HEAD — используйте GET с limit=1. Батч разумнее укрупнять, а не учащать: в один запрос помещается до 500 элементов.
NEW-0904-14: счета поддерживают include=deal
GET /v1/invoices/:id, GET /v1/invoices и POST /v1/invoices/search теперь принимают include=deal. Связанная сделка из parentId2 возвращается в _included.deal. Если связи нет, значение равно null.