
## List members

`GET /v1/chats/:dialogId/users`

Returns the list of dialog members.

The generic `filter` parameter is not applied by this endpoint. By default, the API preserves the previous HTTP 200 response and data, adds `Warning: 299 - "filter is not supported on this endpoint and was ignored"`, and records unsupported-filter use in the server log.
Parameter validation for `format=v2` remains unchanged.

## Parameters

| Parameter | Type | Required | Default | Description |
|----------|-----|:-----:|-----------|---------|
| `dialogId` (path) | string | yes | — | Dialog identifier: `chatXXX` for a group chat, a user ID for the personal dialog with that user, or the alias `me` for the personal dialog with yourself |
| `limit` (query) | number | no | `50` | Number of members, from 1 to 200. An out-of-range value is clamped and echoed in `meta.requestedLimit` and `meta.appliedLimit` |
| `offset` (query) | number | no | `0` | Offset from the start of the list. Rejected in the v2 mode |
| `lastId` (query) | number | no | — | ID of the last received member — an alternative to `offset` for paginated traversal. Rejected in the v2 mode |
| `skipExternal` (query) | boolean | no | — | `true` — exclude external users (types `extranet`, `network`). Rejected in the v2 mode |
| `format` (query) | string | no | — | `v2` turns on the v2 mode — see "The v2 mode" below. Any other value is ignored and the response is unchanged. A repeated `format` is not rejected: with `format=v1&format=v2` the last value wins, so the v2 mode is on, while `format=v2&format=v1` returns the regular response. The bracket form `format[]=v2` turns on the v2 mode when all its values are `v2` |
| `cursorRole` (query) | string | no | — | The v2 mode only: `data.nextCursor.role` of the previous page. Passed together with `cursorRelationId` |
| `cursorRelationId` (query) | number | no | — | The v2 mode only: `data.nextCursor.relationId` of the previous page — the page starts after that membership record. Passed together with `cursorRole` |

**The v2 mode.** `format=v2` reads the members through the v2 messenger. `data` carries `users` — the member cards, `relations` — the membership records with the role `owner`, `manager` or `member`, and `nextCursor` — the cursor of the next page; the keys are in camelCase. The owner comes first, then the managers, then the members. For the next page pass `cursorRole` and `cursorRelationId` from `data.nextCursor`. A full page always carries a cursor, so the list ends with a page whose `nextCursor` is `null`, and that page may be empty. The mode accepts only `format`, `limit` from 1 to 200, clamped and echoed, and the cursor pair; `offset`, `lastId` and `skipExternal` are rejected with `400 INVALID_PARAMS`. **The v2 mode may make you a member:** when the chat allows auto-join — a comment chat, a collab or a task chat, for example — the call adds the current user as a member, as [loading a chat](/docs/chats/messages/load) does. A `READONLY` key may use the v2 mode under two conditions: it is an employee personal key, and the chat is confirmed — `chatN` was passed or the personal dialog was found in the same employee's recent dialogs. The regular mode stays a plain read with no such conditions. The call does not mark messages as read.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/chats/chat123/users?limit=50" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/chats/chat123/users?limit=50" \
  -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/chat123/users?limit=50', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data } = await res.json()
console.log('Members:', data.length)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/chat123/users?limit=50', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { success, data } = await res.json()
console.log('Members:', data.length)
```

### curl — the v2 mode

```bash
curl "https://vibecode.bitrix24.com/v1/chats/chat123/users?format=v2&limit=50&cursorRole=member&cursorRelationId=77" \
  -H "X-Api-Key: YOUR_API_KEY"
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of members |
| `data[].id` | number | User ID |
| `data[].active` | boolean | Whether the account is active |
| `data[].name` | string | Full name |
| `data[].firstName` | string | First name |
| `data[].lastName` | string | Last name |
| `data[].workPosition` | string | Job position |
| `data[].color` | string | Avatar color |
| `data[].avatar` | string | Avatar URL (empty string if no avatar is set) |
| `data[].gender` | string | Gender (`M` — male, `F` — female, empty string — not specified) |
| `data[].birthday` | string | Birth date (empty string if not specified) |
| `data[].extranet` | boolean | External user (type `extranet`) |
| `data[].network` | boolean | Bitrix24 Network user |
| `data[].bot` | boolean | Bot |
| `data[].connector` | boolean | Open Channels user (Contact Center) |
| `data[].status` | string | Status (`online`, `away`, `dnd`) |
| `data[].idle` | boolean | Idle |
| `data[].lastActivityDate` | string | Last activity date (ISO 8601) |
| `data[].absent` | boolean | Absent according to the work calendar |
| `data[].departments` | number[] | List of department IDs |
| `data[].type` | string | User type (`user`, `bot`, `extranet`) |
| `data.users` | array | The v2 mode: the member cards of the page — the same fields as the `data[]` elements of the regular mode |
| `data.relations` | array | The v2 mode: the membership records of the page |
| `data.relations[].id` | number | The v2 mode: membership record ID |
| `data.relations[].userId` | number | The v2 mode: user ID |
| `data.relations[].chatId` | number | The v2 mode: chat ID |
| `data.relations[].role` | string | The v2 mode: `owner`, `manager` or `member` |
| `data.relations[].isHidden` | boolean | The v2 mode: whether the membership is hidden |
| `data.nextCursor` | object\|null | The v2 mode: the cursor of the next page — `role` and `relationId`; `null` — no more pages |
| `meta.requestedLimit` | number | The `limit` passed, when it was outside the range from 1 to 200 |
| `meta.appliedLimit` | number | The `limit` applied — only when it was clamped to a bound |

