[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-entities\u002Fbasket-items\u002Fcreate":3,"docs-tabs-entities\u002Fbasket-items\u002Fcreate":6},{"content":4,"lastmod":5},"\n## Добавить позицию в корзину\n\n`POST \u002Fv1\u002Fbasket-items`\n\nДобавляет товарную позицию в существующий заказ. Позиция ссылается на товар каталога через `productId` либо создаётся виртуальной при `productId: 0`. Тело запроса плоское — без обёртки `fields`.\n\n## Поля запроса (тело)\n\n| Параметр | Тип | Обяз. | Описание |\n|----------|-----|:-----:|---------|\n| `orderId` | number | да | Идентификатор заказа. Источник: [`GET \u002Fv1\u002Forders`](..\u002Forders\u002Flist.md) |\n| `productId` | number | да | Идентификатор товара в каталоге. Источник: [`GET \u002Fv1\u002Fcatalog-products`](\u002Fdocs\u002Fentities\u002Fcatalog-products). Значение `0` создаёт виртуальную позицию без привязки к каталогу |\n| `currency` | string | да | Валюта позиции. Список: [`GET \u002Fv1\u002Fcurrencies`](\u002Fdocs\u002Fentities\u002Fcurrencies) |\n| `quantity` | number | да | Количество |\n| `name` | string | нет | Название позиции. При `productId > 0` подставляется из карточки товара — переданное значение на создании не сохраняется. При `productId: 0` сохраняется как передано |\n| `price` | number | нет | Цена за единицу. Для виртуальной позиции задаётся вручную. Передача `price` включает `customPrice` |\n| `basePrice` | number | нет | Базовая цена до скидки. По умолчанию равна `price` |\n| `discountPrice` | number | нет | Размер скидки за единицу. По умолчанию `0` |\n| `customPrice` | boolean | нет | Защита цены от автопересчёта при изменении товара в каталоге. При передаче `price` выставляется в `true`. По умолчанию `false` |\n| `vatRate` | number | нет | Ставка НДС в долях единицы. `0.20` = 20%, `0.10` = 10%, `0` — без НДС |\n| `vatIncluded` | boolean | нет | Включён ли НДС в цену. По умолчанию `true` |\n| `weight` | number | нет | Вес единицы в граммах |\n| `measureCode` | number | нет | Код единицы измерения. `796` — шт, `163` — г, `006` — м |\n| `productXmlId` | string | нет | Внешний идентификатор товара. Для виртуальной позиции задаётся вручную |\n| `catalogXmlId` | string | нет | Внешний идентификатор каталога. Для виртуальной позиции задаётся вручную |\n| `xmlId` | string | нет | Внешний идентификатор позиции |\n\n## Примеры\n\nПримеры ниже создают виртуальную позицию `productId: 0` — для неё `name` сохраняется как передано.\n\n### curl — личный ключ\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fbasket-items\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"orderId\": 1,\n    \"productId\": 0,\n    \"currency\": \"RUB\",\n    \"quantity\": 1,\n    \"name\": \"Подарочная упаковка\"\n  }'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fbasket-items\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"orderId\": 1,\n    \"productId\": 0,\n    \"currency\": \"RUB\",\n    \"quantity\": 1,\n    \"name\": \"Подарочная упаковка\"\n  }'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fbasket-items', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    orderId: 1,\n    productId: 0,\n    currency: 'RUB',\n    quantity: 1,\n    name: 'Подарочная упаковка',\n  }),\n})\n\nconst { success, data } = await res.json()\nconsole.log('Basket item ID:', data.id)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fbasket-items', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    orderId: 1,\n    productId: 0,\n    currency: 'RUB',\n    quantity: 1,\n    name: 'Подарочная упаковка',\n  }),\n})\n\nconst { success, data } = await res.json()\n```\n\nКаталожная позиция создаётся передачей `productId` товара — `name`, `price` и единица измерения заполнятся из его карточки:\n\n```json\n{\n  \"orderId\": 1,\n  \"productId\": 119,\n  \"currency\": \"RUB\",\n  \"quantity\": 2\n}\n```\n\n## Поля ответа\n\nВозвращается полный объект созданной позиции.\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `id` | number | Идентификатор созданной позиции |\n| `name` | string | Название. Для каталожного товара — из карточки, для виртуальной позиции — как передано |\n| `price` | number | Цена за единицу |\n| `customPrice` | boolean | `true`, если цена задана вручную через `price` |\n| `productXmlId` | string \\| null | Внешний идентификатор товара. `null` у виртуальной позиции без переданного значения |\n| `catalogXmlId` | string \\| null | Внешний идентификатор каталога. `null` у виртуальной позиции без переданного значения |\n| `dateInsert` | datetime | Дата создания |\n\nПолный набор полей — [`GET \u002Fv1\u002Fbasket-items\u002Ffields`](.\u002Ffields.md).\n\n## Пример ответа\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 1021,\n    \"orderId\": 1,\n    \"productId\": 0,\n    \"name\": \"Подарочная упаковка\",\n    \"price\": 0,\n    \"basePrice\": 0,\n    \"discountPrice\": 0,\n    \"customPrice\": false,\n    \"currency\": \"RUB\",\n    \"quantity\": 1,\n    \"sort\": 100,\n    \"weight\": null,\n    \"dimensions\": null,\n    \"measureCode\": null,\n    \"measureName\": null,\n    \"canBuy\": true,\n    \"vatRate\": null,\n    \"vatIncluded\": true,\n    \"xmlId\": \"bx_6a3e475a2d55c\",\n    \"productXmlId\": null,\n    \"catalogXmlId\": null,\n    \"dateInsert\": \"2026-06-26T08:33:14.000Z\",\n    \"dateUpdate\": \"2026-06-26T08:33:14.000Z\"\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n422 — не переданы обязательные поля:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"BITRIX_ERROR\",\n    \"message\": \"Required fields: orderId, productId, currency, quantity\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 422 | `BITRIX_ERROR` | Не переданы обязательные поля — сообщение содержит их список |\n| 422 | `BITRIX_ERROR` | Несуществующий `orderId` или `productId` — позиция не сохранена |\n| 403 | `SCOPE_DENIED` | API-ключ не имеет скоупа `sale` |\n| 401 | `TOKEN_MISSING` | API-ключ не имеет настроенных токенов |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Имя каталожного товара берётся из карточки.** При `productId > 0` поля `name`, `productXmlId`, `catalogXmlId`, `measureCode`, `measureName` заполняются из карточки товара. Переданное в запросе `name` на создании не сохраняется. Чтобы задать каталожной позиции произвольное имя, обновите её после создания через [`PATCH \u002Fv1\u002Fbasket-items\u002F:id`](.\u002Fupdate.md).\n\n**Виртуальная позиция.** При `productId: 0` позиция не привязана к каталогу. Поля `name`, `price`, `productXmlId`, `catalogXmlId` задаются вручную в запросе и сохраняются как переданы.\n\n**Ручная цена включает `customPrice`.** Если передать `price`, в ответе `customPrice` становится `true` — цена позиции не пересчитывается при изменении цены товара в каталоге. Без `price` остаётся `false`.\n\n**Несколько позиций для одного товара.** Можно добавить одну и ту же `productId` в заказ несколькими позициями — Битрикс24 не объединяет их. Чтобы увеличить количество существующей позиции, используйте [`PATCH \u002Fv1\u002Fbasket-items\u002F:id`](.\u002Fupdate.md) с `quantity`.\n\n## Смотрите также\n\n- [Список позиций](.\u002Flist.md)\n- [Получить позицию](.\u002Fget.md)\n- [Обновить позицию](.\u002Fupdate.md)\n- [Поля позиции](.\u002Ffields.md)\n- [Заказ](..\u002Forders\u002Fget.md)\n- [Товары каталога](\u002Fdocs\u002Fentities\u002Fcatalog-products)\n- [Batch](\u002Fdocs\u002Fbatch)\n","2026-06-29",{}]