Для 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.