[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"docs-entities\u002Fproducts\u002Flist":3,"docs-tabs-entities\u002Fproducts\u002Flist":6},{"content":4,"lastmod":5},"## List CRM products\n\n`GET \u002Fv1\u002Fproducts`\n\nReturns a list of CRM catalog products with support for filtering, sorting, and automatic paging.\n\nBy default a list item contains the base product fields. Custom catalog properties `PROPERTY_\u003CN>` arrive in the same item when you name each one in `select`.\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|----------|-----|-----------|---------|\n| `limit` | number | `50` | Number of records (up to 5000). When `limit > 50`, the request is automatically assembled from multiple pages on the server side |\n| `offset` | number | `0` | Offset from the start of the result set |\n| `select` | string | — | Field selection: `?select=id,name,price,active`. A custom catalog property is requested by its own name: `?select=id,name,price,PROPERTY_301`. Property names are listed in [CRM product fields](.\u002Ffields.md) |\n| `sort` | string | — | Sorting via the short syntax: `?sort=-sort`; a leading minus means descending. Supported fields: `id`, `name`, `active`, `sort`, `sectionId`, `xmlId`, `code`, `description`, `descriptionType`, `createdBy`, `modifyBy`, `createdAt`, `updatedAt`, plus catalog properties named `PROPERTY_\u003Cn>` |\n| `order` | object | — | Sorting in object form. Example: `?order[sort]=desc`, `?order[name]=asc`. `price`, `currency`, `catalogId`, `measure`, VAT fields and image fields cannot be sorted: every spelling, including the raw name `PRICE`, returns `400 UNKNOWN_SORT_FIELD` with the supported-field list |\n| `filter` | object | — | Only exact equality and `$in` (IN-set) on the `id`, `name`, `code`, `xmlId`, `active`, `sectionId`, `sort`, `description` fields. Operators (`>`, `>=`, `\u003C`, `\u003C=`, `!`, `%`, `$ne`, `$contains`, `$nin`) and filtering by other fields (`price`, `currency`) are not supported — `400 UNSUPPORTED_FILTER` is returned.\u003Cbr>[Filtering syntax](\u002Fdocs\u002Ffiltering). Example: `?filter[active]=true` |\n| `include` | string | — | Related data: `section` — the catalog section the product belongs to. See the \"Related data\" section for details |\n| `withTotal` | string | — | Whether you need the count: `true` or `false`. `false` — do not request a count. This is the only way to guarantee that `meta.total` is absent from the response. Without the parameter: the API key setting applies, then the platform default — and in that case a short page still carries the exact count even without an explicit request. [Paging and counts](\u002Fdocs\u002Fentity-api#paging-and-record-counts) |\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -g \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fproducts?filter[active]=true&order[sort]=asc&limit=2\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth application\n\n```bash\ncurl -g \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fproducts?filter[active]=true&order[sort]=asc&limit=2\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — personal key\n\n```javascript\nconst params = new URLSearchParams({\n  'filter[active]': 'true',\n  'order[sort]': 'asc',\n  limit: '2',\n})\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fproducts?${params}`, {\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\n\nconst { success, data, meta } = await res.json()\nconsole.log(`Received: ${data.length}, more available: ${meta.hasMore}`)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst params = new URLSearchParams({\n  'filter[active]': 'true',\n  'order[sort]': 'asc',\n  limit: '2',\n})\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fproducts?${params}`, {\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\n\nconst { success, data, meta } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | Always `true` on success |\n| `data` | array | Array of products. For the item's field set, see [CRM product fields](.\u002Ffields.md) |\n| `meta.total` | number | Total number of records matching the filter. An optional field: if no count was requested, it is absent from the response |\n| `meta.hasMore` | boolean | Whether there are more records beyond `limit` |\n| `meta.includeSkipped` | boolean | `true` if the response holds more than 200 records and the relations from `include` are not loaded. Reduce `limit`. With 200 records or fewer, the field is absent |\n\nIn the online store of your Bitrix24 account, the product card URL of any item in the `data` array is built from its `catalogId` and `id`:\n\n```\nhttps:\u002F\u002F\u003Cportal>.bitrix24.com\u002Fshop\u002Fcatalog\u002F\u003CcatalogId>\u002Fproduct\u002F\u003Cid>\u002F\n```\n\n`\u003Cportal>` is your Bitrix24 account domain. Access is restricted by the employee's permissions in Bitrix24.\n\n## Related data\n\nThe catalog section the product belongs to is returned in every array element when you request it through the `include` parameter:\n\n```\nGET \u002Fv1\u002Fproducts?filter[sectionId]=19&limit=1&include=section\n```\n\nThe available value is `section`. The result is in the `_included.section` field of every `data[]` element. For a product outside any section, when `sectionId` is `null`, the response carries `\"section\": null`. If the response holds more than 200 records, relations are not loaded and `meta` carries `includeSkipped: true` — reduce `limit`. The example shows the `sectionId` field and the `_included` block:\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 533,\n      \"name\": \"test\",\n      \"sectionId\": 19,\n      \"_included\": {\n        \"section\": {\n          \"id\": 19,\n          \"name\": \"Tours\",\n          \"catalogId\": 25,\n          \"sectionId\": 31,\n          \"xmlId\": null,\n          \"code\": null\n        }\n      }\n    }\n  ],\n  \"meta\": {\n    \"hasMore\": true\n  }\n}\n```\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 6967,\n      \"name\": \"Master product\",\n      \"code\": \"product_sku\",\n      \"active\": true,\n      \"previewPicture\": null,\n      \"detailPicture\": null,\n      \"sort\": 100,\n      \"xmlId\": \"6967\",\n      \"updatedAt\": \"2025-05-12T09:05:27.000Z\",\n      \"createdAt\": \"2025-05-12T09:03:15.000Z\",\n      \"modifyBy\": 1,\n      \"createdBy\": 1,\n      \"catalogId\": 25,\n      \"sectionId\": null,\n      \"description\": null,\n      \"descriptionType\": \"text\",\n      \"price\": 100,\n      \"currency\": \"USD\",\n      \"vatId\": null,\n      \"vatIncluded\": false,\n      \"measure\": null\n    },\n    {\n      \"id\": 6969,\n      \"name\": \"Service\",\n      \"code\": \"service\",\n      \"active\": true,\n      \"previewPicture\": null,\n      \"detailPicture\": null,\n      \"sort\": 100,\n      \"xmlId\": \"6969\",\n      \"updatedAt\": \"2025-05-12T09:04:01.000Z\",\n      \"createdAt\": \"2025-05-12T09:04:01.000Z\",\n      \"modifyBy\": 1,\n      \"createdBy\": 1,\n      \"catalogId\": 25,\n      \"sectionId\": null,\n      \"description\": null,\n      \"descriptionType\": \"text\",\n      \"price\": 250,\n      \"currency\": \"USD\",\n      \"vatId\": 1,\n      \"vatIncluded\": true,\n      \"measure\": null\n    }\n  ],\n  \"meta\": {\n    \"hasMore\": true\n  }\n}\n```\n\n## Error response example\n\n400 — operator or unsupported field in the filter:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"UNSUPPORTED_FILTER\",\n    \"message\": \"UNSUPPORTED_FILTER: 'price' is not filterable on 'products'. Its Bitrix24 method (crm.product.list) filters by exact match only. Filterable: id, name, code, xmlId, active, sectionId, sort, description.\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `UNSUPPORTED_FILTER` | Operator or unsupported field in the filter. Filter by exact equality or `$in` on `id`, `name`, `code`, `xmlId`, `active`, `sectionId`, `sort`, `description` |\n| 400 | `INVALID_FILTER` | Error in the filter syntax |\n| 400 | `INVALID_INCLUDE` | `include` carries a value other than `section`. The message lists the available values after the word `Available` |\n| 400 | `UNKNOWN_SORT_FIELD` | Sorting by a field the product cannot be sorted by — `price`, `currency`, `catalogId`, `measure`, VAT and image fields in any spelling, including the raw names `PRICE` and `CATALOG_ID`. The message lists the available fields after the word `Available` |\n| 400 | `UNKNOWN_SELECT_FIELD` | `select` carries a name the product does not have. The message lists the allowed names after the word `Available` |\n| 400 | `SELECT_FIELD_NOT_RETURNED` | `select` carries a name that [CRM product fields](.\u002Ffields.md) shows with `notReturned: true` — `currencyId`, for example. Drop it from `select` |\n| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |\n| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |\n| 429 | `RATE_LIMITED` | Rate limit exceeded: 300 requests per minute per portal, shared by all API keys of the portal. The current limit is returned in the `x-ratelimit-limit` header. Retry after the delay in the `Retry-After` header |\n\nFor the full list of common API errors, see [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Catalog properties arrive only when named.** Name every property you need in `select` — `?select=id,name,PROPERTY_295,PROPERTY_297`. The value `select=*` does not return them; it returns the base product fields. An unset property arrives as a key with the value `null`, and a filled one as an object `{ \"valueId\": …, \"value\": … }`, the same as in [Get CRM product](\u002Fdocs\u002Fentities\u002Fproducts\u002Fget).\n\n**The property number is not validated.** A name of the form `PROPERTY_\u003CN>` is accepted with any number. When the Bitrix24 account has no property with that number, the key does not arrive in the response, and there is neither a rejection nor a warning. The numbers in use are in [CRM product fields](.\u002Ffields.md).\n\n## See also\n\n- [Get CRM product](\u002Fdocs\u002Fentities\u002Fproducts\u002Fget)\n- [Search CRM products](\u002Fdocs\u002Fentities\u002Fproducts\u002Fsearch)\n- [Create CRM product](\u002Fdocs\u002Fentities\u002Fproducts\u002Fcreate)\n- [CRM product fields](\u002Fdocs\u002Fentities\u002Fproducts\u002Ffields)\n- [CRM products](\u002Fdocs\u002Fentities\u002Fproducts)\n- [Catalog products](\u002Fdocs\u002Fentities\u002Fcatalog-products)\n- [Filtering syntax](\u002Fdocs\u002Ffiltering)\n- [Batch](\u002Fdocs\u002Fbatch)\n","2026-10-23",{},1794739405698]