01 01234567890 01234567890

Работа со смарт-процессами через API Битрикс24: создание и управление объектами

Битрикс24 API 13 сентября 2026
~8 минут чтения 11 758 символов 24 просмотра

Как создать собственный тип объекта в CRM и управлять им через REST: от crm.type.add до обновления стадии, с разбором частых ошибок

Стандартных сделок и лидов в Битрикс24 хватает для продаж, но как только у бизнеса появляется процесс вроде «заявки на ремонт», «аренда оборудования» или «договоры на согласовании» — стандартные сущности начинают трещать по швам: либо приходится впихивать чужой процесс в воронку сделок, либо заводить кучу пользовательских полей, в которых никто не разбирается. Смарт-процессы (Smart Process Automation, SPA) решают именно это: позволяют создать собственный тип объекта со своими полями, стадиями и правами доступа, и управлять им через API.

В статье разберём, как создавать и работать с объектами смарт-процессов через API Битрикс24: от создания самого типа процесса до CRUD-операций (create, read, update, delete — создание, чтение, обновление, удаление) с объектами через REST. Материал для разработчиков, которые уже работают с REST API Битрикс24 и которым нужно завести собственный тип объекта, а затем управлять им программно.

Что понадобится перед началом

  • Доступ к порталу Битрикс24 с правами администратора (создание типов смарт-процессов требует прав на CRM)
  • Тариф Битрикс24, поддерживающий смарт-процессы (доступны начиная с определённых платных тарифов, на бесплатном тарифе функция может быть недоступна или ограничена)
  • Входящий webhook с правами crm или OAuth-приложение
  • Понимание базовой работы с REST API Битрикс24 (структура запросов, формат ответа)
  • Тестовый портал для отладки, чтобы не создавать мусорные типы процессов в продакшене

Основная часть: создаём и работаем со смарт-процессами

Шаг 1. Создаём тип смарт-процесса через API

Тип процесса (структура — какие поля, стадии, связи с другими сущностями) можно настроить через интерфейс (CRM → Настройки → «Смарт-процессы»), но раз статья про API — создадим его методом crm.type.add.

$webhookUrl = getenv('BITRIX_WEBHOOK_URL');

$payload = [
    'fields' => [
        'title' => 'Аренда оборудования',
        'isStagesEnabled' => 'Y',       // включает работу со стадиями
        'isAutomationEnabled' => 'Y',   // разрешает роботов и триггеры
    ],
];

