
## List employees

`GET /v1/users`

Returns the list of employees in your Bitrix24 account with support for filtering, sorting, and auto-pagination. The method does not return bots, mail users, or Open Channels users.

Besides the `user` scope, the method requires a Bitrix24 plan that includes Vibecode. On a Bitrix24 account without such a plan, the call returns `422 BITRIX_ERROR` with `error.b24Code` set to `FEATURE_NOT_AVAILABLE_ON_CURRENT_PLAN`, and retrying the request does not help. You can check the account's plan before the call: it is returned in the `data.tariff` field of [`GET /v1/me`](/docs/keys-auth/me).

## Parameters

| Parameter | Type | Default | Description |
|----------|-----|-----------|---------|
| `limit` | number | `50` | Number of records (up to 5000). When `limit > 50`, Vibecode automatically requests several pages from Bitrix24 |
| `offset` | number | `0` | Skip N records. When `offset > 0`, `limit ≤ 500` is recommended |
| `sort` | string | — | Comma-separated sort fields. The supported ordinary field is `id`: `?sort=id` for ascending order or `?sort=-id` for descending order. Multiple recognized fields are replaced with ascending `id` order and a warning |
| `order` | object | — | Sort object. The supported ordinary field is `id`: `?order[id]=desc`. Multiple recognized fields are replaced with ascending `id` order and a warning. If both `sort` and `order` are present, `sort` takes precedence |
| `filter` | object | — | Filtering by the fields from `GET /v1/users/fields`.<br>[Filtering syntax](/docs/filtering). Example: `?filter[name]=John` |
| `select` | string | — | Comma-separated response fields, for example `?select=id,name,email`. Without it, every field is returned. Names come from [Employee fields](/docs/entities/users/fields) |
| `include` | string | — | Related data to include: `department`. See the "Related data" section |

`UF_*` fields keep their passthrough behavior only for one page of results from Bitrix24: `limit ≤ 50` and `offset = 0`. Vibecode forwards such a field as-is but does not guarantee that a particular Bitrix24 account applies the order. With `limit > 50` or `offset > 0`, Vibecode replaces a `UF_*` sort with ascending `id` order and adds one `SORT_FALLBACK_TO_ID` warning for the `sort` field to `meta.warnings`. The same warning is returned for multiple recognized sort fields.

## Examples

### curl — personal key

