
## List funnels

`GET /v1/categories/:entityTypeId`

Returns the funnels of the specified CRM entity type.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `entityTypeId` (path) | number | yes | CRM entity type ID. Deals — `2`, contacts — `3`, companies — `4`, invoices — `31`, smart processes — from [`GET /v1/smart-processes`](/docs/entities/smart-processes/list) |
| `select` (query) | string | no | Comma-separated response fields, for example `id,name`. Without the parameter, all fields are returned. The `id` field is always returned. Names come from [Pipeline fields](/docs/entities/categories/fields) |
| `limit` (query) | number | no | How many pipelines to return. `50` by default, `5000` maximum |
| `offset` (query) | number | no | How many pipelines to skip from the start of the list: `?offset=1` starts from the second pipeline |
| `sort` (query) | string | no | Accepted but does not change the order: pipelines always come sorted by the `sort` field ascending. The field name is checked against [Pipeline fields](/docs/entities/categories/fields), and an unknown one returns `400 UNKNOWN_SORT_FIELD`. The same applies to the `order` object: `?order[sort]=desc` |
| `filter` (query) | object | no | Filtering works only by `code`, as an exact match: `?filter[code]=CATALOG_CONTRACTOR_CONTACT`. Only contact and company pipelines have a code, so for other types this filter returns an empty list. Other filter fields are accepted but do not narrow the result. An unknown field name returns `400 UNKNOWN_FILTER_FIELD`; valid names come from `GET /v1/categories/:entityTypeId/fields`.<br>[Filtering syntax](/docs/filtering) |
| `withTotal` (query) | string | no | Accepted but does not affect the response: `meta.total` is returned for any value and any `offset` |

## Examples

The examples use `entityTypeId = 2` (deals); replace it with the type you need.

### curl — personal key

```bash
curl -X GET https://vibecode.bitrix24.com/v1/categories/2 \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl -X GET https://vibecode.bitrix24.com/v1/categories/2 \
  -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/categories/2', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

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

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/categories/2', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

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

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of funnels for the type |
| `data[].id` | number | Funnel ID. For deals the main funnel has ID `0` |
| `data[].name` | string | Funnel name |
| `data[].sort` | number | Sort order |
| `data[].entityTypeId` | number | CRM entity type ID, mirrors the path parameter |
| `data[].isDefault` | boolean | Marks the main pipeline of the type |
| `data[].originId` | string \| null | External identifier. `null` for pipelines with no external binding. Deal pipelines only |
| `data[].originatorId` | string \| null | Source of the external binding. `null` for pipelines with none. Deal pipelines only |
| `data[].isSystem` | string | System pipeline: `Y` — created by Bitrix24, `N` — created by a user. Contact and company pipelines only. |
| `data[].code` | string \| null | Symbolic code of a system pipeline, for example `CATALOG_CONTRACTOR_CONTACT`. `null` for the main pipeline and for user-created ones. Contact and company pipelines only |
| `meta.total` | number | How many pipelines the type has in total — independent of `limit` and `offset` |
| `meta.hasMore` | boolean | Whether pipelines remain beyond the current page |
| `meta.warnings` | array | Returned when `select` lists a name that is absent from the pipeline schema, or the `createdDate` field, which Bitrix24 does not return. The request still runs: a field with an unknown name comes back for the pipelines that have it, and is absent for the rest. Each warning is an object with `code`, `field` and `message`, and the code is `UNKNOWN_SELECT_FIELD` |

The field set depends on the entity type. Deals return `originId` and `originatorId`, except for the main pipeline (id `0`). Contacts (`3`) and companies (`4`) return `isSystem` and `code`. Invoices and smart processes return only the common fields. The `createdDate` field from the [pipeline schema](/docs/entities/categories/fields) is not returned for any type, even when listed in `select`.

For deals (`entityTypeId = 2`), get the stages of the main pipeline (`id = 0`) from `GET /v1/statuses?filter[entityId]=DEAL_STAGE` and the stages of an additional pipeline (`id = N`) from `GET /v1/statuses?filter[entityId]=DEAL_STAGE_{id}` (for example, `id = 1` → `DEAL_STAGE_1`). This deal-stage directory naming rule does not apply to invoices or smart processes.

## Response example

The response always contains `meta`. Additional deal funnels have `originId` and `originatorId`; the main funnel (id `0`) does not:

```json
{
  "success": true,
  "data": [
    { "id": 1, "name": "Newest", "sort": 100, "entityTypeId": 2, "isDefault": false, "originId": null, "originatorId": null },
    { "id": 11, "name": "English", "sort": 200, "entityTypeId": 2, "isDefault": false, "originId": null, "originatorId": null },
    { "id": 0, "name": "General", "sort": 300, "entityTypeId": 2, "isDefault": true }
  ],
  "meta": { "total": 3, "hasMore": false }
}
```

Smart process funnels have a shorter set of fields:

```json
{
  "success": true,
  "data": [
    { "id": 3, "name": "General", "sort": 500, "entityTypeId": 174, "isDefault": true },
    { "id": 23, "name": "Extra pipeline", "sort": 510, "entityTypeId": 174, "isDefault": false }
  ],
  "meta": { "total": 2, "hasMore": false }
}
```

Company and contact pipelines come back with `isSystem` and `code`:

```json
{
  "success": true,
  "data": [
    { "id": 0, "name": "Default pipeline", "sort": 0, "entityTypeId": 4, "isDefault": true, "isSystem": "Y", "code": null },
    { "id": 17, "name": "Vendors", "sort": 500, "entityTypeId": 4, "isDefault": false, "isSystem": "Y", "code": "CATALOG_CONTRACTOR_COMPANY" }
  ],
  "meta": { "total": 2, "hasMore": false }
}
```

## Error response example

404 — type not found:

```json
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "Smart process not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 404 | `ENTITY_NOT_FOUND` | `entityTypeId` does not match an existing CRM type |
| 400 | `UNKNOWN_FILTER_FIELD` | `filter` names a field the pipeline does not have. The message lists the valid names |
| 400 | `UNKNOWN_SORT_FIELD` | `sort` or `order` names a field the pipeline does not have. The message lists the valid names |
| 422 | `BITRIX_ERROR` | The CRM type does not support pipelines. Quotes (type `7`) have no pipelines |
| 403 | `SCOPE_DENIED` | The API key lacks the `crm` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |
| 429 | `RATE_LIMITED` | Rate limit exceeded: 300 requests per minute per portal. All API keys of the portal share one limit. The current limit is returned in the `x-ratelimit-limit` header. Retry after the delay in the `Retry-After` header |

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

## Known specifics

**Sort and filter by name on the client side.** The server filters pipelines only by `code` and always sorts them by the `sort` field in ascending order. To find a pipeline by name, search `data`: `data.filter(c => c.name === 'Sales')`.

**Find a system pipeline by `code`, not by `id`.** Bitrix24 sets the code of a system pipeline, such as `CATALOG_CONTRACTOR_COMPANY`, and it is the same across Bitrix24 accounts. The `id` of the same system pipeline differs from one account to another.

**Paging is relative to the full list for the type.** `meta.total` reports how many funnels the type has in total and does not change with `limit` or `offset` — walk the list until `meta.hasMore` is `false`.

## See also

- [Search funnels](/docs/entities/categories/search)
- [Get funnel](/docs/entities/categories/get)
- [Create funnel](/docs/entities/categories/create)
- [Funnel fields](/docs/entities/categories/fields)
- [Smart process types](/docs/entities/smart-processes)
- [Stages and statuses](/docs/entities/statuses)
- [Entity API](/docs/entity-api)
