For AI agents: markdown of this page — /docs-content-en/chats/messages/initial.md documentation index — /llms.txt
First page of a chat
GET /v1/chats/:dialogId/messages/initial
Returns the page of messages that the messenger shows when it opens a chat — the v2 messenger method im.v2.Chat.Message.list. The page is built around the "unread" mark or, when there is none, around the last read message. Use it to open a chat where the user left off, without a separate request for the chat itself; the chat together with pinned messages comes from loading a chat.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
dialogId (path) |
string | yes | — | Dialog ID: numeric user ID for personal messages, chatXXX for group chats. The me alias addresses the current user's personal dialog. The user's dialogs are in the list of recent dialogs (GET /v1/chats/recent) |
limit (query) |
number | no | 50 | How many messages to take on each side of the anchor message. From 1 to 200: an out-of-range value is clamped and echoed in meta.requestedLimit and meta.appliedLimit |
ignoreMark (query) |
boolean | no | false |
true — build the page around the last read message, ignoring the "unread" mark |
Any other parameter or a repeated parameter is rejected with 400 INVALID_PARAMS.
Examples
curl — personal key
curl "https://vibecode.bitrix24.com/v1/chats/chat42/messages/initial?limit=20" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl "https://vibecode.bitrix24.com/v1/chats/chat42/messages/initial?limit=20" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/chat42/messages/initial?limit=20', {
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data } = await res.json()
console.log('Messages:', data.messages.map((m) => m.id), 'has older:', data.hasPrevPage)
JavaScript — OAuth application
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/chat42/messages/initial?limit=20', {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { data } = await res.json()
console.log('Messages:', data.messages.map((m) => m.id), 'has older:', data.hasPrevPage)
Response fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true on success |
data.messages |
array | Messages on the page, from oldest to newest |
data.messages[].id |
number | Message ID |
data.messages[].chatId |
number | Chat ID |
data.messages[].authorId |
number | Author ID. 0 — a system message |
data.messages[].date |
string | Send date (ISO 8601) |
data.messages[].text |
string | Message text |
data.messages[].unread |
boolean | Not read by the current user |
data.messages[].viewed |
boolean | Viewed by the current user |
data.messages[].viewedByOthers |
boolean | Viewed by one of the members |
data.additionalMessages |
array | Messages that the page's messages reply to, when they are not on the page themselves |
data.users |
array | Authors of the page's messages |
data.usersShort |
array | Short profiles of the page's users |
data.files |
array | Files of the page's messages |
data.reactions |
array | Reactions to the page's messages |
data.stickers |
array | Stickers of the page's messages |
data.tariffRestrictions.isHistoryLimitExceeded |
boolean | History older than the plan allows is hidden |
data.hasPrevPage |
boolean | There are messages older than the page |
data.hasNextPage |
boolean | There are messages newer than the page |
meta.requestedLimit |
number | The passed limit, when it falls outside the range from 1 to 200 |
meta.appliedLimit |
number | The applied limit value |
Response example
{
"success": true,
"data": {
"messages": [
{
"id": 1001,
"chatId": 42,
"authorId": 5,
"date": "2026-09-20T10:00:00+00:00",
"text": "Please review the mockup",
"params": {}
},
{
"id": 1002,
"chatId": 42,
"authorId": 7,
"date": "2026-09-20T10:01:00+00:00",
"text": "All done",
"params": {}
}
],
"additionalMessages": [],
"users": [],
"usersShort": [],
"files": [],
"reactions": [],
"stickers": [],
"tariffRestrictions": { "isHistoryLimitExceeded": false },
"hasPrevPage": true,
"hasNextPage": false
}
}
Error response example
422 — the chat does not exist in the Bitrix24 account:
{
"success": false,
"error": {
"code": "BITRIX_ERROR",
"message": "CHAT_NOT_FOUND",
"b24Code": "CHAT_NOT_FOUND"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_PARAMS |
A parameter other than limit and ignoreMark, a repeated parameter or an invalid value. Checked before any call to Bitrix24 |
| 404 | ENTITY_NOT_FOUND |
Bitrix24 returned the NOT_FOUND code; the portal code is in error.b24Code |
| 422 | BITRIX_ERROR |
Bitrix24 returned an error; the portal code is in error.b24Code. A missing chat lands here too: CHAT_NOT_FOUND |
| 502 | ME_ALIAS_RESOLUTION_FAILED |
Failed to resolve the user for the me alias |
| 403 | BITRIX_ACCESS_DENIED |
The user has no access to the chat — Bitrix24 refused with the ACCESS_DENIED code |
| 403 | SCOPE_DENIED |
The API key does not have the im scope |
| 403 | WRITE_BLOCKED_READONLY_KEY |
Message.list grants Drive quick access, so a read-only key cannot call it; use the v2 feed |
| 401 | TOKEN_MISSING |
The API key has no Bitrix24 tokens configured |
Full list of common API errors — Errors.
Known specifics
The initial page may change state. Beyond conditional auto-join, Message.list grants quick access to Drive files. That is a separate side effect, so a READONLY key gets 403 WRITE_BLOCKED_READONLY_KEY. The v2 feed supports the first page and pagination without that grant.
The limit is per side. limit sets the number of messages before the anchor message and after it, so the page can be almost twice the size of limit.
Response keys. Keys that name fields are converted to camelCase: the FILE_ID message parameter arrives as fileId. Keys that are data stay as they are: the data.copilot.roles dictionary is keyed by the role code, and copilot_assistant arrives as copilot_assistant.
Continue in the message history. Read older messages from the message history in the v2 mode, passing lastId equal to the smallest id on the page, and newer ones with order=asc and lastId equal to the largest.