Пять вещей, которые меня удивили в Bitrix REST API, когда я пошёл в headless
Я провёл с Bitrix REST API больше времени, чем планировал. Не потому что API плохой. А потому что документация описывает синтаксис, но молчит про поведение.
Когда идёшь в первый headless-проект на Bitrix, читаешь официальные доки — и думаешь, что понял. Структура методов ясная. Авторизация описана. Pagination есть. Всё выглядит управляемо.
А потом начинается production.
Вот пять вещей, которые я бы хотел знать до того, как потратил несколько недель на debugging.
Почему документация Bitrix REST API — только половина правды
Bitrix REST API работает. Это важно сказать честно. Для типичных задач — читать товары, оформить заказ, получить статус — всё работает как задокументировано.
Проблема начинается на пересечении нескольких условий: большой каталог, параллельные запросы, авторизация под нагрузкой, составные страницы. В этих сценариях поведение API отличается от того, что написано в доках — не потому что там ошибки, а потому что эти кейсы просто не описаны.
Проект 28 000 SKU дал мне этот опыт в полном объёме. Каждый из пяти сюрпризов ниже — не теоретический.
Сюрприз 1: пагинация инфоблоков и «исчезающие» элементы
Bitrix REST API для инфоблоков использует cursor-based пагинацию через параметр start. Это числовой offset — не настоящий курсор.
Типичный вызов:
lists.element.get?IBLOCK_ID=21&start=50
Проблема: offset-пагинация нестабильна при параллельных обновлениях каталога. Если между запросами страниц 1 и 2 изменился хотя бы один элемент, часть записей сдвинется — и вы получите дубликаты или пропуски.
Когда мы строили полный индекс каталога в Elasticsearch, первые прогоны давали нестабильное количество элементов. Разброс — от 3 до 40 записей за прогон. Причина нашлась в логах: менеджеры обновляли цены прямо во время индексации.
Решение, которое сработало: запускать индексацию ночью в maintenance window, или брать snapshot через экспорт и индексировать из него. Для real-time синхронизации — webhook + очередь, не повторный full scan.
Сюрприз 2: авторизация — когда OAuth ломается под нагрузкой
Bitrix поддерживает несколько схем авторизации для REST API: OAuth 2.0, серверный токен приложения, «пользовательский» токен. В тестах все три работают. В production под нагрузкой картина другая.
OAuth access token живёт 1 час. Если refresh происходит в момент параллельных запросов — часть из них может получить 401 до завершения обновления токена. У нас это проявлялось как случайные 5-секундные провалы в API-ответах примерно раз в час.
Проблема воспроизводилась только под нагрузкой (50+ параллельных запросов к API). В тестовом окружении с одним потоком — никогда.
Перешли на серверный токен приложения для server-to-server интеграции. Он не истекает, не требует refresh, не зависит от сессии пользователя. OAuth оставили только там, где нужны права от имени конкретного человека.
Одна вещь, которую документация не предупреждает: токен приложения работает только пока приложение установлено и активно в Bitrix. Если его деактивировали в панели — API перестаёт отвечать без каких-либо ошибок в логах Next.js. Ошибка появляется только на стороне Bitrix.
Сюрприз 3: select: ["*"] — это ловушка
Bitrix REST API позволяет передать select: ["*"] чтобы получить все поля элемента. Логично, удобно — и медленно.
При select: ["*"] Bitrix возвращает абсолютно все поля, включая кастомные свойства инфоблока, которых может быть 40-60 штук. Каждое свойство — отдельный JOIN в базе данных. Для каталога в 28 000 SKU с 47 свойствами это означало 47 дополнительных JOIN на каждую страницу запроса.
Разница в latency была примерно в 4 раза. Запрос с select: ["*"] — 1.8 секунды. Запрос с явно перечисленными 12 нужными полями — 0.45 секунды.
Правило, которое я ввёл: никакого select: ["*"] в production-интеграции. Всегда явный список полей, который документируется как часть API-контракта между Bitrix и Next.js. Если нужно добавить поле — это изменение в контракте, а не тихая правка select.
Сюрприз 4: рейт-лимиты при cold start каталога
Bitrix REST API имеет рейт-лимиты. Для локального API (запросы с того же сервера, где стоит Bitrix) лимиты менее строгие, но они есть. Для внешних запросов — стандартно 2 запроса в секунду на Bitrix24, на коробочном Bitrix — зависит от настроек.
Cold start каталога — первый полный импорт при развёртывании headless-фронта — это тысячи запросов за короткое время. При 28 000 SKU и постраничном чтении по 50 элементов — 560 запросов только на базовые данные, плюс ещё столько же для свойств.
Наивный код без ограничений получал 429 ошибки примерно на третьей минуте. API не блокировал насовсем — просто добавлял задержку. Но это ломало наш CI/CD пайплайн, который ждал завершения импорта.
Решение: экспоненциальный backoff + жёсткий rate limit на уровне импортёра (не больше 1 запроса в 600 мс для внешних запросов). Для production-синхронизации — очередь с контролем скорости, не прямые parallel fetch.
Сюрприз 5: REST API и составные страницы не дружат
Типичная страница товара в e-commerce — это не один объект. Это SKU из инфоблока, цена из прайс-листа, остатки со складов, связанные товары, отзывы. В Bitrix монолите всё это собирается одним запросом через D7 ORM с JOIN. В headless архитектуре — это 5-7 отдельных REST-запросов.
Проблема: нет batch endpoint'а. Bitrix REST API не поддерживает мультизапрос «дай мне всё для страницы товара одним вызовом». Есть метод batch для Bitrix24 Cloud, но на коробочном Bitrix он работает иначе и не объединяет ответы транзакционно.
Результат: параллельные запросы с клиента или с SSR-слоя Next.js. 7 параллельных запросов по 200 мс каждый = 200 мс суммарно (если сеть хорошая). Но на практике часть запросов имеет разную latency, и TTI страницы получается хуже, чем ожидаешь.
Выход — агрегирующий слой на сервере. Next.js route handler собирает все данные для страницы, кэширует результат через ISR, и фронт получает одну готовую структуру. Это переносит нагрузку на сервер, но даёт контроль над latency и кэшированием. Подробнее про кэш-инвалидацию через ISR — в статье Cache Invalidation in Headless.
Что из этого решается кодом, а что — архитектурой
Если сложить пять сюрпризов вместе, видна закономерность.
Сюрпризы 3 и 4 (скрытые поля и рейт-лимиты) — это проблемы кода. Явный select и rate limiting на уровне импортёра — решается за день.
Сюрпризы 1 и 5 (нестабильная пагинация и составные страницы) — это архитектурные решения. Их нельзя поправить одной функцией. Нужен агрегирующий слой, очередь синхронизации, продуманная стратегия кэширования.
Сюрприз 2 (авторизация под нагрузкой) — посередине. Переход на серверный токен — это правка кода, но осознание, почему OAuth не подходит для server-to-server — это архитектурное решение.
Прежде чем начинать headless-проект на Bitrix, стоит проверить API-слой заранее. Что именно проверять до запуска — читайте в этой статье.
Bitrix REST API — рабочий инструмент. Но он оптимизирован под монолитный сценарий. Headless требует от него другого — и это другое нужно проектировать, а не обнаруживать в production.