Событие onRestServiceBuildDescription модуля rest — штатный способ добавить свои методы в REST API Битрикса. Через него описывают скоупы, привязывают колбэки-обработчики и получают полноценные endpoint'ы, доступные по вебхукам и OAuth наравне с системными.
Зачем это событие
Модуль rest строит карту доступных методов, опрашивая обработчики события onRestServiceBuildDescription. Каждый обработчик возвращает описание своих скоупов и методов, а ядро объединяет их в единый реестр. Так ваши методы становятся вызываемыми через тот же механизм авторизации, что и системные crm.* или lists.*.
Подход даёт три преимущества перед самописным endpoint'ом:
- единая авторизация — вебхуки и OAuth-токены работают из коробки;
- единый формат ответов и ошибок, привычный клиентам REST;
- методы видны в общем списке скоупов приложения.
rest. Перед регистрацией обработчика убедитесь в его наличии через \Bitrix\Main\Loader::includeModule('rest').Регистрация обработчика
Обработчик подключают в init.php или в файле установки модуля. Обратите внимание на регистр имени события — оно начинается с маленькой буквы:
use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler(
'rest',
'onRestServiceBuildDescription',
['\Vendor\Api\RestService', 'onBuildDescription']
);
В отличие от большинства событий, здесь обработчик ничего не меняет по ссылке, а возвращает массив-описание. Ядро соберёт результаты всех обработчиков в общую карту методов.
Описание скоупов и методов
Возвращаемая структура — двухуровневый массив: скоуп → методы. Ключ метода становится его именем в REST (через точку), значение указывает на колбэк:
public static function onBuildDescription(): array
{
return [
'myshop' => [
'myshop.stock.get' => [
'callback' => [__CLASS__, 'getStock'],
'options' => [],
],
'myshop.stock.update' => [
'callback' => [__CLASS__, 'updateStock'],
],
],
];
}
| Уровень | Значение |
|---|---|
| Ключ 1 уровня | Имя скоупа (myshop) |
| Ключ 2 уровня | Полное имя метода (myshop.stock.get) |
callback | Вызываемый обработчик метода |
options | Доп. опции: приватность, требование лицензии и др. |
Имя скоупа лучше делать уникальным префиксом проекта, чтобы не пересечься с системными и сторонними методами.
Сигнатура колбэка метода
Колбэк получает три аргумента: параметры запроса, объект навигации и экземпляр сервера. То, что колбэк вернёт, станет содержимым поля result в ответе REST:
use CRestServer;
public static function getStock($query, $n, CRestServer $server)
{
$query = array_change_key_case($query, CASE_UPPER);
$productId = (int)($query['PRODUCT_ID'] ?? 0);
// ... бизнес-логика ...
return [
'PRODUCT_ID' => $productId,
'QUANTITY' => 42,
];
}
$query— массив входных параметров запроса;$n— служебный объект навигации/пагинации;$server—CRestServer, через него доступны имя метода, скоуп и данные авторизации.
array_change_key_case() и валидируйте типы — не доверяйте внешним данным.Обработка ошибок
Для корректных ошибок REST не возвращайте свой массив с текстом, а бросайте специальное исключение \Bitrix\Rest\RestException — ядро само сформирует правильный HTTP-статус и тело ответа с error и error_description:
use Bitrix\Rest\RestException;
if ($productId <= 0) {
throw new RestException(
'Не передан PRODUCT_ID',
'MYSHOP_BAD_REQUEST',
CRestServer::STATUS_WRONG_REQUEST
);
}
Первый аргумент — человекочитаемое описание, второй — машинный код ошибки, третий — HTTP-статус из констант CRestServer (например, STATUS_FORBIDDEN, STATUS_NOT_FOUND). Клиент получит единообразный ответ, как и для системных методов.
Права, скоупы и безопасность
Регистрация метода не отменяет проверок доступа. Несколько правил, без которых интеграцию нельзя выпускать в прод:
- проверяйте права текущего контекста внутри колбэка — REST-вызов может идти от вебхука с ограниченным набором прав;
- подключайте нужные модули через
Loader::includeModule()в начале колбэка, а не полагайтесь на глобальное состояние; - валидируйте и приводите типы всех входных параметров — SQL и iblock-запросы не должны получать сырые данные клиента;
- для методов на запись используйте отдельный скоуп, чтобы вебхуки на чтение не могли менять данные.
Итог
Через onRestServiceBuildDescription собственные методы встраиваются в REST API Битрикса как родные: единая авторизация, формат ответов и ошибок. Ключевое — вернуть корректное описание скоупов и колбэков, нормализовать входные данные, бросать RestException для ошибок и не забывать про проверку прав внутри метода.
Когда REST-слой вырастает в полноценный интеграционный контур для мобильного приложения, B2B-портала или обмена с внешними системами, мы в B2Bsite проектируем его с версионированием, документацией и безопасностью, чтобы API оставалось стабильным по мере роста нагрузки и числа потребителей.
Частые вопросы
Чем регистрация через событие лучше самописного endpoint?
Метод получает единую авторизацию Битрикса (вебхуки и OAuth), стандартный формат ответов и ошибок и попадает в общий список скоупов. Самописный endpoint пришлось бы защищать и описывать вручную.
Почему имя события пишется с маленькой буквы?
onRestServiceBuildDescription исторически объявлено именно так в модуле rest. Регистр имени события важен — при addEventHandler указывайте его точно, иначе обработчик не сработает.
Что должен возвращать обработчик события?
Двухуровневый массив: скоуп в качестве ключа первого уровня и внутри него методы с указанием callback и опций. Ядро объединит описания всех обработчиков в общий реестр.
Какие аргументы получает колбэк метода?
Три: массив параметров запроса $query, служебный объект навигации $n и экземпляр CRestServer $server. Возвращённое значение станет полем result в ответе.
Как правильно вернуть ошибку клиенту?
Бросьте \Bitrix\Rest\RestException с описанием, машинным кодом и HTTP-статусом из констант CRestServer. Ядро сформирует стандартный ответ с error и error_description.
Отменяет ли скоуп проверку прав?
Нет. Скоуп лишь группирует методы и определяет, что разрешено токену. Проверку прав на конкретные данные нужно выполнять внутри колбэка.
Нужно ли подключать модули внутри колбэка?
Да, вызывайте Loader::includeModule для нужных модулей в начале метода. Не полагайтесь на то, что они уже подключены глобально в контексте REST-запроса.
Как избежать конфликта имён методов?
Используйте уникальный префикс скоупа под свой проект, например myshop, и стройте имена методов через точку от него. Это исключит пересечение с системными и сторонними методами.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.