For AI agents: markdown of this page — /docs-content-en/chats/discovery/folder-recent.md documentation index — /llms.txt
Folder chats
GET /v1/chats/folders/:folderId/recent
Returns the list of recent dialogs in one folder. Folders and their IDs come from GET /v1/chats/folders. The response and paging work the same way as in the recent dialog list in v2 mode: data holds the v2 object — recentItems and the chats, users, messages, files collections — with keys in camelCase format.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ParameterfolderId (path) |
Typenumber | Requiredyes | Default— | DescriptionFolder ID, a positive integer |
Parameterlimit (query) |
Typenumber | Requiredno | Default50 | DescriptionRows per page, from 50 to 200: a smaller value is raised to 50, a larger one is clamped to 200, both echoed in meta.requestedLimit and meta.appliedLimit |
ParameterlastMessageDate (query) |
Typestring | Requiredno | Default— | DescriptionCursor of the next page, format YYYY-MM-DDTHH:MM:SS with an offset or Z, no fractional seconds. Not sent on the first page |
ParameterunreadOnly (query) |
Typeboolean | Requiredno | Defaultfalse |
Descriptiontrue — only chats with unread messages. Personal folders ignore this filter |
Other parameters and repeated parameters are rejected with 400 INVALID_PARAMS.
Paging. The cursor of the next page is the smallest non-empty dateLastActivity among the unpinned rows of the current page. Compare moments in time, not strings. The bound is inclusive. Only hasNextPage: false marks the end of the list. If hasNextPage is true but there is no cursor or it equals the previous one, repeat the request with a larger limit, up to 200. true without progress even at 200 is a failure, not the end of the list. The response contains repeated rows: pinned rows come first on a page — on the first page in a system folder, and on the following pages as well in a personal folder — and the all-chats folder mixes in colleagues the user has not chatted with yet. Deduplicate by dialogId.
Examples
curl — personal key
curl "https://vibecode.bitrix24.com/v1/chats/folders/1/recent?limit=200" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl "https://vibecode.bitrix24.com/v1/chats/folders/1/recent?limit=200" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
// Read the whole folder in pages of 200 rows
const seen = new Map()
let cursor = null
for (;;) {
const qs = new URLSearchParams({ limit: '200' })
if (cursor) qs.set('lastMessageDate', cursor)
const res = await fetch(`https://vibecode.bitrix24.com/v1/chats/folders/1/recent?${qs}`, {
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data } = await res.json()
for (const row of data.recentItems) seen.set(row.dialogId, row)
if (!data.hasNextPage) break
const dates = data.recentItems
.filter((r) => !r.pinned && r.dateLastActivity)
.map((r) => r.dateLastActivity)
const next = dates.sort((a, b) => Date.parse(a) - Date.parse(b))[0]
// At limit=200 a cursor without progress is a failure, not the end of the list
if (!next || (cursor && Date.parse(next) === Date.parse(cursor))) throw new Error('The cursor did not advance')
cursor = next
}
console.log('Chats in the folder:', seen.size)
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/folders/1/recent?limit=200', {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { data } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on success |
Fielddata.recentItems |
Typearray | DescriptionList rows: pinned first, then by activity |
Fielddata.recentItems[].dialogId |
Typestring | DescriptionDialog ID (chatXXX or a user ID) — the deduplication key |
Fielddata.recentItems[].chatId |
Typenumber | DescriptionChat ID |
Fielddata.recentItems[].messageId |
Typenumber | DescriptionID of the last message |
Fielddata.recentItems[].pinned |
Typeboolean | DescriptionWhether the chat is pinned in the folder |
Fielddata.recentItems[].unread |
Typeboolean | DescriptionThe "unread" mark, see Set the "unread" mark |
Fielddata.recentItems[].dateLastActivity |
Typestring | null | DescriptionMoment of the last activity; the smallest value among unpinned rows is the cursor of the next page |
Fielddata.chats |
Typearray | DescriptionChats referenced by the rows |
Fielddata.users |
Typearray | DescriptionUsers referenced by the rows |
Fielddata.messages |
Typearray | DescriptionLast messages of the rows |
Fielddata.files |
Typearray | DescriptionFiles of the last messages |
Fielddata.hasNextPage |
Typeboolean | Descriptionfalse — the end of the list |
Fieldmeta.requestedLimit |
Typenumber | DescriptionThe limit that was sent. Arrives together with appliedLimit, only when the value is below 50 or above 200 |
Fieldmeta.appliedLimit |
Typenumber | DescriptionThe applied limit value — only when it was clamped to a bound |
Response example
{
"success": true,
"data": {
"recentItems": [
{
"dialogId": "chat42",
"chatId": 42,
"messageId": 1002,
"type": "chat",
"pinned": false,
"unread": false,
"options": [],
"invited": false,
"lastReadMessageId": 1002,
"dateUpdate": "2026-09-20T10:01:00+00:00",
"dateLastActivity": "2026-09-20T10:01:00+00:00",
"ownMessageId": 1001
}
],
"chats": [
{ "id": 42, "dialogId": "chat42", "name": "Project", "type": "chat", "owner": 5, "role": "member" }
],
"users": [
{ "id": 7, "active": true, "name": "John Brown", "firstName": "John", "lastName": "Brown", "type": "user" }
],
"messages": [
{ "id": 1002, "chatId": 42, "authorId": 7, "date": "2026-09-20T10:01:00+00:00", "text": "The mockup is ready" }
],
"files": [],
"hasNextPage": false
}
}
Error response example
422 — the folder does not exist:
{
"success": false,
"error": {
"code": "BITRIX_ERROR",
"message": "FOLDER_NOT_FOUND",
"b24Code": "FOLDER_NOT_FOUND"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | CodeINVALID_PARAMS |
DescriptionfolderId is not a positive integer; a parameter other than limit, lastMessageDate or unreadOnly; a repeated parameter; a non-numeric limit; an unreadOnly that is neither true nor false; or a lastMessageDate that is not in the YYYY-MM-DDTHH:MM:SS format with an offset or Z, or that names a date or time that does not exist. Checked before any call to Bitrix24 |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe API key does not have the im scope |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe API key has no Bitrix24 tokens configured |
| HTTP404 | CodeENTITY_NOT_FOUND |
DescriptionBitrix24 returned "not found". The portal code is in error.b24Code |
| HTTP422 | CodeBITRIX_ERROR |
DescriptionBitrix24 returned FOLDER_NOT_FOUND — no such folder. The portal code is in error.b24Code |
| HTTP422 | CodeBITRIX_ERROR |
DescriptionBitrix24 returned FOLDER_ACCESS_DENIED — the folder belongs to another user. The portal code is in error.b24Code |
| HTTP422 | CodeBITRIX_ERROR |
DescriptionBitrix24 returned FOLDER_OPERATION_NOT_SUPPORTED — the folder has no chat list, as with the public channel showcase, or the section is not available to the user. The portal code is in error.b24Code |
| HTTP502 | CodeBITRIX_UNAVAILABLE |
DescriptionBitrix24 is unavailable or returned a server error |
Full list of common API errors — Errors.
Known specifics
- Personal folders ignore
unreadOnly. This is Bitrix24 behavior: a personal folder's list is built from the chats added to it, without the unread filter, sounreadOnly=truereturns all of its chats. To find the unread chats of a personal folder, use the counters: they carry the unread count and the "unread" mark for every chat. - The Bitrix24 code
FOLDER_NOT_FOUNDreturned by this endpoint arrives as422 BITRIX_ERRORwitherror.b24Codeand is not the same as the Vibecode API code404 FOLDER_NOT_FOUND, which is documented on Upload a file to a chat. - The call only reads: its argument is a folder, not a chat, so it does not make anyone a chat member, and a read-only key can run it.
- Pagination does not give a snapshot: a chat that new activity lifts above the cursor during pagination does not appear in the results, so re-read the first page after pagination.