
## Добавить позицию в оплату CRM

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

Добавляет в оплату CRM позицию — часть товарной строки объекта, например сделки, в указанном количестве. Сумма оплаты пересчитывается сразу.

Поля передаются плоско в корне JSON, без обёртки `fields`.

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|:-----:|---------|
| `id` (path) | number | да | ID оплаты. Список оплат объекта: [`GET /v1/crm-payments`](/docs/entities/crm-payments/list) |

## Поля запроса (body)

| Поле | Тип | Обяз. | Описание |
|------|-----|:-----:|---------|
| `rowId` | number | да | ID товарной строки объекта CRM. Список: [`GET /v1/crm-payments/available-products`](/docs/entities/crm-payments/available-products), поле `productRows[].id` |
| `quantity` | number | да | Количество, положительное целое. Не больше остатка строки — поля `productRows[].quantity` в [доступных товарных строках](/docs/entities/crm-payments/available-products) |

## Примеры

### curl — личный ключ

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

### curl — OAuth-приложение

```bash
curl -X POST "https://vibecode.bitrix24.tech/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 — личный ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/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('ID позиции:', data.id, 'сумма оплаты:', data.payment.sum)
```

### JavaScript — OAuth-приложение

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/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()
```

## Поля ответа

HTTP-статус успешного ответа — `201`.

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | `true` при успехе |
| `data.id` | number | ID созданной позиции оплаты. Передаётся как `itemId` в [`PATCH`](/docs/entities/crm-payments/products-update) и [`DELETE /v1/crm-payments/:id/products/:itemId`](/docs/entities/crm-payments/products-delete) |
| `data.payment` | object | Оплата после добавления позиции, поля — как в [`GET /v1/crm-payments/:id`](/docs/entities/crm-payments/get) |
| `data.payment.id` | number | ID оплаты |
| `data.payment.sum` | number | Сумма оплаты с учётом новой позиции |
| `meta.readbackUnavailable` | boolean | Приходит только со значением `true`, когда позиция добавлена, а перечитать оплату не удалось. Тогда `data.payment` содержит только `id`. Повторять добавление не нужно — проверьте позиции через [`GET /v1/crm-payments/:id/products`](/docs/entities/crm-payments/products-list) |

## Пример ответа

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

## Пример ответа при ошибке

422 — `quantity` больше остатка товарной строки:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Недостаточно товара для добавления в оплату",
    "b24Code": "0"
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `MISSING_REQUIRED_FIELDS` | Тело не передано и заголовка `Content-Type` нет, не передан `rowId` или `quantity`, либо значение не положительное целое, например `1.5` |
| 400 | `FST_ERR_CTP_EMPTY_JSON_BODY` | Передан заголовок `Content-Type: application/json`, а тело пустое |
| 400 | `READONLY_FIELD` | В теле есть поле кроме `rowId` и `quantity`, либо тело не JSON-объект, например `null` или массив |
| 400 | `INVALID_ID` | `id` не положительное целое число |
| 404 | `ENTITY_NOT_FOUND` | Оплаты с таким `id` нет — сообщение `Payment has not been found` |
| 404 | `ENTITY_NOT_FOUND` | Проверка подтвердила, что товарной строки с таким `rowId` нет — сообщение `Product row was not found.` на любом языке портала |
| 404 | `ENTITY_NOT_FOUND` | Товарная строка существует, но эта оплата не может её оплатить — сообщение `Product was not found.` для порталов на английском, немецком и казахском языках; `Товар не найден` для портала на русском языке |
| 422 | `BITRIX_ERROR` | `quantity` больше остатка строки — сообщение `Недостаточно товара для добавления в оплату` |
| 422 | `BITRIX_ERROR` | Битрикс24 отклонил запрос, причина — в `error.message` |
| 422 | `BITRIX_NO_EFFECT` | Позиция не создана, например строка с таким `rowId` уже есть в этой оплате. Существующая позиция при этом не меняется — количество в ней меняют через [`PATCH /v1/crm-payments/:id/products/:itemId`](/docs/entities/crm-payments/products-update) |
| 403 | `BITRIX_ACCESS_DENIED` | У пользователя ключа нет доступа к объекту CRM или оплате в Битрикс24 |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Ключу запрещена запись |
| 403 | `SCOPE_DENIED` | API-ключ не имеет скоупа `crm` |
| 401 | `TOKEN_MISSING` | API-ключ не имеет настроенных токенов |
| 401 | `MISSING_API_KEY` | Не передан `X-Api-Key` |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Добавленное количество уходит из остатка строки.** После добавления 2 единиц из строки на 3 единицы `quantity` этой строки в [доступных товарных строках](/docs/entities/crm-payments/available-products) становится `1`.

## Смотрите также

- [Доступные товарные строки](/docs/entities/crm-payments/available-products)
- [Список позиций оплаты](/docs/entities/crm-payments/products-list)
- [Изменить количество в позиции](/docs/entities/crm-payments/products-update)
- [Удалить позицию из оплаты](/docs/entities/crm-payments/products-delete)
- [Создать оплату CRM](/docs/entities/crm-payments/create)
- [Оплаты CRM](/docs/entities/crm-payments)
