
## Add a line item to a CRM payment

`POST /v1/crm-payments/:id/products`

Adds a line item to a CRM payment: the specified quantity taken from a product row of a CRM item, such as a deal. The payment amount is recalculated immediately.

Fields are passed flat at the JSON root, without a `fields` wrapper.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `id` (path) | number | yes | Payment ID. Payments of a CRM item: [`GET /v1/crm-payments`](/docs/entities/crm-payments/list) |

## Request fields (body)

| Field | Type | Required | Description |
|------|-----|:-----:|---------|
| `rowId` | number | yes | ID of the CRM item's product row. List: [`GET /v1/crm-payments/available-products`](/docs/entities/crm-payments/available-products), field `productRows[].id` |
| `quantity` | number | yes | Quantity, a positive integer. Must not exceed the row's remainder, which is the `productRows[].quantity` field in the [available product rows](/docs/entities/crm-payments/available-products) |

## Examples

### curl — personal key

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/crm-payments/573/products" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "rowId": 2357, "quantity": 2 }'
```

### curl — OAuth application

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/crm-payments/573/products" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "rowId": 2357, "quantity": 2 }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/crm-payments/573/products', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ rowId: 2357, quantity: 2 }),
})

const { data } = await res.json()
console.log('Line item ID:', data.id, 'payment amount:', data.payment.sum)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/crm-payments/573/products', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ rowId: 2357, quantity: 2 }),
})

const { data } = await res.json()
```

## Response fields

A successful response returns HTTP status `201`.

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | `true` on success |
| `data.id` | number | ID of the created payment line item. Passed as `itemId` to [`PATCH`](/docs/entities/crm-payments/products-update) and [`DELETE /v1/crm-payments/:id/products/:itemId`](/docs/entities/crm-payments/products-delete) |
| `data.payment` | object | The payment after the line item is added, with the same fields as in [`GET /v1/crm-payments/:id`](/docs/entities/crm-payments/get) |
| `data.payment.id` | number | Payment ID |
| `data.payment.sum` | number | Payment amount including the new line item |
| `meta.readbackUnavailable` | boolean | Returned only with the value `true` when the line item was added but the payment could not be read back. In that case `data.payment` contains only `id`. Do not add the line item again. Check the line items via [`GET /v1/crm-payments/:id/products`](/docs/entities/crm-payments/products-list) |

## Response example

```json
{
  "success": true,
  "data": {
    "id": 445,
    "payment": {
      "id": 573,
      "accountNumber": "1035/1",
      "paid": "N",
      "datePaid": null,
      "empPaidId": null,
      "paySystemId": 19,
      "sum": 3000,
      "currency": "USD",
      "paySystemName": "Card payment"
    }
  }
}
```

## Error response example

422 — `quantity` exceeds the product row's remainder:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Not enough product to add to the payment",
    "b24Code": "0"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `MISSING_REQUIRED_FIELDS` | The body is missing and there is no `Content-Type` header, `rowId` or `quantity` is not provided, or the value is not a positive integer, for example `1.5` |
| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | The `Content-Type: application/json` header is sent with an empty body |
| 400 | `READONLY_FIELD` | The body contains a field other than `rowId` and `quantity`, or the body is not a JSON object, for example `null` or an array |
| 400 | `INVALID_ID` | `id` is not a positive integer |
| 404 | `ENTITY_NOT_FOUND` | No payment with this `id`, message `Payment has not been found` |
| 404 | `ENTITY_NOT_FOUND` | The row lookup confirmed that no product row has this `rowId`; message `Product row was not found.` in every portal language |
| 404 | `ENTITY_NOT_FOUND` | The product row exists, but this payment cannot pay for it; message `Product was not found.` on en/de/kz portals, or a localized Russian message on ru portals (shown in the Russian documentation) |
| 422 | `BITRIX_ERROR` | `quantity` exceeds the row's remainder, message `Not enough product to add to the payment` |
| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request. The reason is in `error.message` |
| 422 | `BITRIX_NO_EFFECT` | The line item was not created, for example because a row with this `rowId` is already in this payment. The existing line item does not change. To change its quantity, use [`PATCH /v1/crm-payments/:id/products/:itemId`](/docs/entities/crm-payments/products-update) |
| 403 | `BITRIX_ACCESS_DENIED` | The key's user has no access to the CRM item or the payment in Bitrix24 |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is not allowed to write |
| 403 | `SCOPE_DENIED` | The API key does not have the `crm` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |
| 401 | `MISSING_API_KEY` | `X-Api-Key` is not provided |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

**The added quantity is taken from the row's remainder.** After 2 units are added from a row of 3 units, the `quantity` of this row in the [available product rows](/docs/entities/crm-payments/available-products) becomes `1`.

## See also

- [Available product rows](/docs/entities/crm-payments/available-products)
- [List payment line items](/docs/entities/crm-payments/products-list)
- [Change the quantity in a line item](/docs/entities/crm-payments/products-update)
- [Delete a line item from a payment](/docs/entities/crm-payments/products-delete)
- [Create a CRM payment](/docs/entities/crm-payments/create)
- [CRM payments](/docs/entities/crm-payments)
