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

A field name that is not in the writable set is no longer dropped silently — the request is rejected with 400 INVALID_PARAMS and the error text lists the writable names. Read-only fields that appear in product-row responses (priceAccount, ownerId, storeId and others) are still accepted and ignored, so an object read via GET can be sent back as is.

A row whose fields are unchanged keeps its id. A modified row comes back with a new id even when the previous identifier is sent in the body. To edit a row and keep its id, use PATCH /v1/items/:entityTypeId/:id/products/:rowId.

Set products of a smart process item

PUT /v1/items/:entityTypeId/:id/products

Sets the product rows of a smart process item. Fully replaces the current list — pass every row you need.

Request fields (body)

Parameter Type Req. Description
entityTypeId (path) number yes Smart process type ID
id (path) number yes Item ID
items array yes Array of product rows
items[].productId number no Catalog product ID. Catalog: GET /v1/products. Pass productId or productName — if you pass neither, the row is created with no product and an empty name
items[].productName string no Row name — for a free-text row with no catalog product
items[].price number no Unit price. If omitted, the row is created with a zero price
items[].quantity number no Quantity. If omitted, the row is created with a quantity of 1
items[].discountTypeId number no How the discount is set: 1 — as an amount in discount, 2 — as a percentage in discountRate. Defaults to 2
items[].discount number no Discount amount. Applied only when discountTypeId is 1
items[].discountRate number no Discount percentage. Applied only when items[].discountTypeId is 2
items[].taxRate number no Tax rate (%)
items[].taxIncluded boolean no Tax included in the price

Examples

curl — personal key

Terminal
curl -X PUT "https://vibecode.bitrix24.com/v1/items/180/47/products" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "productId": 1, "price": 25000, "quantity": 2 },
      { "productId": 5, "price": 5000, "quantity": 1, "discountTypeId": 1, "discount": 500 }
    ]
  }'

curl — OAuth application

Terminal
curl -X PUT "https://vibecode.bitrix24.com/v1/items/180/47/products" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "productId": 1, "price": 25000, "quantity": 2 },
      { "productId": 5, "price": 5000, "quantity": 1, "discountTypeId": 1, "discount": 500 }
    ]
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/items/180/47/products', {
  method: 'PUT',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    items: [
      { productId: 1, price: 25000, quantity: 2 },
      { productId: 5, price: 5000, quantity: 1, discountTypeId: 1, discount: 500 },
    ],
  }),
})

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

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/items/180/47/products', {
  method: 'PUT',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    items: [
      { productId: 1, price: 25000, quantity: 2 },
      { productId: 5, price: 5000, quantity: 1, discountTypeId: 1, discount: 500 },
    ],
  }),
})

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

Response fields

Field Type Description
data array Array of the resulting product rows with the fields productId, productName, price, quantity, discount, taxRate, taxIncluded

Array of the resulting product rows with the fields productId, productName, price, quantity, discount, taxRate, taxIncluded.

Response example

JSON
{
  "success": true,
  "data": [
    {
      "productId": 1,
      "productName": "Server equipment",
      "price": 25000,
      "quantity": 2,
      "discount": 0,
      "discountTypeId": 2,
      "taxRate": null,
      "taxIncluded": false
    },
    {
      "productId": 5,
      "productName": "Installation and setup",
      "price": 5000,
      "quantity": 1,
      "discount": 500,
      "discountTypeId": 1,
      "taxRate": null,
      "taxIncluded": false
    }
  ]
}

Error response example

400 — invalid format:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "items must be an array"
  }
}

Errors

HTTP Code Description
400 INVALID_PARAMS The body contains a field name that is not among the writable fields — see Product fields
400 INVALID_DYNAMIC_PARAM entityTypeId is not a positive integer or is reserved (1, 2, 3, 4, 7, 31)
400 INVALID_PARAMS items is not an array or an array element is not a product-row object
400 INVALID_PARAMS An entry in the items array carries no writable product-row field — an empty object, or read-only fields only. The error text lists the writable names
404 ENTITY_NOT_FOUND Item not found
403 SCOPE_DENIED The API key does not have the crm scope
401 TOKEN_MISSING The API key has no configured tokens

Full list of common API errors — Errors.

Known specifics

Full replacement: PUT replaces the entire product list. To add a row — first fetch the current ones (GET), append the new one to the array, then send everything (PUT). Fetch the list in full: without limit, GET returns only the first page, so pass limit=5000 or page through with offset until meta.hasMore is false. Sending back an incomplete list erases everything it omits.

See also