For AI agents: markdown of this page — /docs-content-en/entities/products/search.md documentation index — /llms.txt

Search CRM products

POST /v1/products/search

Search catalog products with filters and auto-pagination. Parameters are passed in the request body — this is more convenient for compound filters made up of several conditions and for building requests programmatically. For lists of up to 5000 records, GET /v1/products with a filter in query parameters also works.

Request fields (body)

Parameter Type Default Description
Parameterfilter Typeobject Default— DescriptionOnly exact match and $in (IN set) on the fields id, name, code, xmlId, active, sectionId, sort, description — the fields are described in CRM product fields. Operators (>, >=, <, <=, !, %, $ne, $contains, $nin) and filtering by other fields (price, currency) are not supported — 400 UNSUPPORTED_FILTER is returned.
Filtering syntax. Example: { "sectionId": 19, "active": true }
Parameterlimit Typenumber Default50 DescriptionNumber of records (up to 5000)
Parameteroffset Typenumber Default0 DescriptionSkip N records
Parametersort Typestring | object | string[] Default— DescriptionSorting supports the same formats as the list endpoint: "-name", { "name": "desc" }, or ["name"]. Supported fields: id, name, active, sort, sectionId, xmlId, code, description, descriptionType, createdBy, modifyBy, createdAt, updatedAt, plus catalog properties named PROPERTY_<n>
Parameterorder Typeobject Default— DescriptionSort map: { "sort": "desc" }. price, currency, catalogId, measure, VAT fields and image fields cannot be sorted: every spelling, including raw PRICE, returns 400 UNKNOWN_SORT_FIELD with the supported-field list
Parameterselect Typestring[] Default— DescriptionField selection: ["id", "name", "price"]. A custom catalog property is requested by its own name: ["id", "name", "PROPERTY_301"]. Property names are listed in CRM product fields

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/products/search" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": { "active": true },
    "limit": 20,
    "order": { "sort": "desc" }
  }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/products/search" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": { "active": true },
    "limit": 20,
    "order": { "sort": "desc" }
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/products/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filter: { active: true },
    limit: 20,
    order: { sort: 'desc' },
  }),
})

const { success, data, meta } = await res.json()
console.log('Found:', meta.total)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/products/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filter: { active: true },
    limit: 20,
    order: { sort: 'desc' },
  }),
})

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

Other scenarios

Products from a single catalog section:

JSON
{ "filter": { "sectionId": 19 } }

Several products by identifiers via $in:

JSON
{ "filter": { "id": { "$in": [6967, 533] } } }

Response fields

Field Type Description
Fieldsuccess Typeboolean DescriptionAlways true on success
Fielddata Typearray DescriptionArray of products (all fields — see CRM product fields)
Fieldmeta.total Typenumber DescriptionTotal number of records matching the filter
Fieldmeta.hasMore Typeboolean DescriptionWhether there are more records beyond limit
Fieldmeta.durationMs Typenumber DescriptionRequest duration in milliseconds

The meta fields sit next to data, not inside it. Page through the results using meta.hasMore: a data length equal to limit does not rule out the last page.

The card URL of any product from the data array is built from catalogId and id: https://<portal>.bitrix24.com/shop/catalog/<catalogId>/product/<id>/. <portal> is the Bitrix24 portal domain. Access is restricted by the employee's permissions in Bitrix24.

Response example

JSON
{
  "success": true,
  "data": [
    {
      "id": 6967,
      "name": "Master product",
      "code": "product_sku",
      "active": true,
      "sort": 100,
      "xmlId": "6967",
      "catalogId": 25,
      "sectionId": null,
      "price": 100,
      "currency": "USD",
      "vatId": null,
      "vatIncluded": false,
      "createdAt": "2025-05-12T09:03:15.000Z",
      "updatedAt": "2025-05-12T09:05:27.000Z"
    },
    {
      "id": 6969,
      "name": "Service",
      "code": "service",
      "active": true,
      "catalogId": 25,
      "price": 250,
      "currency": "USD",
      "vatId": 1,
      "vatIncluded": true,
      "createdAt": "2025-05-12T09:04:01.000Z",
      "updatedAt": "2025-05-12T09:04:01.000Z"
    }
  ],
  "meta": { "total": 19, "hasMore": true, "durationMs": 2509 }
}

Error response example

400 — an operator or unsupported field in the filter:

JSON
{
  "success": false,
  "error": {
    "code": "UNSUPPORTED_FILTER",
    "message": "UNSUPPORTED_FILTER: operators are not supported on 'products' (near 'price'). Its Bitrix24 method (crm.product.list) filters by exact match only — operators are silently ignored by Bitrix24. Use exact match (field: value) or $in (field: {$in: [...]}) on: id, name, code, xmlId, active, sectionId, sort, description."
  }
}

Errors

HTTP Code Description
HTTP400 CodeUNSUPPORTED_FILTER DescriptionAn operator or unsupported field in the filter. Filter by exact match or $in on id, name, code, xmlId, active, sectionId, sort, description
HTTP400 CodeINVALID_FILTER DescriptionError while parsing the filter
HTTP400 CodeUNKNOWN_SORT_FIELD DescriptionSorting by a field the product cannot be sorted by — price, currency, catalogId, measure, VAT and image fields in any spelling, including raw PRICE and CATALOG_ID. The message lists the available fields after the word Available
HTTP400 CodeUNKNOWN_SELECT_FIELD Descriptionselect carries a name the product does not have. The message lists the allowed names after the word Available
HTTP400 CodeSELECT_FIELD_NOT_RETURNED Descriptionselect carries a name that CRM product fields shows with notReturned: true — currencyId, for example. Drop it from select
HTTP403 CodeSCOPE_DENIED DescriptionThe API key lacks the crm scope
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header was not passed
HTTP429 CodeRATE_LIMITED DescriptionRate 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 common API errors, see Errors.

Known specifics

Auto-pagination. When limit > 50, the request is automatically split into several calls to Bitrix24, up to 5000 records per call. When more records match the filter, meta.hasMore equals true — increase offset for the next batch.

Catalog properties arrive only when named. Without select, the data array contains the base product fields. Name every property you need in select — ["id", "name", "PROPERTY_295"]. A select containing an asterisk does not return them.

See also