Для 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 — личный ключ
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-приложение
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 — личный ключ
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-приложение
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 результат тот же:
{ "aggregate": [{ "field": "*", "function": "count" }] }
Работа с пользовательскими полями (UF) — sum по UF + группировка по другому UF:
{
"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":
{
"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 по неаггрегируемому полю:
{
"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 записей.