← К документации

REST

Входящие вебхуки

Серверный POST-запрос с обработкой транспорта, HTTP-статуса, JSON и ошибки REST.

Из чего состоит адрес

Базовый URL входящего вебхука имеет вид https://example.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE/. Хук работает с правами владельца и выданными скоупами. Код в пути — секрет; его нельзя публиковать в исходниках приложения или логах.

Для примера сохраните базовый URL в серверной переменной окружения BITRIX24_WEBHOOK_BASE. Адрес берётся из вашей конфигурации, а не из запроса посетителя.

Минимальный серверный клиент

Требуется PHP 7.3+ с cURL. Функция возвращает весь ответ, поэтому рядом с result доступны данные пагинации. Пустые параметры отправляются JSON-объектом.

<?php

function callWebhook(string $webhook_base, string $method, array $parameters): array {
    if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+$/D', $method)) {
        throw new InvalidArgumentException('Некорректное имя метода');
    }
    $url_parts = parse_url($webhook_base);
    if (!is_array($url_parts) || ($url_parts['scheme'] ?? '') !== 'https'
        || empty($url_parts['host']) || isset($url_parts['query'])
        || isset($url_parts['fragment']) || isset($url_parts['user'])
    ) {
        throw new InvalidArgumentException('Нужен HTTPS URL вебхука из закрытой конфигурации');
    }
    $handle = curl_init(rtrim($webhook_base, '/') . '/' . $method . '.json');
    curl_setopt_array($handle, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
        CURLOPT_POSTFIELDS => json_encode((object) $parameters, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
    ]);
    $body = curl_exec($handle);
    $errno = curl_errno($handle);
    $status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
    curl_close($handle);
    if ($body === false) {
        throw new RuntimeException('Ошибка транспорта cURL: ' . $errno);
    }
    if ($status < 200 || $status >= 300) {
        throw new RuntimeException('REST вернул HTTP ' . $status);
    }
    $response = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
    if (!is_array($response)) {
        throw new RuntimeException('Ожидался JSON-объект');
    }
    if (array_key_exists('error', $response)) {
        throw new RuntimeException('REST: ' . (string) $response['error']);
    }
    if (!array_key_exists('result', $response)) {
        throw new RuntimeException('В ответе нет result');
    }
    return $response;
}

$webhook_base = (string) getenv('BITRIX24_WEBHOOK_BASE');
$response = callWebhook($webhook_base, 'user.current', []);
$user_id = (int) ($response['result']['ID'] ?? 0);

Клиент не записывает ответ или URL в журнал. На ошибке HTTP он сообщает статус; тело для дополнительной диагностики следует разбирать отдельно в закрытом обработчике, без токенов и персональных данных.

Что означает успешный HTTP-ответ

HTTP 200 ещё не означает успех метода. Нужно разобрать JSON и проверить error; неверный JSON нельзя превращать в пустой успешный результат. Значение result: false допустимо для некоторых методов и не равно отсутствию ключа.

После таймаута операция записи могла выполниться на портале. Не повторяйте создание вслепую: сначала найдите результат по внешнему ключу. Код выше намеренно не делает автоматических повторов.

Границы примера

Это клиент классического REST. REST 3.0 имеет отдельный маршрут и контракт ответа. Доступность метода также зависит от скоупа, пользователя, тарифа и версии коробки.

Генератор запросов · Пагинация

Источники