Особенности вызовов REST при изменении адреса Битрикс24

Выберите инструмент для разработки с AI-агентом:

  • используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
  • используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации

Облачный Битрикс24 получает сгенерированный адрес вида b24-xxxxxx.bitrix24.ru. Администратор может заменить его на другой адрес или подключить свой домен, и тогда адрес, записанный в интеграции, перестает быть актуальным.

Запросы по старому адресу не пропадают: Битрикс24 отвечает редиректом — статусом 301 или 302 и заголовком Location с новым адресом. Ошибка появляется на стороне интеграции: при редиректе HTTP-клиент может повторить POST-запрос как GET и потерять параметры метода.

Все дальнейшее относится к облачному Битрикс24. Адрес коробочного Битрикс24 меняет администратор компании, а переадресацию со старого адреса настраивают на веб-сервере.

Редирект обрабатывают в своем коде, а актуальный адрес берут из авторизационных данных. Порядок смены адреса на стороне пользователя описан в статье Как изменить адрес Битрикс24 или подключить свой домен.

Что происходит с вызовом после смены адреса

Поведение зависит от того, как переданы параметры метода.

Способ передачи параметров

Что происходит при редиректе

GET, параметры в строке запроса

HTTP-клиент повторяет запрос по новому адресу вместе со строкой запроса. Метод выполняется, разницы в ответе не видно

POST, параметры в теле запроса

HTTP-клиент может повторить запрос методом GET. Тело запроса теряется: метод получает вызов без параметров

Поведение при редиректе задает не Битрикс24, а настройки HTTP-клиента. Например, библиотека curl с включенной опцией CURLOPT_FOLLOWLOCATION по умолчанию меняет метод запроса на GET. Менять метод клиент может на статусах 301 и 302, а на 307 и 308 он должен повторить исходный запрос вместе с телом.

Потерянное тело видно по ответу: метод сообщает о недостающих данных, а не об ошибке авторизации или неверном адресе. Вызов crm.deal.get без параметра id возвращает статус 400 и описание ошибки:

{
    "error": "",
    "error_description": "ID is not defined or invalid."
}

Если вызовы перестали работать все сразу, начните проверку с адреса: сравните адрес в коде с текущим адресом Битрикс24.

Примечание

Редирект после смены адреса обрабатывает B24PySDK: он сам переключается на новый домен, а на это действие можно подписаться сигналом. Для остальных SDK Битрикс24 обработка редиректа не описана — проверьте поведение своей библиотеки.

Откуда взять актуальный адрес

Отдельного события о смене адреса в REST нет — Битрикс24 не уведомляет приложение о переезде. Новый адрес приложение получает вместе с обычными данными авторизации.

Приложение

member_id — постоянный идентификатор Битрикс24, он приходит приложению в авторизационных данных и при смене адреса не меняется. По нему приложение узнает свой Битрикс24 и после смены адреса, а обновить нужно только адрес, по которому уходят вызовы методов.

Общий путь для вызовов методов приходит в поле client_endpoint, например https://mycompany.bitrix24.ru/rest/. Поле есть в двух местах:

  • в ответе сервера авторизации при выдаче и продлении токенов — порядок описан в статье Полный протокол авторизации OAuth 2.0
  • в параметрах auth при вызове обработчика события, рядом с полем domain — адресом Битрикс24, на котором произошло событие

Храните значение client_endpoint по ключу member_id и перезаписывайте его при каждом новом наборе токенов. Тогда приложение обращается по адресу из последних авторизационных данных, а не по адресу, записанному в коде.

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

Адрес встроен в URL вебхука вида https://mycompany.bitrix24.ru/rest/1/8g9l071eismy9q2l/crm.deal.add, и нового адреса входящий вебхук не присылает. Новый адрес берут одним из двух способов:

  • из заголовка Location в ответе с редиректом. Заголовок доступен, только если клиент не следует за редиректом сам — как в примерах ниже
  • из настроек входящего вебхука. Откройте свой вебхук и скопируйте URL заново — в нем уже будет новый адрес

Важно

URL вебхука содержит секретный код, в примере выше — 8g9l071eismy9q2l. Он дает доступ к данным Битрикс24 в рамках выбранных scope и прав создавшего вебхук сотрудника. Не публикуйте URL целиком и не пишите его в логи.

Как обработать редирект в своем коде

Есть два подхода: обработать редирект вручную или разрешить HTTP-клиенту повторять POST автоматически. По умолчанию выбирайте ручную обработку — она не зависит от языка и библиотеки и дает новый адрес, чтобы сохранить его у себя.

Запретить редирект и повторить запрос вручную

Запретите HTTP-клиенту следовать за редиректом, проверьте статус ответа, возьмите новый адрес из заголовка Location и повторите тот же POST-запрос с теми же параметрами.

import requests

url = "https://mycompany.bitrix24.ru/rest/1/8g9l071eismy9q2l/crm.deal.add"
params = {"fields": {"TITLE": "Новая сделка"}}

response = requests.post(url, json=params, allow_redirects=False)

if response.status_code in (301, 302):
    url = response.headers["Location"]
    response = requests.post(url, json=params, allow_redirects=False)

    endpoint = url.split("/rest/")[0] + "/rest/"
    # сохраните endpoint на своей стороне

print(response.json())
$url = 'https://mycompany.bitrix24.ru/rest/1/8g9l071eismy9q2l/crm.deal.add';
$params = ['fields' => ['TITLE' => 'Новая сделка']];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($statusCode === 301 || $statusCode === 302) {
    $url = curl_getinfo($ch, CURLINFO_REDIRECT_URL);
    curl_setopt($ch, CURLOPT_URL, $url);
    $response = curl_exec($ch);

    $endpoint = explode('/rest/', $url)[0] . '/rest/';
    // сохраните $endpoint на своей стороне
}

curl_close($ch);

print_r(json_decode($response, true));

Заголовок Location содержит и путь вызванного метода, поэтому для повторного запроса адрес используется целиком. Для хранения из него оставляют общий путь до /rest/ — то же значение, что приходит приложению в client_endpoint.

Разрешить повтор POST при редиректе

Опция CURLOPT_POSTREDIR указывает, при каких статусах ответа curl повторяет запрос методом POST, а не GET. Значение собирают из битовых флагов CURL_REDIR_POST_301, CURL_REDIR_POST_302 и CURL_REDIR_POST_303. Сумма первых двух равна числу 3 — такая запись тоже встречается. Работает опция только вместе с CURLOPT_FOLLOWLOCATION.

$url = 'https://mycompany.bitrix24.ru/rest/1/8g9l071eismy9q2l/crm.deal.add';
$params = ['fields' => ['TITLE' => 'Новая сделка']];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POSTREDIR, CURL_REDIR_POST_301 | CURL_REDIR_POST_302);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

print_r(json_decode($response, true));

Кода меньше, но интеграция продолжит обращаться по старому адресу и получать лишний редирект при каждом вызове. Новый адрес отдельным полем не приходит — его достают из фактического адреса запроса через curl_getinfo($ch, CURLINFO_EFFECTIVE_URL). Опция специфична для curl: в клиентах без такой настройки, например в библиотеке requests для Python, остается ручная обработка.

Что проверить в интеграции

  1. Общий путь для вызовов вида https://mycompany.bitrix24.ru/rest/ хранится в одном месте, а не записан в нескольких файлах
  2. У приложения это значение обновляется из client_endpoint и хранится по ключу member_id
  3. POST-запросы не теряют тело при редиректе
  4. В логах видно, на какой адрес Битрикс24 и в какой метод ушел запрос и с каким статусом вернулся ответ

Продолжите изучение