## Messages around a message

`GET /v1/chats/messages/:messageId/context`

Returns a message and its neighbours. Use it to open a chat at a specific message: from a link, from search or from a reply. The chat is resolved from the message, so no `dialogId` is needed.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|---------|
| `messageId` (path) | number | yes | — | Message ID, a positive integer — the `id` field of a message from the [message history](/docs/chats/messages/list) or [chat loading](/docs/chats/messages/load) |
| `range` (query) | number | no | 50 | How many messages to take on each side: up to `range` messages before the given one, the message itself and up to `range` after. From 1 to 200: a value outside the range is clamped and echoed in `meta.requestedRange` and `meta.appliedRange` |

Any other parameter or a repeated parameter is rejected with `400 INVALID_PARAMS`.

**Read-only key.** In `READONLY` mode this request reads an existing chat by `messageId`: the chat is resolved from the message, and no `dialogId` is passed. The read effects — auto-join and a presence update — are described below, under "Opening the context may make you a member".

This exception for named reads applies only to an ordinary employee personal key, whether it uses a webhook or previously configured OAuth tokens. In `READONLY` mode, an application key with a user Bearer session, a management key, or a key whose owner type is unconfirmed receives `403 WRITE_BLOCKED_READONLY_KEY` before the existing-chat binding is checked and the named messenger method is called. Ordinary reads without these effects remain available to application keys; keys in read-write mode are unaffected.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/chats/messages/1002/context?range=10" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/chats/messages/1002/context?range=10" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/messages/1002/context?range=10', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const { data } = await res.json()
console.log('Messages:', data.messages.map((m) => m.id))
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/messages/1002/context?range=10', {
  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))
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data.messages` | array | The given message and its neighbours |
| `data.messages[].id` | number | Message ID — the `lastId` cursor for the next page and the `messageId` for [messages around a message](/docs/chats/messages/context) |
| `data.messages[].chatId` | number | Chat ID — equals `data.chat.id` in the [chat loading](/docs/chats/messages/load) response |
| `data.messages[].authorId` | number | Author ID — the profile is in `data.users` of the same response or can be fetched [by user ID](/docs/entities/users/get). `0` — a system message |
| `data.messages[].date` | string | Date sent (ISO 8601) |
| `data.messages[].text` | string | Message text |
| `data.messages[].params` | object | Additional message parameters, keys in camelCase |
| `data.messages[].block` | object \| null | Blocks of a constructor message, the `elements` array. `null` for a plain message |
| `data.messages[].block.elements[].id` | string | Block ID — the `blockId` for [replacing](/docs/chats/messages/blocks-update) and [removing](/docs/chats/messages/blocks-delete) a block |
| `data.users` | array | Authors of the messages on the page |
| `data.files` | array | Files attached to the messages on the page |
| `data.reactions` | array | Reactions to the messages on the page |
| `data.hasPrevPage` | boolean | Whether there are messages older than this page |
| `data.hasNextPage` | boolean | Whether there are messages newer than this page |
| `meta.requestedRange` | number | The passed `range` before clamping. Present together with `meta.appliedRange` only when the passed value falls outside the range from 1 to 200 |
| `meta.appliedRange` | number | The applied `range` value — only when it was clamped to a bound |

## Response example

```json
{
  "success": true,
  "data": {
    "messages": [
      {
        "id": 1001,
        "chatId": 42,
        "authorId": 5,
        "date": "2026-09-20T10:00:00+00:00",
        "text": "Please check the mockup",
        "params": {},
        "block": null
      },
      {
        "id": 1002,
        "chatId": 42,
        "authorId": 7,
        "date": "2026-09-20T10:01:00+00:00",
        "text": "All done",
        "params": {},
        "block": null
      }
    ],
    "users": [],
    "files": [],
    "reactions": [],
    "hasPrevPage": false,
    "hasNextPage": true
  }
}
```

## Error response example

422 — the message does not exist in the Bitrix24 account:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "MESSAGE_NOT_FOUND",
    "b24Code": "MESSAGE_NOT_FOUND"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | `messageId` is not a positive integer, or the request has a parameter other than `range`, a repeated parameter or an invalid value. Checked before any call to Bitrix24 |
| 404 | `ENTITY_NOT_FOUND` | Bitrix24 returned "not found"; the portal code is in `error.b24Code` |
| 422 | `BITRIX_ERROR` | Bitrix24 returned an error; the portal code is in `error.b24Code`. A missing message lands here too: the portal sends `MESSAGE_NOT_FOUND` with no text, and `message` repeats the code, so it is not a 404 |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | In read-only mode, the named method is unavailable to application keys, management keys and keys whose owner type is unconfirmed; an ordinary employee personal key is permitted |
| 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 |
| 401 | `TOKEN_MISSING` | The API key has no Bitrix24 tokens configured |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

**Opening the context may make you a member.** When the message's chat allows auto-join, the call adds the current user as a member, as [loading a chat](/docs/chats/messages/load) does. A `READONLY` key may call this read operation as a targeted exception; the user's Bitrix24 access and the `im` scope are still checked. Bitrix24 updates the employee's online presence on this read. Opening the context does not itself mark the message as read. The exact boundaries of these effects are described in [access rights](/docs/access-rights).

**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` — the same value that `role` carries on a chat and a message in `data.copilot`, so you can look up a role directly with `roles[role]`. Fields inside a role are converted to camelCase.

**Continue in the message history.** Read older messages from the [message history in the v2 mode](/docs/chats/messages/list), passing `lastId` equal to the smallest `id` on the page, and newer ones with `order=asc` and `lastId` equal to the largest.

## See also

- [Load a chat](/docs/chats/messages/load)
- [Read messages](/docs/chats/messages/list)
