Для AI-агентов: markdown этой страницы — /docs-content/chats/discovery/sync.md индекс документации — /llms.txt
Изменения чатов с момента
GET /v1/chats/sync
Возвращает, что изменилось в чатах текущего пользователя начиная с указанного момента: новые и удалённые чаты, новые, изменённые и удалённые сообщения, закрепы. Подходит, чтобы догнать локальную копию чатов после перерыва, не перечитывая весь список.
Параметры
| Параметр | Тип | Обяз. | По умолч. | Описание |
|---|---|---|---|---|
lastDate (query) |
string | да | — | С какого момента читать изменения. Формат YYYY-MM-DDTHH:MM:SS со смещением или Z, без долей секунды. Для следующей страницы — navigationData.lastServerDate предыдущей |
lastId (query) |
integer | нет | — | navigationData.lastId предыдущей страницы, не меньше 0. На первой странице не передаётся |
limit (query) |
integer | нет | 50 | Записей журнала изменений на странице, от 1 до 200. Меньшее значение поднимается до 1, большее срезается до 200, оба раза с эхом в meta |
Другие параметры и повторы отклоняются с 400 INVALID_PARAMS.
Обход. Первую страницу запрашивайте с lastDate — моментом, до которого копия актуальна. Пока navigationData.hasMore равен true, запрашивайте следующую с lastDate, равным navigationData.lastServerDate, и lastId, равным navigationData.lastId. Пару lastServerDate и lastId последней страницы сохраните — с неё начнётся следующая синхронизация.
Примеры
curl — личный ключ
curl "https://vibecode.bitrix24.tech/v1/chats/sync?lastDate=2026-09-24T10:00:00Z&limit=200" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth-приложение
curl "https://vibecode.bitrix24.tech/v1/chats/sync?lastDate=2026-09-24T10:00:00Z&limit=200" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — личный ключ
let lastDate = '2026-09-24T10:00:00Z'
let lastId
const added = new Set()
for (;;) {
const url = new URL('https://vibecode.bitrix24.tech/v1/chats/sync')
url.searchParams.set('lastDate', lastDate)
url.searchParams.set('limit', '200')
if (lastId !== undefined) url.searchParams.set('lastId', String(lastId))
const res = await fetch(url, { headers: { 'X-Api-Key': 'YOUR_API_KEY' } })
const { data } = await res.json()
if (Array.isArray(data)) throw new Error('Incremental sync is unavailable; refresh the full recent-chat list')
for (const id of Object.values(data.messageSync.addedMessages)) added.add(id)
lastDate = data.navigationData.lastServerDate
lastId = data.navigationData.lastId
if (!data.navigationData.hasMore) break
}
JavaScript — OAuth-приложение
let lastDate = '2026-09-24T10:00:00Z'
let lastId
const added = new Set()
for (;;) {
const url = new URL('https://vibecode.bitrix24.tech/v1/chats/sync')
url.searchParams.set('lastDate', lastDate)
url.searchParams.set('limit', '200')
if (lastId !== undefined) url.searchParams.set('lastId', String(lastId))
const res = await fetch(url, {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { data } = await res.json()
if (Array.isArray(data)) throw new Error('Incremental sync is unavailable; refresh the full recent-chat list')
for (const id of Object.values(data.messageSync.addedMessages)) added.add(id)
lastDate = data.navigationData.lastServerDate
lastId = data.navigationData.lastId
if (!data.navigationData.hasMore) break
}
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | Всегда true при успехе |
data.chatSync.addedRecent |
object | Чаты, появившиеся в списке диалогов: ключ и значение — ID чата |
data.chatSync.addedChats |
object | Чаты, которые появились или изменились у пользователя: ключ и значение — ID чата |
data.chatSync.deletedChats |
object | Чаты, убранные из списка диалогов пользователя: ключ и значение — ID чата |
data.chatSync.completeDeletedChats |
object | Чаты, удалённые с портала: ключ и значение — ID чата |
data.chatSync.readAllChats |
boolean | Приходит со значением true, если за это время пользователь прочитал все чаты: сбросьте счётчики непрочитанного в локальной копии |
data.messageSync.addedMessages |
object | Новые сообщения: ключ и значение — ID сообщения |
data.messageSync.updatedMessages |
object | Изменённые сообщения: ключ и значение — ID сообщения |
data.messageSync.completeDeletedMessages |
object | Удалённые сообщения: ключ и значение — ID сообщения |
data.pinSync.addedPins |
object | Новые закреплённые сообщения: ключ и значение — ID закрепа |
data.pinSync.deletedPins |
object | Снятые закрепы сообщений: ключ и значение — ID закрепа |
data.userSync |
object | Изменения пользователей: updatedUsers и deletedUsers |
data.chats |
array | Карточки чатов из chatSync |
data.messages |
array | Сообщения из messageSync |
data.pins |
array | Закрепы сообщений из pinSync: id, messageId, chatId, authorId, dateCreate |
data.recentItems |
array | Строки списка диалогов для чатов из chatSync |
data.users |
array | Пользователи, упомянутые в изменениях |
data.dialogIds |
object | Соответствие ID чата и ID диалога: ключ — ID чата, значение — dialogId |
data.navigationData.lastServerDate |
string | lastDate для следующей страницы — момент последней записи журнала на этой странице |
data.navigationData.lastId |
number | lastId для следующей страницы |
data.navigationData.hasMore |
boolean | true — есть следующая страница |
meta.requestedLimit |
number | Переданный limit. Приходит вместе с appliedLimit, только когда значение вышло за диапазон от 1 до 200 |
meta.appliedLimit |
number | Применённый limit — только если он был приведён к границе |
Пример ответа
Показаны основные поля:
{
"success": true,
"data": {
"chatSync": {
"addedRecent": { "264431": 264431 },
"addedChats": { "264431": 264431 },
"deletedChats": { "264418": 264418 },
"completeDeletedChats": []
},
"messageSync": {
"addedMessages": { "609001": 609001 },
"updatedMessages": [],
"completeDeletedMessages": []
},
"pinSync": {
"addedPins": [],
"deletedPins": []
},
"userSync": {
"updatedUsers": [],
"deletedUsers": []
},
"messages": [
{
"id": 609001,
"chatId": 264431,
"authorId": 1,
"date": "2026-09-24T21:10:22+00:00",
"text": "Черновик плана готов"
}
],
"chats": [
{
"id": 264431,
"dialogId": "chat264431",
"name": "Подготовка релиза",
"type": "chat"
}
],
"dialogIds": { "264431": "chat264431" },
"navigationData": {
"lastServerDate": "2026-09-24T21:10:22+00:00",
"hasMore": false,
"lastId": 182091
}
}
}
Пример ответа при ошибке
400 — дата без смещения:
{
"success": false,
"error": {
"code": "INVALID_PARAMS",
"message": "`lastDate` must be a datetime YYYY-MM-DDTHH:MM:SS with a UTC offset (+03:00) or Z and no fractional seconds — `navigationData.lastServerDate` of the previous page."
}
}
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | INVALID_PARAMS |
Нет lastDate, lastDate не в формате YYYY-MM-DDTHH:MM:SS со смещением или Z либо с несуществующей датой или временем (2026-02-30, 24:00), lastId меньше 0, нечисловой limit, параметр вне lastDate, lastId, limit или повтор параметра. Проверяется до обращения к Битрикс24 |
| 422 | BITRIX_ERROR |
Битрикс24 вернул ошибку, код портала — в error.b24Code |
| 403 | BITRIX_ACCESS_DENIED |
Битрикс24 отказал в доступе |
| 403 | SCOPE_DENIED |
API-ключ не имеет скоупа im |
| 401 | TOKEN_MISSING |
API-ключ не имеет настроенных токенов Битрикс24 |
| 502 | BITRIX_UNAVAILABLE |
Битрикс24 недоступен или вернул ошибку сервера |
Полный список общих ошибок API — Ошибки.
Известные особенности
Пустая коллекция приходит массивом. Когда в группе изменений нет записей, вместо объекта приходит пустой массив: "updatedMessages": []. Читайте такие поля через Object.values, он одинаково работает с обоими видами.
Инкрементальный журнал не гарантирует четыре недели истории. Часть записей Битрикс24 хранится лишь около суток. После долгого перерыва, особенно близкого к суткам, перечитайте последние диалоги и нужную историю сообщений целиком, прежде чем доверять новой дельте.
Синхронизация может быть выключена на портале. Тогда data — пустой массив, а не объект с полями выше. В этом случае перечитывайте список целиком.
Это не события в реальном времени. Эндпоинт отвечает на вопрос «что изменилось с момента», а новые сообщения по мере появления приходят через опрос событий.