For AI agents: markdown of this page — /docs-content-en/entities/doc-templates/aggregate.md documentation index — /llms.txt

Aggregate document templates

POST /v1/doc-templates/aggregate

Count and numeric aggregations (sum, average, minimum, maximum) over document templates with filtering and grouping.

Standard fields:

  • sort — sort index, the only numeric field where sum/avg/min/max are meaningful
  • numeratorId — numerator, a number, works in numeric functions and in groupBy
  • fileId — template file on Drive, a number, works in numeric functions and in groupBy
  • region — template region, a string, for groupBy only
  • moduleId — owner module, a string, for groupBy only
  • active — active flag, a string, for groupBy only

The sum/avg/min/max functions accept only numeric fields — those of type number in GET /v1/doc-templates/fields. A string field in a numeric function returns 400 INVALID_PARAMS. groupBy accepts any field from the list above.

Request fields (body)

Parameter Type Required Description
Parameteraggregate Typearray Requiredno DescriptionArray of aggregations. Each item: { "field": "sort", "function": "sum" }. Functions: count, sum, avg, min, max. For count the field is "*". Without the array — count only
Parameterfilter Typeobject Requiredno DescriptionFiltering by the fields from GET /v1/doc-templates/fields. Filtering syntax
ParametergroupBy Typestring | string[] Requiredno DescriptionA field or an array of fields to group by (up to 5). Allowed values are from the list above

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/doc-templates/aggregate" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "aggregate": [
      { "field": "sort", "function": "sum" },
      { "field": "sort", "function": "avg" }
    ],
    "groupBy": "region"
  }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/doc-templates/aggregate" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "aggregate": [
      { "field": "sort", "function": "sum" },
      { "field": "sort", "function": "avg" }
    ],
    "groupBy": "region"
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/doc-templates/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    aggregate: [
      { field: 'sort', function: 'sum' },
      { field: 'sort', function: 'avg' },
    ],
    groupBy: 'region',
  }),
})

const { success, data } = await res.json()
console.log('Total templates:', data.count)
console.log('By region:', data.groups)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/doc-templates/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    aggregate: [
      { field: 'sort', function: 'sum' },
      { field: 'sort', function: 'avg' },
    ],
    groupBy: 'region',
  }),
})

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

To group by several fields, pass an array: "groupBy": ["region", "active"] (up to 5).

Other scenarios

Record count — count with the field "*", the fastest request without loading templates. Without the aggregate array the result is the same:

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

Breakdown by two fields at once — how many templates fall into each combination of region and active flag:

JSON
{ "groupBy": ["region", "active"] }

Number of templates in a single region — count with a filter, records are not loaded:

JSON
{ "filter": { "region": "uk" } }

Response fields

Field Type Description
Fieldsuccess Typeboolean DescriptionAlways true on success
Fielddata.count Typenumber DescriptionTotal number of templates matching the filter
Fielddata.aggregates Typeobject DescriptionNumeric aggregation results: { "sort": { "sum": 1650, "avg": 275 } }. An empty object when the aggregate array is not passed
Fielddata.groups Typearray DescriptionGroups, present only with groupBy. Each item: grouping fields + count + aggregates
Fielddata.meta.totalRecords Typenumber DescriptionTotal number of records matching the filter
Fielddata.meta.recordsProcessed Typenumber DescriptionHow many records were processed for numeric aggregations. Equals 0 for a request without numeric functions — records are not loaded
Fielddata.meta.truncated Typeboolean Descriptiontrue when the numbers were computed over only some of the records that match the filter: fewer records were read than data.count promised — including when more than 5000 matched the filter — or the slice was cut short by a sub-page error. The size of the gap is reported in data.meta.recordsShortfall, the interrupted slice in data.meta.pageErrorSample. Always present, and false on a complete response. If the request has neither groupBy nor a numeric function, no records are fetched and the flag is always false
Fielddata.meta.groupTotal Typenumber DescriptionNumber of groups, present only with groupBy
Fielddata.meta.groupsTruncated Typeboolean Descriptiontrue if there were more groups than the output limit. Present only with groupBy

Response example

Response to the main request (sum and avg over sort with groupBy: "region"):

JSON
{
  "success": true,
  "data": {
    "count": 6,
    "aggregates": {
      "sort": { "sum": 1650, "avg": 275 }
    },
    "groups": [
      {
        "region": "uk",
        "count": 3,
        "aggregates": { "sort": { "sum": 600, "avg": 200 } }
      },
      {
        "region": "de",
        "count": 2,
        "aggregates": { "sort": { "sum": 900, "avg": 450 } }
      },
      {
        "region": "fr",
        "count": 1,
        "aggregates": { "sort": { "sum": 150, "avg": 150 } }
      }
    ],
    "meta": {
      "totalRecords": 6,
      "recordsProcessed": 6,
      "truncated": false,
      "groupTotal": 3,
      "groupsTruncated": false
    }
  }
}

Without groupBy the fields data.groups, data.meta.groupTotal and data.meta.groupsTruncated are absent from the response.

Error response example

400 — a non-existent field. The message lists the available fields:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "Field 'bogus' not found. Available numeric fields: id, numeratorId, sort, fileId, createdBy, updatedBy."
  }
}

Errors

HTTP Code Description
HTTP400 CodeINVALID_PARAMS DescriptionInvalid function name or a non-existent field — the message lists the available fields
HTTP400 CodeINVALID_PARAMS DescriptionA string field (region, moduleId, active) in sum/avg/min/max — the message names the field type
HTTP400 CodeINVALID_PARAMS DescriptiongroupBy on a field outside the list, a reserved word (count, aggregates, meta, groups), or more than 5 fields in groupBy
HTTP403 CodeSCOPE_DENIED DescriptionThe API key lacks the documentgenerator scope
HTTP401 CodeTOKEN_MISSING DescriptionThe API key has no configured tokens
HTTP429 CodeRATE_LIMITED DescriptionRate limit exceeded: 300 requests per minute per portal, all API keys of the portal share one limit. The exact value arrives in the x-ratelimit-limit header (the cap is divided across replicas). Retry after the delay in the Retry-After header

For the full list of common API errors, see Errors.

Known specifics

count vs numeric functions. count is computed with a single call to Bitrix24 for any data volume, without loading records, and meta.recordsProcessed equals 0. The sum/avg/min/max functions load records page by page (up to 5000) and compute on the Vibecode side — if more than 5000 records match the filter, meta.truncated becomes true and the aggregation runs over the first 5000. For exact counts on large result sets, use count or narrow the filter. The ceiling is not the only reason for this marker: it also appears when fewer records were read than data.count promised, and the size of the gap is reported in data.meta.recordsShortfall.

Numeric aggregation is over a single field. Only sort yields a meaningful sum or average. The numeratorId and fileId fields are numeric too and are accepted in sum/avg/min/max, but they are identifiers — aggregate them for grouping, not for summation. The remaining fields are strings and work only in groupBy.

The truncation marker travels with the number itself. When a response arrives with meta.truncated: true, the marker truncated: true sits inside every field object in data.aggregates and on every element of data.groups, and data.meta.warnings gains a warning with the code AGGREGATE_TRUNCATED. A client that reads only the number itself therefore sees that it was computed over only some of the records. None of these markers appear on a complete response. Full details — Aggregation POST — the 5000-record ceiling.

See also