Для AI-агентов: markdown этой страницы — /docs-content/entities/requisites/aggregate.md индекс документации — /llms.txt

Агрегация реквизитов

POST /v1/requisites/aggregate

Подсчёт количества реквизитов с фильтрацией и группировкой.

Стандартные поля для groupBy:

  • rqInn, rqKpp, rqOgrn, rqOgrnip, rqOkpo — налоговые/регистрационные идентификаторы (ИНН, КПП, ОГРН, ОГРНИП, ОКПО)
  • rqVatId — VAT/налоговый номер (для не-РФ стран)
  • rqResidenceCountry — страна резидентства
  • rqCompanyName — название компании
  • entityTypeId — тип владельца (1 — лид, 3 — контакт, 4 — компания)
  • presetId — шаблон реквизита
  • active — признак активности

Все поля в aggregatable — идентификаторы и категориальные коды, поэтому по ним работает groupBy. Группировка по rqInn (или другому идентификатору) — самый быстрый способ найти дубли реквизитов одним вызовом, без выгрузки всех записей. Числовые функции (sum/avg/min/max) по этим полям недоступны (это строки) — используйте для них пользовательские UF-поля числового типа.

Контракт count. Функция count принимает ТОЛЬКО field: "*" — { "field": "*", "function": "count" }. Передача field: "id" (или любого другого имени) вернёт 400 INVALID_PARAMS с сообщением count aggregate requires field "*". Это намеренный контракт: count считает строки, а не значения конкретного поля.

Пользовательские поля (UF): UF-поля типов integer, double, money — для числовых функций, UF любого типа — для groupBy. Строковые UF-поля реквизита — ИНН, номер телефона, адрес — доступны только в groupBy. Полный список UF-полей конкретного портала приходит в тексте ошибки INVALID_PARAMS, если передать несуществующее имя.

Поля запроса (body)

Параметр Тип Обяз. Описание
aggregate array нет Массив агрегаций. Каждый элемент: { "field": "*", "function": "count" }. Без параметра — только count
filter object нет Фильтрация по полям GET /v1/requisites/fields.
Синтаксис фильтрации
groupBy string | string[] нет Поле или массив полей для группировки (максимум 5). Принимает UF-поля любого типа

Примеры

curl — личный ключ

Terminal
curl -X POST "https://vibecode.bitrix24.tech/v1/requisites/aggregate" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": { "active": true },
    "groupBy": "entityTypeId"
  }'

curl — OAuth-приложение

Terminal
curl -X POST "https://vibecode.bitrix24.tech/v1/requisites/aggregate" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": { "active": true },
    "groupBy": "entityTypeId"
  }'

JavaScript — личный ключ

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/requisites/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filter: { active: true },
    groupBy: 'entityTypeId',
  }),
})

const { success, data } = await res.json()
console.log('Всего активных реквизитов:', data.count)
console.log('По типам владельцев:', data.groups)

JavaScript — OAuth-приложение

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/requisites/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filter: { active: true },
    groupBy: 'entityTypeId',
  }),
})

const { success, data } = await res.json()

Для группировки по нескольким полям передайте массив: "groupBy": ["entityTypeId", "presetId"] (максимум 5).

Другие сценарии

Блоки ниже — тела запросов.

Общее количество реквизитов в портале — самый быстрый запрос, без выгрузки записей:

JSON
{}

Поиск дублей по ИНН одним вызовом — группы с count > 1 содержат повторяющиеся ИНН:

JSON
{ "aggregate": [{ "field": "*", "function": "count" }], "groupBy": "rqInn" }

Группировка по UF-полю (любой тип — например, пользовательский классификатор):

JSON
{ "groupBy": "UF_CRM_CLASSIFIER" }

Поля ответа

Поле Тип Описание
success boolean Всегда true при успехе
data.count number Количество записей, соответствующих фильтру
data.aggregates object Результаты числовых агрегаций. Пусто, если массив aggregate не передан или содержит только count
data.groups array Группы (только при groupBy). Каждый элемент: поля группировки + count
data.meta.totalRecords number Общее количество записей
data.meta.recordsProcessed number Количество обработанных записей
data.meta.truncated boolean true, если числа посчитаны не по всем записям под фильтр: прочитано меньше записей, чем обещал data.count — в том числе когда под фильтр попало больше 5000, — либо срез оборвался ошибкой подстраницы. Размер нехватки приходит в data.meta.recordsShortfall, оборванный срез — в data.meta.pageErrorSample. Присутствует всегда, на полном ответе равен false. Если в запросе нет ни groupBy, ни числовых функций, записи не выгружаются и флаг всегда false

Пример ответа

Ответ на основной запрос (groupBy: "entityTypeId"):

JSON
{
  "success": true,
  "data": {
    "count": 164,
    "aggregates": {},
    "groups": [
      { "entityTypeId": 4, "count": 120 },
      { "entityTypeId": 3, "count": 40 },
      { "entityTypeId": 1, "count": 4 }
    ],
    "meta": {
      "totalRecords": 164,
      "recordsProcessed": 164,
      "truncated": false
    }
  }
}

Без groupBy поле data.groups в ответе отсутствует.

Пример ответа при ошибке

403 — нет скоупа:

JSON
{
  "success": false,
  "error": {
    "code": "SCOPE_DENIED",
    "message": "Requires 'crm' scope"
  }
}

Ошибки

HTTP Код Описание
400 INVALID_PARAMS Некорректное имя функции агрегации или несуществующее поле
403 SCOPE_DENIED API-ключ не имеет скоупа crm
401 TOKEN_MISSING API-ключ не имеет настроенных токенов
429 RATE_LIMITED Превышен лимит запросов: 300 в минуту на портал, все API-ключи портала делят один лимит. Точное значение — в заголовке x-ratelimit-limit (потолок делится на реплики). Повторите после срока из заголовка Retry-After

Полный список общих ошибок API — Ошибки.

Известные особенности

Money-поля. UF-поля типа money хранятся в формате "сумма|валюта" ("1500|RUB") — агрегат извлекает числовую часть автоматически, складывать можно без парсинга.

Без массива aggregate — только count. Если не передать aggregate, метод вернёт count записей с учётом фильтра.

Фильтрация по UF работает. В filter можно передавать любые поля — стандартные и пользовательские, любого типа. Например, { "filter": { "UF_CRM_1234": "value" } } вернёт количество реквизитов с этим значением UF.

Потолок 5000 записей. Числовые функции и группировка подгружают записи постранично, максимум 5000. Если под фильтр попадает больше, ответ приходит с meta.truncated: true. Точное количество берите из data.count — оно считается отдельным подсчётом и верно на выборке любого размера. Потолок не единственная причина такой пометки: она появляется и когда прочитано меньше записей, чем обещал data.count, — размер нехватки лежит в data.meta.recordsShortfall.

Признак усечения приходит рядом с самим числом. Когда ответ приходит с meta.truncated: true, пометка truncated: true стоит внутри объекта каждого поля в data.aggregates, у каждого элемента data.groups, а в data.meta.warnings добавляется предупреждение с кодом AGGREGATE_TRUNCATED. Так клиент, который читает только само число, видит, что оно посчитано по части записей. На полном ответе ни одной из этих пометок нет. Полный разбор — Агрегация POST — потолок 5000 записей.

Смотрите также