For AI agents: markdown of this page — /docs-content-en/entities/activities/aggregate.md documentation index — /llms.txt
Aggregate activities
POST /v1/activities/aggregate
Count activities with filtering and grouping.
Standard fields:
typeId— activity type (forgroupBy)ownerTypeId— parent entity type (forgroupBy)responsibleId— responsible person (forgroupBy)completed— completion status (forgroupBy)
All fields in aggregatable are categorical identifiers, so the main scenario is count with grouping. The numeric functions sum/avg/min/max are rarely used.
Request fields (body)
| Parameter | Type | Required | Description |
|---|---|---|---|
aggregate |
array | no | Array of aggregations. Each element: { "field": "*", "function": "count" }. Without the array — count only |
filter |
object | no | Filter by GET /v1/activities/fields fields. Filter syntax |
groupBy |
string | string[] | no | Field or array of fields to group by (maximum 5). Allowed values — from the list above |
Examples
curl — personal key
Number of activities for a deal (ownerTypeId: 2 — deal), grouped by activity type:
curl -X POST "https://vibecode.bitrix24.com/v1/activities/aggregate" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter": { "ownerTypeId": 2, "ownerId": 741, "completed": "Y" },
"groupBy": "typeId"
}'
curl — OAuth application
curl -X POST "https://vibecode.bitrix24.com/v1/activities/aggregate" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filter": { "ownerTypeId": 2, "ownerId": 741, "completed": "Y" },
"groupBy": "typeId"
}'
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/activities/aggregate', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
filter: { ownerTypeId: 2, ownerId: 741, completed: 'Y' },
groupBy: 'typeId',
}),
})
const { success, data } = await res.json()
console.log('Total completed activities for the deal:', data.count)
console.log('Distribution by type:', data.groups)
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/activities/aggregate', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
filter: { ownerTypeId: 2, ownerId: 741, completed: 'Y' },
groupBy: 'typeId',
}),
})
const { success, data } = await res.json()
To group by several fields, pass an array:
"groupBy": ["typeId", "completed"](maximum 5).
Other scenarios
Total number of activities in the Bitrix24 account — the fastest query, no record retrieval:
{}
Group activities by contact (ownerTypeId: 3) by completion status:
{
"filter": { "ownerTypeId": 3, "ownerId": 485 },
"groupBy": "completed"
}
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on success |
data.count |
number | Total number of records matching the filter |
data.aggregates |
object | Aggregation results (usually empty for activities) |
data.groups |
array | Groups (only with groupBy). Each element: grouping fields + count |
data.meta.totalRecords |
number | Total number of records matching the filter |
data.meta.recordsProcessed |
number | How many records were processed (for count — 0, records are not retrieved) |
data.meta.truncated |
boolean | true if more than 5000 records matched the filter |
Response example
Response to the main query (groupBy: "typeId"):
{
"success": true,
"data": {
"count": 2600,
"aggregates": {},
"groups": [
{ "typeId": 1, "count": 1200 },
{ "typeId": 2, "count": 800 },
{ "typeId": 6, "count": 600 }
],
"meta": {
"totalRecords": 2600,
"recordsProcessed": 2600,
"truncated": false
}
}
}
Without groupBy, the data.groups field is absent from the response.
Error response example
400 — groupBy on a non-aggregatable field or a non-existent field:
{
"success": false,
"error": {
"code": "INVALID_PARAMS",
"message": "groupBy field 'subject' is not aggregatable on this entity. Available: typeId, ownerTypeId, responsibleId, completed"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_PARAMS |
groupBy on a non-aggregatable field or more than 5 fields in groupBy |
| 401 | TOKEN_MISSING |
The API key has no configured tokens |
| 403 | SCOPE_DENIED |
The API key lacks the crm scope |
Full list of common API errors — Errors.
Known specifics
Universal ownerTypeId. For counters by parent entity, use the ownerTypeId + ownerId pairs: 2 — deal, 3 — contact, 4 — company, 1 — lead. This is the most common scenario for /v1/activities/aggregate.
See also
- List activities — get records with filtering
- Search activities — POST request with filters
- Filter syntax
- Limits and optimization — rate limits