For AI agents: markdown of this page — /docs-content-en/chats/discovery/recent-channels.md documentation index — /llms.txt

Channel list

GET /v1/chats/recent/channels

Returns the public channels of the Bitrix24 account page by page, from the channel with the newest message to older ones. Use it to build a directory of channels the user can subscribe to.

Parameters

Parameter Type Required Default Description
Parameterlimit (query) Typeinteger Requiredno Default50 DescriptionRows per page, 1 to 200. A smaller value is raised to 1 and a larger one is clamped to 200, and both adjustments are echoed in meta
ParameterlastMessageId (query) Typeinteger Requiredno Default— DescriptionCursor for the next page: the smallest positive messageId among the rows of the previous page. Not passed on the first page

Other parameters and repeated parameters are rejected with 400 INVALID_PARAMS.

Pagination. Rows are ordered by the ID of the channel's last message, from largest to smallest. Request the next page with lastMessageId equal to the smallest positive messageId of the current page. The bound is exclusive: the channel with that messageId is not repeated on the next page. The list ends only at hasNextPage: false. If hasNextPage is true but the page has no row with a positive messageId, repeat the request with a larger limit, up to 200.

Examples

curl — personal key

Terminal
curl "https://vibecode.bitrix24.com/v1/chats/recent/channels?limit=50" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/chats/recent/channels?limit=50" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const channels = []
const seen = new Set()
let limit = 50
let cursor
for (;;) {
  const url = new URL('https://vibecode.bitrix24.com/v1/chats/recent/channels')
  url.searchParams.set('limit', String(limit))
  if (cursor) url.searchParams.set('lastMessageId', String(cursor))
  const res = await fetch(url, { headers: { 'X-Api-Key': 'YOUR_API_KEY' } })
  const { data } = await res.json()
  for (const item of data.recentItems) {
    if (!seen.has(item.chatId)) { seen.add(item.chatId); channels.push(item) }
  }
  if (!data.hasNextPage) break
  const ids = data.recentItems.map((i) => i.messageId).filter((id) => id > 0)
  const next = ids.length ? Math.min(...ids) : undefined
  if (next === undefined || (cursor !== undefined && next >= cursor)) {
    if (limit === 200) throw new Error('Channel cursor did not advance; restart with a full refresh')
    limit = Math.min(limit * 2, 200)
    continue
  }
  cursor = next
  limit = 50
}

JavaScript — OAuth application

javascript
const channels = []
const seen = new Set()
let limit = 50
let cursor
for (;;) {
  const url = new URL('https://vibecode.bitrix24.com/v1/chats/recent/channels')
  url.searchParams.set('limit', String(limit))
  if (cursor) url.searchParams.set('lastMessageId', String(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) {
    if (!seen.has(item.chatId)) { seen.add(item.chatId); channels.push(item) }
  }
  if (!data.hasNextPage) break
  const ids = data.recentItems.map((i) => i.messageId).filter((id) => id > 0)
  const next = ids.length ? Math.min(...ids) : undefined
  if (next === undefined || (cursor !== undefined && next >= cursor)) {
    if (limit === 200) throw new Error('Channel 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 DescriptionList rows, one per channel
Fielddata.recentItems[].dialogId Typestring DescriptionDialog ID of the channel, chatXXX
Fielddata.recentItems[].chatId Typenumber DescriptionChat ID of the channel, the deduplication key
Fielddata.recentItems[].messageId Typenumber DescriptionID of the channel's last message, 0 for a channel without messages. The smallest positive value on the page is the cursor for the next one
Fielddata.recentItems[].pinned Typeboolean DescriptionWhether the channel is pinned for the current user. It does not affect the row order
Fielddata.recentItems[].dateLastActivity Typenull DescriptionAlways null in this list: channels are ordered by message ID, not by date
Fielddata.chats Typearray DescriptionChannel cards: id, dialogId, name, type, owner, the current user's role and other chat fields
Fielddata.messages Typearray DescriptionThe channels' last messages
Fielddata.users Typearray DescriptionAuthors of the last messages
Fielddata.recentConfigs Typearray DescriptionThe list sections each channel is counted in: chatId and sections
Fielddata.hasNextPage Typeboolean Descriptionfalse — the end of the list
Fieldmeta.requestedLimit Typenumber DescriptionThe limit passed. Returned together with appliedLimit, and only when the value was outside the range of 1 to 200
Fieldmeta.appliedLimit Typenumber DescriptionThe limit applied — only when it was clamped to a bound

Response example

The main fields are shown:

JSON
{
  "success": true,
  "data": {
    "recentItems": [
      {
        "dialogId": "chat206",
        "chatId": 206,
        "messageId": 329393,
        "type": "chat",
        "pinned": false,
        "unread": false,
        "dateUpdate": null,
        "dateLastActivity": null
      },
      {
        "dialogId": "chat2",
        "chatId": 2,
        "messageId": 0,
        "type": "chat",
        "pinned": false,
        "unread": false,
        "dateUpdate": null,
        "dateLastActivity": null
      }
    ],
    "chats": [
      {
        "id": 206,
        "dialogId": "chat206",
        "name": "Company news",
        "type": "openChannel",
        "owner": 4,
        "role": "guest"
      }
    ],
    "messages": [
      {
        "id": 329393,
        "chatId": 206,
        "authorId": 4,
        "date": "2026-09-10T09:15:00+00:00",
        "text": "Quarterly results are published"
      }
    ],
    "recentConfigs": [
      { "chatId": 206, "sections": ["default", "openChannel", "channel"] }
    ],
    "hasNextPage": false
  }
}

Error response example

400 — the cursor is not a positive number:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "`lastMessageId` must be an integer, 1 or more — the smallest positive `messageId` among the rows of the previous page."
  }
}

Errors

HTTP Code Description
HTTP400 CodeINVALID_PARAMS DescriptionA parameter other than limit and lastMessageId, a repeated parameter, a non-numeric limit, or lastMessageId less than 1. 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

The list holds all public channels of the Bitrix24 account, not only yours. Channels the user is not a member of are returned too, with the guest role in data.chats[].role.

Channels without messages come last. Their messageId is 0, and they do not serve as a cursor. If such channels do not fit on one page of 200 rows, pagination cannot continue past them: the next page would have no cursor.

See also