## Response example

Regular mode:

```json
{
  "success": true,
  "data": [
    {
      "id": 42,
      "active": true,
      "name": "John Brown",
      "firstName": "John",
      "lastName": "Brown",
      "workPosition": "Manager",
      "color": "#df532d",
      "avatar": "",
      "gender": "M",
      "birthday": "",
      "extranet": false,
      "network": false,
      "bot": false,
      "connector": false,
      "status": "online",
      "idle": false,
      "lastActivityDate": "2026-06-05T09:40:32+00:00",
      "absent": false,
      "departments": [1, 47],
      "type": "user"
    },
    {
      "id": 53,
      "active": true,
      "name": "Maria Davis",
      "firstName": "Maria",
      "lastName": "Davis",
      "workPosition": "Analyst",
      "color": "#83c3f7",
      "avatar": "",
      "gender": "F",
      "birthday": "",
      "extranet": false,
      "network": false,
      "bot": false,
      "connector": false,
      "status": "away",
      "idle": false,
      "lastActivityDate": "2026-06-04T18:15:00+00:00",
      "absent": false,
      "departments": [1],
      "type": "user"
    }
  ]
}
```

The v2 mode, the response to the "curl — the v2 mode" request above: the page after the cursor is the last one, so `nextCursor` is `null`. The cards in `users` are shortened; the full set of fields is the same as in the regular mode:

```json
{
  "success": true,
  "data": {
    "users": [
      { "id": 42, "active": true, "name": "John Brown", "firstName": "John", "lastName": "Brown", "type": "user" },
      { "id": 53, "active": true, "name": "Maria Davis", "firstName": "Maria", "lastName": "Davis", "type": "user" }
    ],
    "relations": [
      { "id": 81, "userId": 42, "chatId": 123, "isHidden": false, "role": "member" },
      { "id": 95, "userId": 53, "chatId": 123, "isHidden": false, "role": "member" }
    ],
    "nextCursor": null
  }
}
```

## Error response example

422 — Bitrix24 error (no access to the dialog):

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Access denied"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 200 | `Warning: 299` | The filter is ignored by default; previous data is preserved and the warning is sent in the `Warning` header. |
| 400 (strict mode only) | `UNSUPPORTED_FILTER` | The server mode is disabled by default; until it is enabled, the endpoint preserves HTTP 200 and the previous data. |
| 400 | `INVALID_PARAMS` | The v2 mode only: a parameter other than `format`, `limit`, `cursorRole`, `cursorRelationId`, a repeated parameter other than `format`, a non-numeric `limit`, one half of the cursor pair without the other, a role other than `owner`, `manager`, `member`, or a `cursorRelationId` that is not a positive integer. Checked before any call to Bitrix24 |
| 403 | `SCOPE_DENIED` | The API key does not have the `im` scope |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The v2 mode: a read-only key, and the chat is not confirmed — a value other than `chatN` was passed and the personal dialog was not found in the same employee's recent dialog list, up to 20 pages and 4000 rows, or the alias creates a dialog. Rejected before any call to Bitrix24 |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The v2 mode: a read-only key that is not an employee personal key — an application key with a user session, a [management key](/docs/management-keys), or a key with an unconfirmed owner |
| 401 | `TOKEN_MISSING` | The API key has no configured Bitrix24 tokens |
| 404 | `ENTITY_NOT_FOUND` | The v2 mode: Bitrix24 returned "not found"; the portal code is in `error.b24Code` |
| 422 | `BITRIX_ERROR` | Bitrix24 returned an error — the text is in the `message` field (for example, no access to the dialog). In the v2 mode the portal code arrives in `error.b24Code`; a missing chat — `CHAT_NOT_FOUND` |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a server error |
| 502 | `ME_ALIAS_RESOLUTION_FAILED` | Could not resolve the `me` alias — the token expired or Bitrix24 is unavailable |

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

## Known specifics

**Pagination via `lastId`.** When sequentially traversing large chats, pass `lastId` from the last item of the previous response instead of `offset`. This approach works more reliably during concurrent changes to chat membership.

**The `me` alias** returns members of the personal dialog with yourself — that is just you. For the membership of a group chat, pass `chatXXX`.

## See also

- [Chat members](/docs/chats/members)
- [Add members](/docs/chats/members/add)
- [Remove a member](/docs/chats/members/remove)
- [Chat management](/docs/chats/management)
- [Chats](/docs/chats)