```bash
curl -g "https://vibecode.bitrix24.com/v1/users?limit=10&filter[active]=true" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl -g "https://vibecode.bitrix24.com/v1/users?limit=10&filter[active]=true" \
  -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/users?limit=10&filter[active]=true', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data, meta } = await res.json()
console.log(`Found ${meta.total} employees`)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/users?limit=10&filter[active]=true', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

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

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of employees. Each element contains all fields — see [Employee fields](/docs/entities/users/fields) |
| `data[]._included` | object | The employee's related data. Returned only with the `include` parameter — see the "Related data" section |
| `meta.total` | number | Total number of records matching the filter |
| `meta.hasMore` | boolean | Whether there are more records beyond `limit` |
| `meta.warnings` | array | Warnings. Absent when there are no warnings |
| `meta.warnings[].code` | string | Machine-readable warning code. `SORT_FALLBACK_TO_ID` means the requested sort was replaced with ascending `id` order. `UNKNOWN_SELECT_FIELD` means `select` contains a name that is not an employee field |
| `meta.warnings[].field` | string | Request field the warning applies to. For `SORT_FALLBACK_TO_ID`, this is `sort`. For `UNKNOWN_SELECT_FIELD`, this is the unknown name from `select` |
| `meta.warnings[].message` | string | Warning explanation |

The profile URL of any employee in the `data` array is built from their `id`:

```
https://<portal>.bitrix24.com/company/personal/user/<id>/
```

`<portal>` — the Bitrix24 portal domain. Access is restricted by the employee's permissions in Bitrix24.

## Related data

To retrieve the employees' departments together with the list, use the `include` parameter in the GET request:

```
GET /v1/users?limit=2&include=department
```

Available include: `department`. The result is in the `_included.departments` field of each element of the `data` array: the departments from the employee's `departmentId` that [`GET /v1/departments`](/docs/entities/departments/list) returns. A department from `departmentId` that this list does not contain is left out of the array:

```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "Maria",
      "departmentId": [1, 107],
      "_included": {
        "departments": [
          { "id": 107, "name": "Sales", "sort": 800, "parentId": 1, "headId": 1 }
        ]
      }
    },
    {
      "id": 29,
      "name": "John",
      "departmentId": [],
      "_included": {
        "departments": []
      }
    }
  ],
  "meta": {
    "total": 64,
    "hasMore": true
  }
}
```

For more on includes, including the limit on selection size, see [Related data](/docs/includes).

## Response example

```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "xmlId": "28889266",
      "active": true,
      "name": "Maria",
      "lastName": null,
      "secondName": "Middle name",
      "email": "maria@example.com",
      "lastLogin": "2026-05-05T08:25:11.000Z",
      "dateRegister": "2020-04-20T00:00:00.000Z",
      "timeZone": "UTC",
      "isOnline": false,
      "timestampX": {},
      "lastActivityDate": {},
      "personalGender": "F",
      "personalPhoto": "https://cdn.bitrix24.com/.../photo.jpg",
      "personalMobile": "+12025550123",
      "workPosition": null,
      "departmentId": [1, 107, 47],
      "userType": "employee"
    },
    {
      "id": 29,
      "xmlId": "28936832",
      "active": true,
      "name": "John",
      "lastName": "Brown",
      "email": "john.brown@example.com",
      "departmentId": [1],
      "userType": "employee"
    }
  ],
  "meta": {
    "total": 30,
    "hasMore": true
  }
}
```

The main fields are shown. For the full list, see [Employee fields](/docs/entities/users/fields).

## Error response example

403 — no scope:

```json
{
  "success": false,
  "error": {
    "code": "SCOPE_DENIED",
    "message": "This endpoint requires 'user' scope"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_FILTER_FIELD` | Filter by a nonexistent field — the field list is in `GET /v1/users/fields` |
| 400 | `UNKNOWN_SORT_FIELD` | A single ordinary sort field differs from `id`, including the declared `isOnline` and `isAdmin` fields. Multiple recognized fields are instead replaced with ascending `id` order and a `SORT_FALLBACK_TO_ID` warning. In the single-field case, the request is not sent to Bitrix24. |
| 400 | `INVALID_SORT_FIELD` | A sort field name is unsafe or malformed |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |
| 403 | `SCOPE_DENIED` | The API key lacks the `user` scope |
| 422 | `BITRIX_ERROR` | `error.b24Code` is `FEATURE_NOT_AVAILABLE_ON_CURRENT_PLAN`: the Bitrix24 account's plan does not include Vibecode. Retrying does not help. The account's plan is in the `data.tariff` field of `GET /v1/me` |
| 429 | `RATE_LIMITED` | This route allows 300 requests per minute per portal, shared by all API keys of the portal. The current route limit is returned in the `x-ratelimit-limit` header. Retry after the delay in the `Retry-After` header |

For the full list of common API errors, see [Errors](/docs/errors).

## Known specifics

**Sorting.** Vibecode guarantees employee order only by `id`. The `id` and `-id` values preserve the requested direction and add no warning. A single-page `UF_*` sort keeps its passthrough behavior for backward compatibility. With multiple recognized fields or a multi-page `UF_*` sort, the request succeeds with ascending `id` order and one `SORT_FALLBACK_TO_ID` warning. A single ordinary field other than `id` still returns `UNKNOWN_SORT_FIELD`. A Bitrix24 error remains an error response.

**Semantics of `filter[active]`.** `active: true` excludes deactivated employees. Bitrix24 does not interpret `active: false` as "deactivated only" — it returns all employees. To get only deactivated ones, filter the result on the client side by the `active` field.

**`WORK_*` fields and some `PERSONAL_*` fields arrive in `UPPER_SNAKE_CASE`.** `WORK_COMPANY`, `WORK_DEPARTMENT`, `WORK_WWW`, `WORK_FAX`, `WORK_CITY`, `WORK_STATE`, `WORK_ZIP`, `WORK_COUNTRY`, and the like. `PERSONAL_STATE`, `PERSONAL_ZIP`, `PERSONAL_COUNTRY`, `PERSONAL_MAILBOX`, and `PERSONAL_NOTES` arrive with their original Bitrix24 names. UF fields of the Bitrix24 account also keep their names. Standard fields (`name`, `email`, `active`, `timeZone`, `userType`, `departmentId`, etc.) use `camelCase`.

**The `lastActivityDate` field (declared `datetime`).** In practice it arrives as an **empty object `{}`**, or the key is **absent** altogether — an ISO string for this field has not been observed in checks. `{}` is a truthy value in JS, so `if (u.lastActivityDate)` gives a false positive. Same for `timestampX` (always `{}`). Do not parse it as a date and do not rely on a truthy check. Compare the type (`typeof x === 'string'`). See the summary of "empty" values in datetime fields in the [entity overview](/docs/entities/users) (item 7).

## See also

- [Get employee](/docs/entities/users/get)
- [Search employees](/docs/entities/users/search)
- [Employee fields](/docs/entities/users/fields)
- [Filtering syntax](/docs/filtering)
- [Entity API](/docs/entity-api)
- [Limits and optimization](/docs/optimization)
