For AI agents: markdown of this page — /docs-content-en/entities/deals/products-add.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.

Add a product to a deal

POST /v1/deals/:id/products

Adds a single product row to a deal. Unlike PUT /v1/deals/:id/products, it does not replace existing rows.

Request fields (body)

Parameter Type Required Description
id (path) number yes Deal ID
productId number no Catalog product ID. If set without productName, the name is taken from the catalog. Catalog: GET /v1/products
productName string no Product row name — for a free-form row without a catalog product. Provide at least one of productId / productName.
price number no Unit price
quantity number no Quantity
discountTypeId number no How the discount is set: 1 — as an amount in discount, 2 — as a percentage in discountRate. Defaults to 2
discount number no Discount amount. Applied only when discountTypeId is 1
discountRate number no Discount percentage. Applied only when discountTypeId is 2
taxRate number no Tax rate (%)
taxIncluded boolean no Tax included in price

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/deals/741/products" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "productId": 1, "price": 25000, "quantity": 2 }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/deals/741/products" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "productId": 1, "price": 25000, "quantity": 2 }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/deals/741/products', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ productId: 1, price: 25000, quantity: 2 }),
})

const { success, data } = await res.json()
console.log('Row ID:', data.id)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/deals/741/products', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ productId: 1, price: 25000, quantity: 2 }),
})

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

Response fields

Field Type Description
data object The created product row in full, HTTP status 201. Field set — Product fields

Response example

Key fields shown. Full list — Product fields.

JSON
{
  "success": true,
  "data": {
    "id": 1465,
    "productId": 1,
    "productName": "Server equipment",
    "price": 25000,
    "quantity": 2,
    "discount": 0,
    "discountTypeId": 2,
    "taxIncluded": false
  }
}

Error response example

404 — deal not found:

JSON
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "Item not found"
  }
}

Errors

HTTP Code Description
400 INVALID_PARAMS The body contains a field name that is not among the writable fields — see Product fields
404 ENTITY_NOT_FOUND Deal not found
403 SCOPE_DENIED API key lacks the crm scope
401 TOKEN_MISSING API key has no configured tokens

Full list of common API errors — Errors.

See also