For AI agents: markdown of this page — /docs-content-en/entities/workgroups/search.md documentation index — /llms.txt
Search workgroups
POST /v1/workgroups/search
Returns a list of workgroups matching the given filters. It uses the same contract as GET /v1/workgroups, but passes the conditions in the request body, making it suitable for long filters and non-Latin values.
Request fields (body)
| Field | Type | Description |
|---|---|---|
Fieldfilter |
Typeobject | DescriptionFiltering conditions. Field list: GET /v1/workgroups/fields. Syntax: Filtering. |
Fieldselect |
Typearray | DescriptionList of fields in the response. Use field names from GET /v1/workgroups/fields. |
Fieldsort |
Typeobject | DescriptionSorting: {"<field>": "ASC"|"DESC"}. |
Fieldlimit |
Typenumber | DescriptionMaximum records. Default 50, maximum 5000. |
Fieldoffset |
Typenumber | DescriptionOffset from the start of the result set. Default 0. Together with a date-range filter wider than 14 days it is rejected — see UNSTABLE_OFFSET_PAGINATION in the "Errors" section. |
FieldautoWindow |
Typeboolean | DescriptionSplit the result set into weekly windows when filtering by a date range wider than 14 days. Defaults to true. false disables splitting |
For limit > 50 Vibecode automatically paginates the request on the server side. The maximum is 5000 records per call. If more match the filter — meta.hasMore will be true.
Get projects only
A single collection stores both workgroups and projects. The isProject field distinguishes them: true — a project, false — an ordinary workgroup. To select projects, pass "filter": { "isProject": "Y" }.
Examples
curl — personal key
curl -X POST "https://vibecode.bitrix24.com/v1/workgroups/search" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filter": { "%name": "Marketing", "archived": "N" },
"select": ["id", "name", "ownerId", "membersCount"],
"sort": { "dateCreate": "DESC" },
"limit": 5
}'
curl — OAuth application
curl -X POST "https://vibecode.bitrix24.com/v1/workgroups/search" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filter": { "%name": "Marketing", "archived": "N" },
"select": ["id", "name", "ownerId", "membersCount"],
"sort": { "dateCreate": "DESC" },
"limit": 5
}'
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/workgroups/search', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
filter: { '%name': 'Marketing', archived: 'N' },
select: ['id', 'name', 'ownerId', 'membersCount'],
sort: { dateCreate: 'DESC' },
limit: 5,
}),
})
const { success, data, meta } = await res.json()
console.log(`Found ${meta.total} workgroups`)
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/workgroups/search', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
filter: { '%name': 'Marketing', archived: 'N' },
select: ['id', 'name', 'ownerId', 'membersCount'],
sort: { dateCreate: 'DESC' },
limit: 5,
}),
})
const { success, data, meta } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on success |
Fielddata |
Typearray | DescriptionArray of workgroups (all fields — see Workgroup fields) |
Fieldmeta.total |
Typenumber | DescriptionHow many records matched the filter |
Fieldmeta.hasMore |
Typeboolean | DescriptionWhether there is a next page |
Fieldmeta.durationMs |
Typenumber | DescriptionRequest duration in milliseconds |
Fieldmeta.autoWindowed |
Typeboolean | Descriptiontrue if the result set was split into time windows |
Fieldmeta.windowCount |
Typenumber | DescriptionNumber of windows. Present with autoWindowed: true |
Fieldmeta.batchWaves |
Typenumber | DescriptionNumber of parallel request waves. Present with autoWindowed: true |
The meta fields sit next to data, not inside it. Page through the results using meta.hasMore: a data length equal to limit does not rule out the last page.
Response example
{
"success": true,
"data": [
{
"id": 85,
"name": "Marketing 2026",
"ownerId": 1271,
"membersCount": 2,
"dateCreate": "2026-03-20T06:45:10.000Z"
},
{
"id": 83,
"name": "New product development team",
"ownerId": 1269,
"membersCount": 1,
"dateCreate": "2026-03-20T06:41:07.000Z"
},
{
"id": 81,
"name": "Regional office launch",
"ownerId": 1271,
"membersCount": 1,
"dateCreate": "2026-03-20T06:29:07.000Z"
}
],
"meta": {
"total": 3,
"hasMore": false
}
}
With a date-range filter wider than 14 days, meta additionally returns autoWindowed, windowCount, and batchWaves:
{
"success": true,
"data": [ /* ... */ ],
"meta": {
"total": 29,
"hasMore": true,
"autoWindowed": true,
"windowCount": 131,
"batchWaves": 3,
"durationMs": 4217
}
}
Error response example
401 — no authorization key was passed:
{
"success": false,
"error": {
"code": "MISSING_API_KEY",
"message": "API key required. Pass via X-Api-Key header."
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | CodeINVALID_PARAMS |
DescriptionThe request body does not parse or contains invalid fields |
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header was not passed |
| HTTP401 | CodeINVALID_API_KEY |
DescriptionThe key is not recognized — no such key exists on the platform |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe key is missing the sonet_group scope |
| HTTP400 | CodeUNSTABLE_OFFSET_PAGINATION |
Descriptionoffset greater than zero together with a date-range filter wider than 14 days. Two different retrieval algorithms produce inconsistent results, so the request is rejected. Take everything in a single request with limit up to 5000, or pass autoWindow: false with sorting by id, or split the date range into parts yourself |
| HTTP429 | CodeRATE_LIMITED |
DescriptionRate limit exceeded: 300 requests per minute per portal. All API keys of the portal share one limit. The current limit is returned in the x-ratelimit-limit header. Retry after the delay in the Retry-After header |
For the full list of common API errors, see Errors.
Known specifics
Time-window splitting. A date-range filter wider than 14 days is automatically split into weekly windows executed in parallel waves, so the result set bypasses the ceiling of 5000 records per call. meta then returns autoWindowed: true, the number of windows windowCount, and the number of waves batchWaves. The autoWindow: false parameter disables splitting. While splitting is active, an offset greater than zero is rejected with UNSTABLE_OFFSET_PAGINATION.
Boolean fields in the filter can be passed in two ways. In the POST body both Y / N and native JSON true / false are allowed: "filter": {"active": "Y"} and "filter": {"active": true} produce the same result set. In the response the same fields always come back as true / false.
A % prefix in the field name — substring search. "filter": {"%name": "Marketing"} will find all groups whose name contains "Marketing". Without the prefix the filter requires an exact match.
The sort parameter in the body is sort. An order key in the body is ignored without an error — the result set is returned in the default order. Use "sort": {"dateCreate": "DESC"} or the string form "sort": "dateCreate" (the default direction is ASC).