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

Aggregate nodes

POST /v1/humanresources/nodes/aggregate

Counts org structure nodes of the selected type and computes numeric aggregations over them — sum, average, minimum, maximum. The node type is passed inside the filter in the request body, not in the query string as with the node list.

Fields available to numeric functions:

  • userCount — the number of employees in the node, the only field where numeric aggregation is meaningful.
  • id, structureId, parentId — identifiers. The sum, avg, min, max functions accept them, but the result carries no meaning as a metric.

Request fields (body)

Parameter Type Required Description
Parameterfilter Typeobject Requiredyes DescriptionAn object with a single key type — the node type: DEPARTMENT (department) or TEAM (team). Other filter keys are not accepted
Parameteraggregate Typearray Requiredno DescriptionAggregations: [{ "field": "userCount", "function": "sum" }], up to 5 expressions. Functions: count, sum, avg, min, max. For count the field is "*". Without the parameter, only count is returned

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/humanresources/nodes/aggregate" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": { "type": "DEPARTMENT" },
    "aggregate": [
      { "field": "userCount", "function": "sum" }
    ]
  }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/humanresources/nodes/aggregate" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": { "type": "DEPARTMENT" },
    "aggregate": [
      { "field": "userCount", "function": "sum" }
    ]
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/humanresources/nodes/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filter: { type: 'DEPARTMENT' },
    aggregate: [
      { field: 'userCount', function: 'sum' },
    ],
  }),
})

const { success, data } = await res.json()
console.log(`Departments: ${data.count}, employees in them: ${data.aggregates.userCount.sum}`)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/humanresources/nodes/aggregate', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filter: { type: 'DEPARTMENT' },
    aggregate: [
      { field: 'userCount', function: 'sum' },
    ],
  }),
})

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

Other scenarios

The blocks below are request bodies.

The number of teams — the fastest query, without fetching records:

JSON
{ "filter": { "type": "TEAM" } }

The same via an explicit count — field "*", the result matches the request without aggregate:

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

Response fields

Field Type Description
Fieldsuccess Typeboolean DescriptionAlways true on success
Fielddata.count Typenumber DescriptionNumber of nodes of the selected type
Fielddata.aggregates Typeobject DescriptionNumeric-function results: { "userCount": { "sum": 55 } }. An empty object if no numeric functions were requested
Fielddata.meta.totalRecords Typenumber DescriptionTotal number of records
Fielddata.meta.recordsProcessed Typenumber DescriptionNumber of records processed. 0 for a request without numeric functions
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 no numeric functions, no records are fetched and the flag is always false

Response example

Total employees across all departments:

JSON
{
  "success": true,
  "data": {
    "count": 20,
    "aggregates": {
      "userCount": { "sum": 55 }
    },
    "meta": {
      "totalRecords": 20,
      "recordsProcessed": 20,
      "truncated": false
    }
  }
}

Error response example

400 — the node type is not passed in filter:

JSON
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_PARAMS",
    "message": "POST /v1/humanresources/nodes/aggregate requires filter params: type. Example body: { \"filter\": {\"type\":\"...\"} }"
  }
}

Errors

HTTP Code Description
HTTP400 CodeMISSING_REQUIRED_PARAMS Descriptionfilter has no type key, or the value is empty or passed as an array or object. The same response if type is passed at the top level of the body or in the query string
HTTP400 CodeINVALID_PARAMS DescriptionThe type value is neither DEPARTMENT nor TEAM — validation[] contains an element with field: "INVALID_TYPE"
HTTP400 CodeINVALID_PARAMS DescriptionUnknown function — Invalid aggregate function '<name>'. Supported: count, sum, avg, min, max
HTTP400 CodeINVALID_PARAMS DescriptionNumeric function on a non-numeric field — Field '<name>' is not numeric (type: string)
HTTP400 CodeINVALID_PARAMS DescriptionNumeric function on a field that nodes do not have — Field '<name>' not found, the message lists the available numeric fields
HTTP400 CodeINVALID_PARAMS DescriptionNumeric function without a field or with field "*"
HTTP400 CodeINVALID_PARAMS Descriptioncount with a field other than "*"
HTTP400 CodeINVALID_PARAMS DescriptionEmpty aggregate array or more than 5 expressions in it
HTTP400 CodeINVALID_PARAMS DescriptiongroupBy is passed — message groupBy field '<name>' is not aggregatable on this entity
HTTP422 CodeBITRIX_ERROR Descriptionfilter contains a key other than type, such as parentId or name — a message about an unrecognized filter expression
HTTP403 CodeSCOPE_DENIED DescriptionThe key lacks the humanresources scope
HTTP401 CodeTOKEN_MISSING DescriptionThe API key has no Bitrix24 tokens configured
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

Full list of common API errors — Errors.

Known specifics

count takes a single request, numeric functions do not. count is computed in one call regardless of the number of nodes. The sum, avg, min, max functions load records page by page — up to 5000 — and compute the values on the server side.

Grouping is not available. Nodes have no fields for groupBy: a request with any grouping field returns 400 INVALID_PARAMS with an empty list of allowed fields. To get separate numbers for departments and teams, make one request per type or call node count by type.

The truncation marker arrives next to the number itself. When the response comes with meta.truncated: true, a truncated: true marker sits inside the object of each field in data.aggregates, and a warning with code AGGREGATE_TRUNCATED is added to data.meta.warnings. This way a client that reads only the number itself sees that it was computed over only some of the records. A complete response carries none of these markers. Full breakdown — Aggregation POST — the 5000-record ceiling.

See also