
## Массовая загрузка сообщений

`POST /v1/chats/messages/bulk`

Загружает сообщения из нескольких диалогов одним запросом. Используется для синхронизации нескольких чатов без лишних вызовов API.

## Поля запроса (body)

| Поле | Тип | Обяз. | Описание |
|------|-----|:-----:|---------|
| `dialogs` | array | да | Массив диалогов для загрузки. От 1 до 50 элементов |
| `dialogs[].dialogId` | string | да | ID диалога: числовой ID пользователя, `chatXXX` или литерал `me`. В ответе результат приходит под тем значением, которое передано в запросе, — для `me` ключом будет `"me"` |
| `dialogs[].lastId` | number | нет | Курсор для загрузки более старых сообщений |
| `dialogs[].firstId` | number | нет | Курсор для загрузки более новых сообщений |
| `dialogs[].limit` | number | нет | Количество сообщений для этого диалога (не более 200) |

## Примеры

### curl — личный ключ

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/chats/messages/bulk" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dialogs": [
      { "dialogId": "chat42", "limit": 20 },
      { "dialogId": "chat99", "lastId": 5000 }
    ]
  }'
```

### curl — OAuth-приложение

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/chats/messages/bulk" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "dialogs": [
      { "dialogId": "chat42", "limit": 20 },
      { "dialogId": "chat99", "lastId": 5000 }
    ]
  }'
```

### JavaScript — личный ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/chats/messages/bulk', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    dialogs: [
      { dialogId: 'chat42', limit: 20 },
      { dialogId: 'chat99', lastId: 5000 },
    ],
  }),
})

const { success, data } = await res.json()
console.log('Итог:', data.summary)
for (const [key, result] of Object.entries(data.results)) {
  console.log(`Диалог ${key}:`, result.messages.length, 'сообщений')
}
```

### JavaScript — OAuth-приложение

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/chats/messages/bulk', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    dialogs: [
      { dialogId: 'chat42', limit: 20 },
      { dialogId: 'chat99', lastId: 5000 },
    ],
  }),
})

const { success, data } = await res.json()
```

## Поля ответа

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true` при успехе |
| `data.results` | object | Словарь результатов: ключ — `dialogId` из запроса, значение — объект с сообщениями |
| `data.results.<dialogId>.chatId` | number | Числовой ID чата |
| `data.results.<dialogId>.messages` | array | Массив сообщений диалога (поля — как в [Чтении сообщений](/docs/chats/messages/list)) |
| `data.results.<dialogId>.users` | array | Участники диалога с профилями |
| `data.errors` | object | Словарь ошибок: ключ — `dialogId`, значение — объект с полем `code` |
| `data.summary.total` | number | Общее количество запрошенных диалогов |
| `data.summary.succeeded` | number | Количество успешно загруженных диалогов |
| `data.summary.failed` | number | Количество диалогов с ошибкой |

## Пример ответа

```json
{
  "success": true,
  "data": {
    "results": {
      "chat42": {
        "chatId": 42,
        "messages": [
          {
            "id": 1001,
            "chatId": 42,
            "authorId": 5,
            "date": "2026-06-05T10:00:00+03:00",
            "text": "Привет, команда!",
            "unread": false,
            "uuid": null,
            "replaces": [],
            "params": [],
            "disappearingDate": null
          }
        ],
        "users": [
          {
            "id": 5,
            "active": true,
            "name": "Иван Петров",
            "firstName": "Иван",
            "lastName": "Петров",
            "bot": false,
            "type": "user"
          }
        ],
        "files": []
      }
    },
    "errors": {},
    "summary": {
      "total": 1,
      "succeeded": 1,
      "failed": 0
    }
  }
}
```

## Пример ответа при ошибке

400 — массив `dialogs` отсутствует или пустой:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Body must contain \"dialogs\" array with at least 1 item. Each item: { dialogId, lastId?, firstId?, limit? }"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `INVALID_REQUEST` | Поле `dialogs` отсутствует, пустое, или элемент не содержит `dialogId` |
| 400 | `BATCH_LIMIT_EXCEEDED` | Превышено ограничение: более 50 диалогов в одном запросе |
| 422 | `BITRIX_ERROR` | Битрикс24 вернул ошибку при обработке всего пакетного запроса |
| 502 | `ME_ALIAS_RESOLUTION_FAILED` | Не удалось определить текущего пользователя для литерала `me`. Отклоняется весь пакет |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 недоступен или вернул ошибку сервера |
| 403 | `SCOPE_DENIED` | Ключу не хватает скоупа `im` |
| 401 | `TOKEN_MISSING` | Не передан `X-Api-Key` или не настроены токены |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Частичный успех.** Ошибка для отдельного диалога не прерывает обработку остальных. Проверяйте `data.errors` и `data.summary.failed` для обнаружения частичных сбоев.

**Ограничение 50 диалогов.** Определяется лимитом пакетных запросов Битрикс24. При необходимости обработать больше диалогов разбейте запрос на несколько частей.

**Ключи результата.** Ключи в `data.results` и `data.errors` соответствуют полю `dialogId` из запроса. Если вы передали несколько записей с одинаковым `dialogId`, результат будет только для последнего совпадения.

## Смотрите также

- [Сообщения](/docs/chats/messages)
- [Чтение сообщений](/docs/chats/messages/list)
- [Поиск чатов](/docs/chats/discovery/get)
