Как создать поставщика в CRM
Scope:
crmКто может выполнять методы: чтобы пройти сценарий целиком, нужны оба права — на добавление и на чтение элементов объекта CRM
- crm.item.add — пользователь с правом на добавление элементов объекта CRM
- crm.item.list — пользователь с правом на чтение элементов объекта CRM
- crm.category.list — любой пользователь
Выберите инструмент для разработки с AI-агентом:
- используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
- используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации
Поставщик в Битрикс24 — это контакт или компания CRM из системной воронки с особым кодом:
-
CATALOG_CONTRACTOR_CONTACT— для контакта -
CATALOG_CONTRACTOR_COMPANY— для компании
Отдельного метода для создания поставщика нет. Поставщиком становится контакт или компания с идентификатором системной воронки в поле categoryId. Записать этот идентификатор в код константой нельзя, поэтому сначала запросим его по коду воронки, а потом создадим объект.
В результате сценария в CRM появится контакт в воронке поставщиков, а метод вернет его id. Этот идентификатор нужен методам складского учета. Например, метод catalog.documentcontractor.add привязывает поставщика к складскому документу.
Сценарий состоит из двух шагов.
- Получить
idсистемной воронки поставщиков методом crm.category.list - Создать контакт или компанию методом crm.item.add, передав этот
idв полеcategoryId
Что нужно до начала
-
вебхук создан от имени пользователя, у которого есть право добавлять контакты и компании в CRM
-
в правах вебхука отмечен scope
crm -
в Битрикс24 включен складской учет: системные воронки поставщиков создаются вместе с ним
-
у пользователя вебхука есть доступ к воронке поставщиков: шаг 1 возвращает только видимые ему воронки, а шаг 2 проверяет право добавлять элементы именно в эту воронку
-
путь вебхука дает полный доступ в рамках своего scope. Храните путь в переменной окружения и не публикуйте его в открытом коде
-
вы решили, кого создаете: контакта или компанию. От этого зависят
entityTypeId, код системной воронки и поля названия
Значения для контакта и компании различаются — выберите столбец для своего объекта.
|
Что передаем |
Контакт |
Компания |
|
|
|
|
|
Код системной воронки |
|
|
|
Поля названия |
|
|
Дальше в примерах создается контакт. Что заменить для компании, описано в блоке Что важно учитывать.
1. Получим идентификатор воронки поставщиков
Используем метод crm.category.list с параметрами:
-
entityTypeId— идентификатор типа объекта CRM, обязательный параметр. Укажем3— контакт -
filter[code]— фильтр по коду воронки. УкажемCATALOG_CONTRACTOR_CONTACT. Без фильтра метод вернет все воронки контактов, включая общую
Как использовать примеры в документации
import { B24Hook } from '@bitrix24/b24jssdk'
const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
// B24_HOOK = 'https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/'
const resultCategory = await $b24.actions.v2.call.make({
method: 'crm.category.list',
params: {
entityTypeId: 3, // 3 — контакт
filter: {
code: 'CATALOG_CONTRACTOR_CONTACT' // Код системной воронки поставщиков
}
},
requestId: 'category-list'
});
const categories = resultCategory.getData().result.categories;
const categoryId = categories.length ? categories[0].id : null;
from b24pysdk import BitrixWebhook, Client
client = Client(
BitrixWebhook(
domain="your-domain.bitrix24.com",
webhook_token="user_id/webhook_key",
)
)
# обертка b24pysdk принимает только entity_type_id, поэтому отбираем воронку по коду в ответе
categories = client.crm.category.list(
entity_type_id=3, # 3 — контакт
).response.result["categories"]
contractor_categories = [
category
for category in categories
if category["code"] == "CATALOG_CONTRACTOR_CONTACT"
]
category_id = contractor_categories[0]["id"] if contractor_categories else None
// composer require bitrix24/b24phpsdk:"^3.0"
require_once 'vendor/autoload.php';
use Bitrix24\SDK\Services\ServiceBuilderFactory;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Psr\Log\NullLogger;
$sb = (new ServiceBuilderFactory(new EventDispatcher(), new NullLogger()))
->initFromWebhook('https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/');
// у crm.category.list нет обертки в SDK — вызываем метод напрямую
$result = $sb->core->call(
'crm.category.list',
[
'entityTypeId' => 3, // 3 — контакт
'filter' => [
'code' => 'CATALOG_CONTRACTOR_CONTACT' // Код системной воронки поставщиков
]
]
);
$categories = $result->getResponseData()->getResult()['categories'] ?? [];
$categoryId = $categories[0]['id'] ?? null;
В ответе метод вернет массив categories. Сохраните id первого элемента — его нужно передать в шаг 2. В примере id: 15.
{
"result": {
"categories": [
{
"id": 15,
"name": "Контакты поставщика",
"sort": 500,
"entityTypeId": 3,
"isDefault": "N",
"isSystem": "Y",
"code": "CATALOG_CONTRACTOR_CONTACT"
}
]
},
"total": 1
}
Признак isSystem: Y подтверждает, что воронка создана системой, а не пользователем.
До вызова шага 2 проверьте, что массив categories не пустой. Если вызвать метод crm.item.add без categoryId, ошибки не будет: контакт создастся в общей воронке, но в списке поставщиков его не появится.
2. Создадим поставщика
Используем метод crm.item.add с параметрами:
-
entityTypeId— идентификатор типа объекта CRM, обязательный параметр. Укажем3— контакт -
fields[categoryId]— идентификатор воронки из шага crm.category.list, в примере15. Именно это поле делает контакт поставщиком -
fields[name]иfields[lastName]— имя и фамилия контакта -
fields[fm]— массив мультиполей crm_multifield для телефонов и почты -
fields[comments]— комментарий в карточке
Телефон и почту Битрикс24 хранит не отдельными полями, а мультиполями. Каждый элемент массива fm содержит:
-
typeId— тип мультиполя,PHONEилиEMAIL -
valueType— тип значения, напримерWORKилиMOBILE -
value— само значение
const resultItem = await $b24.actions.v2.call.make({
method: 'crm.item.add',
params: {
entityTypeId: 3, // 3 — контакт
fields: {
name: 'Иван', // Имя
lastName: 'Иванов', // Фамилия
categoryId: categoryId, // Идентификатор воронки из шага 1
fm: [ // Телефоны и почта
{ typeId: 'PHONE', valueType: 'WORK', value: '+7 900 000 00 00' },
{ typeId: 'PHONE', valueType: 'MOBILE', value: '+7 495 111 22 33' },
{ typeId: 'EMAIL', valueType: 'WORK', value: 'supplier@example.ru' }
],
comments: 'Поставщик электроники' // Комментарий
}
},
requestId: 'item-add'
});
const contractorId = resultItem.getData().result.item.id;
item = client.crm.item.add(
entity_type_id=3, # 3 — контакт
fields={
"name": "Иван", # Имя
"lastName": "Иванов", # Фамилия
"categoryId": category_id, # Идентификатор воронки из шага 1
"fm": [ # Телефоны и почта
{"typeId": "PHONE", "valueType": "WORK", "value": "+7 900 000 00 00"},
{"typeId": "PHONE", "valueType": "MOBILE", "value": "+7 495 111 22 33"},
{"typeId": "EMAIL", "valueType": "WORK", "value": "supplier@example.ru"},
],
"comments": "Поставщик электроники", # Комментарий
},
).response.result["item"]
contractor_id = item["id"]
$result = $sb->getCRMScope()->item()->add(
3, // 3 — контакт
[
'name' => 'Иван', // Имя
'lastName' => 'Иванов', // Фамилия
'categoryId' => $categoryId, // Идентификатор воронки из шага 1
'fm' => [ // Телефоны и почта
[ 'typeId' => 'PHONE', 'valueType' => 'WORK', 'value' => '+7 900 000 00 00' ],
[ 'typeId' => 'PHONE', 'valueType' => 'MOBILE', 'value' => '+7 495 111 22 33' ],
[ 'typeId' => 'EMAIL', 'valueType' => 'WORK', 'value' => 'supplier@example.ru' ]
],
'comments' => 'Поставщик электроники' // Комментарий
]
);
$contractorId = $result->item()->id;
В ответе метод вернет объект item с полным набором полей контакта. Ответ сокращен, показаны поля, которые подтверждают результат.
{
"result": {
"item": {
"id": 2643,
"entityTypeId": 3,
"categoryId": 15,
"name": "Иван",
"lastName": "Иванов",
"comments": "Поставщик электроники",
"hasPhone": "Y",
"hasEmail": "Y",
"createdTime": "2026-08-19T14:56:05+03:00",
"createdBy": 1,
"assignedById": 1,
"fm": [
{
"id": 8533,
"valueType": "WORK",
"value": "+7 900 000 00 00",
"typeId": "PHONE"
},
{
"id": 8535,
"valueType": "MOBILE",
"value": "+7 495 111 22 33",
"typeId": "PHONE"
},
{
"id": 8537,
"valueType": "WORK",
"value": "supplier@example.ru",
"typeId": "EMAIL"
}
]
}
}
}
Сохраните id. В примере id: 2643.
Проверим результат
Откройте список контактов в CRM и переключитесь на воронку «Контакты поставщика» — ее название пришло в поле name на шаге 1. Новый контакт «Иван Иванов» появится в этой воронке с телефонами и почтой из запроса. В общей воронке контактов его не будет.
Через REST поставщиков возвращает метод crm.item.list с параметрами:
-
entityTypeId—3для контактов -
filter[categoryId]— идентификатор воронки из шага 1, в примере15 -
filter[id]— идентификатор поставщика из шага 2, в примере2643. Без него метод вернет первую страницу списка поставщиков: если поставщиков много, нового элемента в ней может не оказаться
const checkResult = await $b24.actions.v2.call.make({
method: 'crm.item.list',
params: {
entityTypeId: 3,
filter: { categoryId: categoryId, id: contractorId },
select: ['id', 'name', 'lastName', 'categoryId']
},
requestId: 'item-list'
});
console.dir(checkResult.getData().result.items);
check_result = client.crm.item.list(
3,
filter={"categoryId": category_id, "id": contractor_id},
select=["id", "name", "lastName", "categoryId"],
).response.result["items"]
print(check_result)
$checkResult = $sb->getCRMScope()->item()->list(
3,
[],
['categoryId' => $categoryId, 'id' => $contractorId],
['id', 'name', 'lastName', 'categoryId']
);
print_r($checkResult->getItems());
Сценарий выполнен, если в массиве items есть элемент с id из шага 2, а его categoryId совпадает с идентификатором системной воронки.
{
"result": {
"items": [
{
"id": 2643,
"name": "Иван",
"lastName": "Иванов",
"categoryId": 15
}
]
}
}
Ошибки и диагностика
Если метод вернул ошибку, проверьте данные запроса.
|
Код |
Причина и действие |
|
|
У пользователя вебхука нет права добавлять элементы объекта с этим |
|
|
Вебхук создан от имени внешнего пользователя. Сценарий доступен только сотрудникам Битрикс24 |
|
|
В |
|
|
Неверное значение поля. Две частые причины: недопустимый |
|
|
В множественное поле передан не массив. Проверьте, что |
Поля, которых нет у объекта, метод не считает ошибкой — он их отбрасывает. При неверном наборе полей метод не откажет, а контакт или компания создадутся неполными.
Пустой массив categories в шаге 1 — не ошибка метода. Причин две: в Битрикс24 не включен складской учет, поэтому системных воронок поставщиков нет, либо у пользователя вебхука нет доступа к этой воронке — метод crm.category.list возвращает только те воронки, которые пользователю разрешено читать.
Чтобы различить причины, выполните шаг 1 вебхуком администратора. Если администратор воронку видит, а исходный вебхук нет, дело в правах его пользователя. Если не видит и администратор, складской учет не включен.
Шаг 1 ничего не создает, его можно повторять сколько угодно раз. Если ошибку вернул шаг 2, поставщик не создан: исправьте fields и повторите только этот шаг.
Что важно учитывать
-
чтобы создать поставщика-компанию, замените
entityTypeIdна4, код воронки наCATALOG_CONTRACTOR_COMPANY, а поляnameиlastName— наtitle. МенятьentityTypeIdи код воронки нужно вместе, иначе метод вернет ошибкуCRM_FIELD_ERROR_VALUE_NOT_VALID -
если при переходе на компанию оставить поля контакта, компания все равно создастся, но с автоматическим названием вида «Компания #3009». Подставьте
titleсамостоятельно -
воронку поставщиков нельзя создать самостоятельно: метод crm.category.add запрещает добавление системных воронок
-
метод crm.item.add не проверяет дубликаты. Повторный запуск примера создаст второго поставщика с теми же данными. Перед созданием ищите поставщика методом crm.duplicate.findbycomm по телефону или почте
-
идентификатор воронки различается на разных Битрикс24. Не переносите значение
15из примера в рабочий код, запрашивайте его шагом 1
Пример кода
Скрипт получает идентификатор системной воронки поставщиков и создает в ней контакт. Значения entityTypeId, кода воронки и полей вынесены в переменные — для компании достаточно поменять их в одном месте.
import { B24Hook } from '@bitrix24/b24jssdk'
const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
// B24_HOOK = 'https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/'
const entityTypeId = 3; // 3 — контакт, для компании укажите 4
const categoryCode = 'CATALOG_CONTRACTOR_CONTACT'; // для компании укажите CATALOG_CONTRACTOR_COMPANY
const nameFields = { name: 'Иван', lastName: 'Иванов' }; // для компании укажите { title: 'ООО Электроника' }
async function createContractor() {
try {
const resultCategory = await $b24.actions.v2.call.make({
method: 'crm.category.list',
params: {
entityTypeId: entityTypeId,
filter: { code: categoryCode }
},
requestId: 'category-list'
});
const categories = resultCategory.getData().result.categories;
if (!categories.length) {
console.error('Воронка поставщиков не найдена: проверьте складской учет и доступ пользователя вебхука');
return;
}
const categoryId = categories[0].id;
const resultItem = await $b24.actions.v2.call.make({
method: 'crm.item.add',
params: {
entityTypeId: entityTypeId,
fields: {
...nameFields,
categoryId: categoryId,
fm: [
{ typeId: 'PHONE', valueType: 'WORK', value: '+7 900 000 00 00' },
{ typeId: 'PHONE', valueType: 'MOBILE', value: '+7 495 111 22 33' },
{ typeId: 'EMAIL', valueType: 'WORK', value: 'supplier@example.ru' }
],
comments: 'Поставщик электроники'
}
},
requestId: 'item-add'
});
console.log('Поставщик создан, id:', resultItem.getData().result.item.id);
} catch (error) {
console.error('Поставщик не создан:', error.message);
}
}
createContractor();
from b24pysdk import BitrixWebhook, Client
from b24pysdk.errors import BitrixAPIError
client = Client(
BitrixWebhook(
domain="your-domain.bitrix24.com",
webhook_token="user_id/webhook_key",
)
)
entity_type_id = 3 # 3 — контакт, для компании укажите 4
category_code = "CATALOG_CONTRACTOR_CONTACT" # для компании укажите CATALOG_CONTRACTOR_COMPANY
name_fields = {"name": "Иван", "lastName": "Иванов"} # для компании укажите {"title": "ООО Электроника"}
try:
# обертка b24pysdk принимает только entity_type_id, поэтому отбираем воронку по коду в ответе
categories = client.crm.category.list(
entity_type_id=entity_type_id,
).response.result["categories"]
contractor_categories = [
category
for category in categories
if category["code"] == category_code
]
if not contractor_categories:
print("Воронка поставщиков не найдена: проверьте складской учет и доступ пользователя вебхука")
else:
item = client.crm.item.add(
entity_type_id,
{
**name_fields,
"categoryId": contractor_categories[0]["id"],
"fm": [
{"typeId": "PHONE", "valueType": "WORK", "value": "+7 900 000 00 00"},
{"typeId": "PHONE", "valueType": "MOBILE", "value": "+7 495 111 22 33"},
{"typeId": "EMAIL", "valueType": "WORK", "value": "supplier@example.ru"},
],
"comments": "Поставщик электроники",
},
).response.result["item"]
print(f"Поставщик создан, id: {item['id']}")
except BitrixAPIError as error:
print(f"Поставщик не создан: {error}")
<?php
// composer require bitrix24/b24phpsdk:"^3.0"
require_once 'vendor/autoload.php';
use Bitrix24\SDK\Services\ServiceBuilderFactory;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Psr\Log\NullLogger;
$sb = (new ServiceBuilderFactory(new EventDispatcher(), new NullLogger()))
->initFromWebhook('https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/');
$entityTypeId = 3; // 3 — контакт, для компании укажите 4
$categoryCode = 'CATALOG_CONTRACTOR_CONTACT'; // для компании укажите CATALOG_CONTRACTOR_COMPANY
$nameFields = ['name' => 'Иван', 'lastName' => 'Иванов']; // для компании укажите ['title' => 'ООО Электроника']
try {
// у crm.category.list нет обертки в SDK — вызываем метод напрямую
$resultCategory = $sb->core->call(
'crm.category.list',
[
'entityTypeId' => $entityTypeId,
'filter' => ['code' => $categoryCode]
]
);
$categories = $resultCategory->getResponseData()->getResult()['categories'] ?? [];
if (empty($categories)) {
echo 'Воронка поставщиков не найдена: проверьте складской учет и доступ пользователя вебхука';
return;
}
$categoryId = $categories[0]['id'];
$resultItem = $sb->getCRMScope()->item()->add(
$entityTypeId,
array_merge(
$nameFields,
[
'categoryId' => $categoryId,
'fm' => [
[ 'typeId' => 'PHONE', 'valueType' => 'WORK', 'value' => '+7 900 000 00 00' ],
[ 'typeId' => 'PHONE', 'valueType' => 'MOBILE', 'value' => '+7 495 111 22 33' ],
[ 'typeId' => 'EMAIL', 'valueType' => 'WORK', 'value' => 'supplier@example.ru' ]
],
'comments' => 'Поставщик электроники'
]
)
);
echo 'Поставщик создан, id: ' . $resultItem->item()->id;
} catch (\Throwable $e) {
echo 'Поставщик не создан: ' . $e->getMessage();
}
Продолжите изучение
- Как получить список поставщиков
- Создать новый элемент CRM crm.item.add
- Получить список элементов crm.item.list
- Получить список воронок crm.category.list
- Типы данных и структура объектов в REST API CRM
- Добавить поставщика к документу складского учета catalog.documentcontractor.add
- Получить список привязок поставщиков к документам catalog.documentcontractor.list