[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"docs-chats\u002Fdiscovery\u002Ffolder-recent":3,"docs-tabs-chats\u002Fdiscovery\u002Ffolder-recent":6},{"content":4,"lastmod":5},"## Folder chats\n\n`GET \u002Fv1\u002Fchats\u002Ffolders\u002F:folderId\u002Frecent`\n\nReturns the list of recent dialogs in one folder. Folders and their IDs come from [`GET \u002Fv1\u002Fchats\u002Ffolders`](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Ffolders). The response and paging work the same way as in the [recent dialog list in v2 mode](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent): `data` holds the v2 object — `recentItems` and the `chats`, `users`, `messages`, `files` collections — with keys in `camelCase` format.\n\n## Parameters\n\n| Parameter | Type | Required | Default | Description |\n|----------|-----|:-----:|-----------|---------|\n| `folderId` (path) | number | yes | — | Folder ID, a positive integer |\n| `limit` (query) | number | no | 50 | Rows 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` |\n| `lastMessageDate` (query) | string | no | — | Cursor of the next page, format `YYYY-MM-DDTHH:MM:SS` with an offset or `Z`, no fractional seconds. Not sent on the first page |\n| `unreadOnly` (query) | boolean | no | `false` | `true` — only chats with unread messages. Personal folders ignore this filter |\n\nOther parameters and repeated parameters are rejected with `400 INVALID_PARAMS`.\n\n**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`.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fchats\u002Ffolders\u002F1\u002Frecent?limit=200\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fchats\u002Ffolders\u002F1\u002Frecent?limit=200\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\n\u002F\u002F Read the whole folder in pages of 200 rows\nconst seen = new Map()\nlet cursor = null\nfor (;;) {\n  const qs = new URLSearchParams({ limit: '200' })\n  if (cursor) qs.set('lastMessageDate', cursor)\n  const res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fchats\u002Ffolders\u002F1\u002Frecent?${qs}`, {\n    headers: { 'X-Api-Key': 'YOUR_API_KEY' },\n  })\n  const { data } = await res.json()\n  for (const row of data.recentItems) seen.set(row.dialogId, row)\n  if (!data.hasNextPage) break\n  const dates = data.recentItems\n    .filter((r) => !r.pinned && r.dateLastActivity)\n    .map((r) => r.dateLastActivity)\n  const next = dates.sort((a, b) => Date.parse(a) - Date.parse(b))[0]\n  \u002F\u002F At limit=200 a cursor without progress is a failure, not the end of the list\n  if (!next || (cursor && Date.parse(next) === Date.parse(cursor))) throw new Error('The cursor did not advance')\n  cursor = next\n}\nconsole.log('Chats in the folder:', seen.size)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fchats\u002Ffolders\u002F1\u002Frecent?limit=200', {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { data } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | Always `true` on success |\n| `data.recentItems` | array | List rows: pinned first, then by activity |\n| `data.recentItems[].dialogId` | string | Dialog ID (`chatXXX` or a user ID) — the deduplication key |\n| `data.recentItems[].chatId` | number | Chat ID |\n| `data.recentItems[].messageId` | number | ID of the last message |\n| `data.recentItems[].pinned` | boolean | Whether the chat is pinned in the folder |\n| `data.recentItems[].unread` | boolean | The \"unread\" mark, see [Set the \"unread\" mark](\u002Fdocs\u002Fchats\u002Fmanagement\u002Funread-create) |\n| `data.recentItems[].dateLastActivity` | string \\| null | Moment of the last activity; the smallest value among unpinned rows is the cursor of the next page |\n| `data.chats` | array | Chats referenced by the rows |\n| `data.users` | array | Users referenced by the rows |\n| `data.messages` | array | Last messages of the rows |\n| `data.files` | array | Files of the last messages |\n| `data.hasNextPage` | boolean | `false` — the end of the list |\n| `meta.requestedLimit` | number | The `limit` that was sent. Arrives together with `appliedLimit`, only when the value is below 50 or above 200 |\n| `meta.appliedLimit` | number | The applied `limit` value — only when it was clamped to a bound |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"recentItems\": [\n      {\n        \"dialogId\": \"chat42\",\n        \"chatId\": 42,\n        \"messageId\": 1002,\n        \"type\": \"chat\",\n        \"pinned\": false,\n        \"unread\": false,\n        \"options\": [],\n        \"invited\": false,\n        \"lastReadMessageId\": 1002,\n        \"dateUpdate\": \"2026-09-20T10:01:00+00:00\",\n        \"dateLastActivity\": \"2026-09-20T10:01:00+00:00\",\n        \"ownMessageId\": 1001\n      }\n    ],\n    \"chats\": [\n      { \"id\": 42, \"dialogId\": \"chat42\", \"name\": \"Project\", \"type\": \"chat\", \"owner\": 5, \"role\": \"member\" }\n    ],\n    \"users\": [\n      { \"id\": 7, \"active\": true, \"name\": \"John Brown\", \"firstName\": \"John\", \"lastName\": \"Brown\", \"type\": \"user\" }\n    ],\n    \"messages\": [\n      { \"id\": 1002, \"chatId\": 42, \"authorId\": 7, \"date\": \"2026-09-20T10:01:00+00:00\", \"text\": \"The mockup is ready\" }\n    ],\n    \"files\": [],\n    \"hasNextPage\": false\n  }\n}\n```\n\n## Error response example\n\n422 — the folder does not exist:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"BITRIX_ERROR\",\n    \"message\": \"FOLDER_NOT_FOUND\",\n    \"b24Code\": \"FOLDER_NOT_FOUND\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `INVALID_PARAMS` | `folderId` 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 |\n| 403 | `SCOPE_DENIED` | The API key does not have the `im` scope |\n| 401 | `TOKEN_MISSING` | The API key has no Bitrix24 tokens configured |\n| 404 | `ENTITY_NOT_FOUND` | Bitrix24 returned \"not found\". The portal code is in `error.b24Code` |\n| 422 | `BITRIX_ERROR` | Bitrix24 returned `FOLDER_NOT_FOUND` — no such folder. The portal code is in `error.b24Code` |\n| 422 | `BITRIX_ERROR` | Bitrix24 returned `FOLDER_ACCESS_DENIED` — the folder belongs to another user. The portal code is in `error.b24Code` |\n| 422 | `BITRIX_ERROR` | Bitrix24 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` |\n| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a server error |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n- **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, so `unreadOnly=true` returns all of its chats. To find the unread chats of a personal folder, use the [counters](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Fcounters): they carry the unread count and the \"unread\" mark for every chat.\n- The Bitrix24 code `FOLDER_NOT_FOUND` returned by this endpoint arrives as `422 BITRIX_ERROR` with `error.b24Code` and is not the same as the Vibecode API code `404 FOLDER_NOT_FOUND`, which is documented on [Upload a file to a chat](\u002Fdocs\u002Fchats\u002Ffiles\u002Fupload).\n- 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.\n- 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.\n\n## See also\n\n- [Chat folders](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Ffolders)\n- [Recent dialogs](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Frecent)\n- [Unread counters](\u002Fdocs\u002Fchats\u002Fdiscovery\u002Fcounters)\n- [Chat discovery](\u002Fdocs\u002Fchats\u002Fdiscovery)\n","2026-10-07",{},1794739534640]