For AI agents: markdown of this page — /docs-content-en/chats/discovery/recent-external.md documentation index — /llms.txt
External chats of a section
GET /v1/chats/recent/external
Returns one section of the current user's chat list: the chats that other Bitrix24 modules create, such as task chats or calendar event chats. Ordering and paging work as in recent dialogs: pinned ones first, then by the time of the last activity.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
Parametertype (query) |
Typestring | Requiredyes | Default— | DescriptionSection code: a Latin letter, then letters, digits or _, up to 64 characters. tasksTask — task chats, calendar — calendar event chats. The sections a chat is counted in are listed in the recentSections field of the unread counters |
Parameterlimit (query) |
Typeinteger | Requiredno | Default50 | DescriptionRows per page, 50 to 200. A smaller value is raised to 50 and a larger one is clamped to 200, and both adjustments are echoed in meta |
ParameterlastMessageDate (query) |
Typestring | Requiredno | Default— | DescriptionCursor of the next page: the smallest dateLastActivity among the unpinned rows of the previous page. Format YYYY-MM-DDTHH:MM:SS with an offset or Z, without fractional seconds. Not passed on the first page |
Other parameters and repeated parameters are rejected with 400 INVALID_PARAMS. The default and collab sections are not read here, as they have their own endpoints: the common list — recent dialogs in the v2 mode, collabs — collab list.
Pagination — as in recent dialogs in the v2 mode. The cursor of the next page is the smallest non-empty dateLastActivity among the unpinned rows; compare instants, not strings. The bound is inclusive, and pinned chats appear at the top of every page, so deduplicate by chatId. The list ends only at hasNextPage: false. 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. Do not discard response rows: the cursor is computed over the whole response.
Examples
curl — personal key
curl "https://vibecode.bitrix24.com/v1/chats/recent/external?type=tasksTask&limit=50" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl "https://vibecode.bitrix24.com/v1/chats/recent/external?type=tasksTask&limit=50" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
const rows = new Map()
let limit = 50
let cursor
for (;;) {
const url = new URL('https://vibecode.bitrix24.com/v1/chats/recent/external')
url.searchParams.set('type', 'tasksTask')
url.searchParams.set('limit', String(limit))
if (cursor) url.searchParams.set('lastMessageDate', cursor)
const res = await fetch(url, { headers: { 'X-Api-Key': 'YOUR_API_KEY' } })
const { data } = await res.json()
for (const item of data.recentItems) rows.set(item.chatId, item)
if (!data.hasNextPage) break
const dates = data.recentItems.filter((i) => !i.pinned && i.dateLastActivity).map((i) => i.dateLastActivity)
const next = dates.length ? dates.reduce((a, b) => (Date.parse(a) <= Date.parse(b) ? a : b)) : undefined
if (!next || (cursor && Date.parse(next) >= Date.parse(cursor))) {
if (limit === 200) throw new Error('Recent-list cursor did not advance; restart with a full refresh')
limit = Math.min(limit * 2, 200)
continue
}
cursor = next
limit = 50
}
JavaScript — OAuth application
const rows = new Map()
let limit = 50
let cursor
for (;;) {
const url = new URL('https://vibecode.bitrix24.com/v1/chats/recent/external')
url.searchParams.set('type', 'tasksTask')
url.searchParams.set('limit', String(limit))
if (cursor) url.searchParams.set('lastMessageDate', cursor)
const res = await fetch(url, {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { data } = await res.json()
for (const item of data.recentItems) rows.set(item.chatId, item)
if (!data.hasNextPage) break
const dates = data.recentItems.filter((i) => !i.pinned && i.dateLastActivity).map((i) => i.dateLastActivity)
const next = dates.length ? dates.reduce((a, b) => (Date.parse(a) <= Date.parse(b) ? a : b)) : undefined
if (!next || (cursor && Date.parse(next) >= Date.parse(cursor))) {
if (limit === 200) throw new Error('Recent-list cursor did not advance; restart with a full refresh')
limit = Math.min(limit * 2, 200)
continue
}
cursor = next
limit = 50
}
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on success |
Fielddata.recentItems |
Typearray | DescriptionSection rows in the order Bitrix24 returns them: pinned ones first, then by activity |
Fielddata.recentItems[].dialogId |
Typestring | DescriptionDialog ID, chatXXX |
Fielddata.recentItems[].chatId |
Typenumber | DescriptionChat ID, the deduplication key |
Fielddata.recentItems[].messageId |
Typenumber | DescriptionID of the last message |
Fielddata.recentItems[].pinned |
Typeboolean | DescriptionThe chat is pinned for the current user |
Fielddata.recentItems[].unread |
Typeboolean | DescriptionThe chat is manually marked as unread |
Fielddata.recentItems[].dateLastActivity |
Typestring|null | DescriptionInstant of the last activity. The smallest value among the unpinned rows is the cursor of the next page |
Fielddata.chats |
Typearray | DescriptionChat cards: id, dialogId, name, type — the same section code, entityType and entityId — the linked entity, entityLink.url — its address in Bitrix24, the current user's role and other chat fields |
Fielddata.messages |
Typearray | DescriptionThe chats' last messages |
Fielddata.users |
Typearray | DescriptionAuthors of the last messages |
Fielddata.recentConfigs |
Typearray | DescriptionThe list sections each chat is counted in: chatId and sections |
Fielddata.hasNextPage |
Typeboolean | Descriptionfalse — the end of the section |
Fieldmeta.requestedLimit |
Typenumber | DescriptionThe limit passed. Present together with appliedLimit only when the value was outside the range of 50 to 200 |
Fieldmeta.appliedLimit |
Typenumber | DescriptionThe limit applied — only when it was clamped to a bound |
Response example
The tasksTask section, with the main fields shown:
{
"success": true,
"data": {
"recentItems": [
{
"dialogId": "chat264388",
"chatId": 264388,
"messageId": 608251,
"type": "chat",
"pinned": false,
"unread": false,
"dateUpdate": "2026-09-11T12:53:10+00:00",
"dateLastActivity": "2026-09-11T12:53:10+00:00"
}
],
"chats": [
{
"id": 264388,
"dialogId": "chat264388",
"name": "Prepare the release",
"type": "tasksTask",
"entityType": "TASKS_TASK",
"entityId": "27",
"owner": 1,
"role": "owner"
}
],
"recentConfigs": [
{ "chatId": 264388, "sections": ["tasksTask"] }
],
"hasNextPage": false
}
}
Error response example
400 — the common list is requested:
{
"success": false,
"error": {
"code": "INVALID_PARAMS",
"message": "`type` default is not an external-chat section — read it through GET /v1/chats/recent?format=v2."
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | CodeINVALID_PARAMS |
DescriptionNo type, type is not a section code, or type is default or collab — the message names the right endpoint. Also a parameter other than type, limit, lastMessageDate, a repeated parameter, a non-numeric limit, or lastMessageDate not in the YYYY-MM-DDTHH:MM:SS format with an offset or Z, or with a nonexistent date or time. Checked before the Bitrix24 call |
| HTTP422 | CodeBITRIX_ERROR |
DescriptionBitrix24 returned an error; the Bitrix24 code is in error.b24Code |
| HTTP403 | CodeBITRIX_ACCESS_DENIED |
DescriptionBitrix24 denied access |
| HTTP403 | CodeSCOPE_DENIED |
DescriptionThe API key does not have the im scope |
| HTTP401 | CodeTOKEN_MISSING |
DescriptionThe API key has no Bitrix24 tokens configured |
| HTTP502 | CodeBITRIX_UNAVAILABLE |
DescriptionBitrix24 is unavailable or returned a server error |
Full list of common API errors — Errors.
Known specifics
An unknown section is an empty list, not an error. A code that does not exist in the Bitrix24 account returns 200 with an empty recentItems and hasNextPage: false. The response does not reveal a typo in type: check the code against the recentSections field of the unread counters.
The limit floor is 50. A user can have up to 45 pinned chats, and they repeat on every page. A page of fewer than 50 rows could consist of repeats only and give no cursor.
Pagination does not give a snapshot. A chat lifted above the cursor by new activity during pagination does not appear in the results. Re-read the first page after pagination.