
## Search funnels

`POST /v1/categories/:entityTypeId/search`

Returns the pipelines of the specified CRM entity type. The parameters are passed in the request body rather than in the query string.

The same set of funnels is served by [`GET /v1/categories/:entityTypeId`](/docs/entities/categories/list).

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `entityTypeId` (path) | number | yes | CRM entity type identifier. Deals — `2`, contacts — `3`, companies — `4`, invoices — `31`, smart processes — the value from [`GET /v1/smart-processes`](/docs/entities/smart-processes/list) |

## Request fields (body)

| Field | Type | Required | Default | Description |
|------|-----|:-----:|-----------|---------|
| `limit` | number | no | `50` | Number of records, up to 5000 |
| `offset` | number | no | — | How many funnels to skip from the start of the list |
| `select` | string[] | no | — | Field selection: `["id", "name", "sort"]` |
| `filter` | object | no | — | Filtering works only by `code`, as an exact match: `{"code": "CATALOG_CONTRACTOR_COMPANY"}`. Only contact and company pipelines have a code. 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` |

## Examples

In the examples, `entityTypeId` is `2` (deals). Substitute the type you need.

### curl — personal key

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/categories/2/search" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "limit": 5 }'
```

### curl — OAuth application

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/categories/2/search" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "limit": 5 }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/categories/2/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ limit: 5 }),
})

const { success, data, meta } = await res.json()
console.log(`Pipelines of this type: ${meta.total}`)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/categories/2/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ limit: 5 }),
})

const { success, data, meta } = 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 identifier. For the main deal funnel it equals `0` |
| `data[].name` | string | Funnel name |
| `data[].sort` | number | Sort order |
| `data[].entityTypeId` | number | CRM entity type identifier, mirrors the path segment |
| `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_COMPANY`. `null` for the main pipeline and for user-created ones. Contact and company pipelines only |
| `meta.total` | number | Number of pipelines the type has |
| `meta.hasMore` | boolean | Whether pipelines remain beyond `limit` |
| `meta.durationMs` | number | Request duration in milliseconds |
| `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 — check that a key is present before reading it. Contacts (`3`) and companies (`4`) return `isSystem` and `code`. Invoices and smart processes return only the common fields.

## Response example

```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 },
    { "id": 3, "name": "Partners", "sort": 400, "entityTypeId": 2, "isDefault": false, "originId": null, "originatorId": null },
    { "id": 9, "name": "Tenders", "sort": 500, "entityTypeId": 2, "isDefault": false, "originId": null, "originatorId": null }
  ],
  "meta": {
    "total": 8,
    "hasMore": true,
    "durationMs": 1847
  }
}
```

## Error response example

404 — no CRM type with this `entityTypeId`:

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

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_DYNAMIC_PARAM` | `entityTypeId` in the path is not a positive integer |
| 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 |
| 404 | `ENTITY_NOT_FOUND` | `entityTypeId` does not match an existing CRM type |
| 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

**The order does not change, and there is no filtering by name.** `sort` and `order` in the body are accepted, but pipelines always come sorted by the `sort` field ascending. An unknown field name returns `400 UNKNOWN_SORT_FIELD`; valid names come from `GET /v1/categories/:entityTypeId/fields`. To find a pipeline by name, match its `name` in the returned array; to get a single known pipeline in full, use [`GET /v1/categories/:entityTypeId/:id`](/docs/entities/categories/get). A system contact or company pipeline is more reliably found by filtering on `code`: the code is the same across Bitrix24 accounts, while the `id` differs.

## See also

- [List funnels](/docs/entities/categories/list)
- [Get funnel](/docs/entities/categories/get)
- [Funnel fields](/docs/entities/categories/fields)
- [Stages and statuses](/docs/entities/statuses)