$ch = curl_init($webhookUrl . 'crm.type.add.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

$entityTypeId = $response['result']['type']['entityTypeId'];

Поле title — единственное обязательное. entityTypeId можно не указывать вообще — Битрикс24 присвоит его автоматически; если нужен конкретный номер, его можно передать явно — он должен попадать в диапазон, отведённый под динамические типы, и быть свободным на портале.

Полученный entityTypeId дальше нужен во всех запросах к этому процессу — сохраните его, а не подбирайте вручную.

Частая ошибка: создают тип процесса прямо в продакшн-портале «на пробу», а потом не могут его удалить без последствий — если в нём уже есть объекты, тип процесса с данными удаляется с потерей информации. Тестируйте структуру на тестовом портале.

Шаг 2. Получаем список типов смарт-процессов через API

Перед тем как создавать объекты, нужно знать точный entityTypeId нужного типа процесса.

// Получаем список всех типов смарт-процессов на портале
$webhookUrl = getenv('BITRIX_WEBHOOK_URL');
$response = file_get_contents($webhookUrl . 'crm.type.list.json');
$types = json_decode($response, true);

foreach ($types['result']['types'] as $type) {
    echo $type['entityTypeId'] . ' — ' . $type['title'] . PHP_EOL;
}

Шаг 3. Создаём объект смарт-процесса через API

Зная entityTypeId, создаём объект методом crm.item.add. Структура запроса похожа на создание лида или сделки, но требует обязательного указания entityTypeId.

function addSmartProcessItem(string $webhookUrl, int $entityTypeId, array $fields): array
{
    $url = $webhookUrl . 'crm.item.add.json';

    $payload = [
        'entityTypeId' => $entityTypeId,
        'fields' => $fields,
    ];

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

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

    return json_decode($response, true);
}

$fields = [
    'title' => 'Аренда экскаватора на 3 дня',
    'opportunity' => 45000, // сумма, если есть денежное поле
    'ufCrm5_equipmentType' => 'Экскаватор', // пользовательское поле, имя зависит от настройки
];

$result = addSmartProcessItem($webhookUrl, $entityTypeId, $fields);
$newItemId = $result['result']['item']['id']; // ID лежит не в result напрямую, а в result.item.id

Частая ошибка: путают имена пользовательских полей. Поля, добавленные через интерфейс к смарт-процессу, получают сгенерированные технические имена вида ufCrm{N}_xxx (или UF_CRM_{N}_xxx, если передать параметр useOriginalUfNames: true), и угадать их нельзя — нужно смотреть точное имя через метод crm.item.fields с указанием entityTypeId.

Вторая частая ошибка — берут код из примеров для crm.lead.add (там ID лида возвращается прямо в result) и пытаются так же читать ID из ответа crm.item.add. У универсальных crm.item.* методов структура ответа другая — объект целиком лежит в result.item, а не в result.

Шаг 4. Получаем список полей объекта

Чтобы не угадывать технические имена полей, всегда сначала запрашиваем структуру.

$response = file_get_contents($webhookUrl . 'crm.item.fields.json?entityTypeId=' . $entityTypeId);
$fieldsInfo = json_decode($response, true);

foreach ($fieldsInfo['result']['fields'] as $name => $info) {
    echo $name . ' — ' . ($info['title'] ?? '') . PHP_EOL;
}

Шаг 5. Читаем и обновляем объекты

Получить объект по ID — метод crm.item.get, обновить — crm.item.update. Оба требуют entityTypeId и id объекта.

Перед обновлением стадии нужно знать её точный код — получаем его через crm.status.list, а не придумываем по шаблону.

$statusResponse = file_get_contents($webhookUrl . "crm.status.list.json?filter[ENTITY_ID]=DYNAMIC_{$entityTypeId}_STAGE");
$stages = json_decode($statusResponse, true)['result'];
$stageId = $stages[0]['STATUS_ID']; // берём конкретный нужный код из списка, а не первый попавшийся
// Чтение объекта
$response = file_get_contents($webhookUrl . "crm.item.get.json?entityTypeId={$entityTypeId}&id=42");
$item = json_decode($response, true)['result']['item']; // объект снова лежит в result.item

// Обновление стадии объекта
$updatePayload = [
    'entityTypeId' => $entityTypeId,
    'id' => 42,
    'fields' => ['stageId' => $stageId], // код стадии, полученный на предыдущем шаге
];

$ch = curl_init($webhookUrl . 'crm.item.update.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($updatePayload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$updated = json_decode(curl_exec($ch), true);
curl_close($ch);

if (isset($updated['error'])) {
    // ошибку возвращает не HTTP-код, а тело ответа — проверять нужно именно его
    throw new RuntimeException($updated['error_description'] ?? $updated['error']);
}

Частая ошибка: при обновлении стадии передают просто название стадии («Завершено»), а не её технический код. Код стадии для конкретного смарт-процесса нельзя угадать по шаблону — его нужно получить через метод crm.status.list (или crm.dealcategory.stage.list для процессов со стадиями в стиле сделок) с фильтром по entityId, соответствующему вашему типу процесса, и использовать ровно ту строку, которую вернул API.

Шаг 6. Удаляем объекты и обрабатываем связанные данные

Удаление — метод crm.item.delete. Перед удалением стоит учесть, что у объекта могут быть связанные сущности (например, привязанные контакты или товары) — они не удаляются автоматически и могут остаться «осиротевшими» записями.

$deletePayload = [
    'entityTypeId' => $entityTypeId,
    'id' => 42,
];

$ch = curl_init($webhookUrl . 'crm.item.delete.json');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($deletePayload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$deleted = json_decode(curl_exec($ch), true);
curl_close($ch);

Шаг 7. Настраиваем обработку событий смарт-процесса через webhook

Как и для стандартных CRM-сущностей, для смарт-процессов можно настроить исходящие webhook на события (создание, изменение стадии). Имя события строится из общего префикса для динамических объектов и номера типа процесса — то есть у каждого смарт-процесса оно своё, и подписываться нужно именно на «своё» имя, а не на общее. Как устроен обработчик такого события, разбирали в статье про настройку вебхуков.

Частые ошибки и как их избежать

Ошибка: жёстко прописывают entityTypeId в коде как магическое число без комментария, вместо того чтобы получить его через crm.type.add или crm.type.list и сохранить. Через полгода никто не помнит, что означает конкретное число, особенно если на портале несколько типов смарт-процессов. Решение: хранить соответствие entityTypeId → название процесса в конфиге или константах с понятными именами, а не вписывать число напрямую в вызовы API.

Ошибка: не проверяют права доступа при создании объекта от имени пользователя (не через входящий webhook с административными правами). Если у пользователя, от имени которого выполняется запрос, нет прав на этот смарт-процесс, API вернёт ошибку доступа, которую легко спутать с ошибкой в данных. Решение: при отладке сверять права через интерфейс CRM, прежде чем искать ошибку в коде.

Ошибка: считают смарт-процессы полной заменой кастомной таблицы в базе данных. Смарт-процессы хороши для CRM-логики (воронки, стадии, права доступа), но для больших объёмов данных без отношения к продажам (например, логи или служебные таблицы) использовать D7 ORM или собственную БД эффективнее.

Из практики А2

Смарт-процессы чаще всего заводят не там, где надо. Если у сущности нет своей воронки и стадий — это не смарт-процесс, а справочник, и жить ему лучше в отдельной таблице: карточка со стадиями, по которым объект никогда не движется, только мешает пользователям.

Технические имена пользовательских полей — главный источник потерянного времени. Они генерируются при создании поля, отличаются между порталами, и код, написанный на тестовом портале, на боевом просто не находит поля. Единственный надёжный путь — на старте запросить crm.item.fields для нужного типа и держать соответствие «понятное имя → техническое» в конфиге проекта.

Ещё одна ловушка — ответ универсальных методов. Разработчик, привыкший к crm.lead.add, читает result и получает null, потому что у crm.item.* объект лежит на уровень глубже. Ошибка выглядит как «API не работает», хотя объект создан.

И про удаление: типы смарт-процессов удаляются вместе с данными, а восстановить их из интерфейса нельзя. Экспериментировать со структурой стоит на тестовом портале, даже когда кажется, что «просто попробуем и удалим».

Итог

После этой инструкции у вас есть рабочий подход к созданию собственного типа процесса в Битрикс24 и управлению его объектами через API — без искусственной подгонки под стандартные лиды и сделки. Если на каком-то шаге застряли — опишите ситуацию в комментарии или напишите нам напрямую.

Денис

Денис

CRM-интегратор

Знаю про CRM-системы и Битрикс24 всё

Остались вопросы? Мы можем помочь!

Сколько стоит продвижение сайта: из чего складывается цена
Следующая статья 11.09.2026