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

Product search

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 built from several conditions and for programmatic request assembly. 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
filter object Exact match and $in (IN set) only, on the fields id, name, code, xmlId, active, sectionId, sort. 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 }
limit number 50 Number of records (up to 5000)
offset number 0 Skip N records
order object Sorting by the fields id, name, sort: { "sort": "desc" }. The fields price and currency do not support sorting
select string[] Field selection: ["id", "name", "price"]

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 of 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
success boolean Always true on success
data array Array of products (all fields — see Product fields)
meta.total number Total number of products matching the filter
meta.hasMore boolean Whether there are more records beyond limit
meta.durationMs number Request duration in milliseconds

The meta fields sit next to data, not inside it. Pages must be walked by 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 account 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."
  }
}

Errors

HTTP Code Description
400 UNSUPPORTED_FILTER An operator or unsupported field in the filter. Filter by exact match or $in on id, name, code, xmlId, active, sectionId, sort
400 INVALID_FILTER Error while parsing the filter
403 SCOPE_DENIED The API key lacks the crm scope
401 MISSING_API_KEY The X-Api-Key header was not passed

Full list of common API errors — 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 are not included in the response. The data array contains the standard product fields. To get the values of the PROPERTY_<N> properties, request the product by identifier via GET /v1/products/:id.

See also