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

Агрегация счетов

POST /v1/invoices/aggregate

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

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

  • opportunity — сумма счёта (числовое агрегирование имеет смысл)
  • stageId — стадия (для groupBy)
  • assignedById — ответственный (для groupBy)

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

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

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

Примеры

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

Terminal
curl -X POST "https://vibecode.bitrix24.tech/v1/invoices/aggregate" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "aggregate": [
      { "field": "opportunity", "function": "sum" },
      { "field": "opportunity", "function": "avg" }
    ],
    "filter": { "assignedById": 1 },
    "groupBy": "stageId"
  }'

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

Terminal
curl -X POST "https://vibecode.bitrix24.tech/v1/invoices/aggregate" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "aggregate": [
      { "field": "opportunity", "function": "sum" },
      { "field": "opportunity", "function": "avg" }
    ],
    "filter": { "assignedById": 1 },
    "groupBy": "stageId"
  }'

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

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/invoices/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    aggregate: [
      { field: 'opportunity', function: 'sum' },
      { field: 'opportunity', function: 'avg' },
    ],
    filter: { assignedById: 1 },
    groupBy: 'stageId',
  }),
})

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/invoices/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    aggregate: [
      { field: 'opportunity', function: 'sum' },
      { field: 'opportunity', function: 'avg' },
    ],
    filter: { assignedById: 1 },
    groupBy: 'stageId',
  }),
})

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

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

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

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

Подсчёт записей — count с полем "*", самый быстрый запрос без выгрузки записей. Без массива aggregate результат тот же:

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

Работа с пользовательскими полями (UF) — sum по UF + группировка по другому UF:

JSON
{
  "aggregate": [{ "field": "UF_CRM_TAX", "function": "sum" }],
  "groupBy": "UF_CRM_PAYMENT_METHOD"
}

Поля ответа

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

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

Ответ на основной запрос — агрегации и groupBy: "stageId":

JSON
{
  "success": true,
  "data": {
    "count": 57,
    "aggregates": {
      "opportunity": { "sum": 121850.2, "avg": 2137.722807017544 }
    },
    "groups": [
      {
        "stageId": "DT31_5:N",
        "count": 54,
        "aggregates": { "opportunity": { "sum": 121620.2, "avg": 2252.225925925926 } }
      },
      {
        "stageId": "DT31_5:P",
        "count": 3,
        "aggregates": { "opportunity": { "sum": 230, "avg": 76.66666666666667 } }
      }
    ],
    "meta": {
      "totalRecords": 57,
      "recordsProcessed": 57,
      "truncated": false,
      "groupTotal": 2,
      "groupsTruncated": false
    }
  }
}

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

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

400 — неверное имя функции, несуществующее поле или groupBy по неаггрегируемому полю:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Field 'foo' not found. Available numeric fields: opportunity, stageId, assignedById. User-defined: ufCrm_619F45A0AF6DB (money), ufCrm_619F45A16FECA (money), ufCrm_619F45A18C152 (double), ufCrm_619F45A719813 (integer), ..."
  }
}

Ошибки

HTTP Код Описание
400 INVALID_PARAMS Разбор массива aggregate и поля groupBy: некорректное имя функции, несуществующее поле в aggregate, нечисловое поле в sum/avg/min/max, groupBy по неаггрегируемому полю или больше 5 полей в groupBy
400 UNKNOWN_FILTER_FIELD Разбор filter: фильтр по полю, которого у счёта нет. В тексте ошибки перечислены допустимые имена. Это другая ветка, чем INVALID_PARAMS выше, — она отвечает за состав aggregate и groupBy
401 TOKEN_MISSING API-ключ не имеет настроенных токенов
403 SCOPE_DENIED API-ключ не имеет скоупа crm

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

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

count vs числовые функции. count считается одним вызовом в Битрикс24 на любом объёме данных. Функции sum/avg/min/max подгружают записи постранично (максимум 5000) и считают на стороне Вайбкод — если под фильтр попадает больше 5000 записей, meta.truncated будет true, агрегация выполнится по первым 5000. Для точных счётчиков на больших выборках используйте count или сужайте фильтр. Потолок не единственная причина такой пометки: она появляется и когда прочитано меньше записей, чем обещал data.count, — размер нехватки лежит в data.meta.recordsShortfall.

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

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

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