# Оптовая торговля

> Счета на крупные суммы, привязка к номеру заказа, до 100 счетов одним запросом, подписки для постоянных клиентов, связка с 1С, частичная оплата траншами и возвраты.

## Коротко

В опте счетов в день немного, но каждый крупный, и за каждым стоит конкретный заказ, накладная и взаиморасчёт. Поэтому здесь важен не QR, а **аккуратность учёта**: привязка счёта к заказу через `externalOrderId`, защита от дублей через `Idempotency-Key` и запись оплаты в вашу систему по webhook. Одним запросом можно выставить до 100 счетов, а ежемесячные платежи постоянных клиентов — перевести на подписки.

## Базовый сценарий

1. Менеджер подтверждает заказ в 1С или CRM: №РН-00142 на 1 480 000 ₸.
2. Система создаёт счёт:

```json
POST /api/v1/invoices
{
  "amount": 1480000,
  "kind": "phone",
  "description": "Заказ РН-00142",
  "externalOrderId": "RN-00142",
  "customer": { "name": "ТОО «Арна Трейд»", "phone": "77011234567" },
  "metadata": { "manager": "sultan", "warehouse": "almaty-1", "doc": "RN-00142" }
}
```

3. Клиенту приходит push в Kaspi, он оплачивает.
4. Вам приходит webhook `invoice.paid` — оплата фиксируется в 1С, заказ уходит на отгрузку.

В опте чаще удобнее `kind: "phone"`: клиент сидит у себя в офисе, экрана с QR перед ним нет. Но здесь два ограничения: **`description` до 60 символов** и телефон в формате `7XXXXXXXXXX`. Если клиент рядом или забирает товар со склада, подойдёт `kind: "qr"` — там описание до 100 символов.

## О суммах

- `amount` указывается в тенге. У QR-счёта допустимо не больше двух знаков после запятой, а **счёт по телефону принимает только целые тенге**. Округляйте на своей стороне, иначе сумма не пройдёт: [Сумма неверная или теряются тиыны](/kb/ru/wrong-amount).
- С нашей стороны задокументированного верхнего предела суммы нет, но **ограничения может устанавливать Kaspi** — это его правила, и повлиять на них мы не можем. Поэтому перед работой с непривычно крупными суммами прогоните один пробный счёт.
- У клиента в Kaspi тоже могут быть свои лимиты. Если сумма не проходит, сначала определите, на чьей стороне проблема: [Проблема у вас или у Kaspi](/kb/ru/is-it-us-or-kaspi).

## Защита от дублей

На крупных суммах задвоенный счёт — это реальные потери. Используйте оба инструмента сразу.

**Заголовок `Idempotency-Key`.** Привяжите значение к заказу, например `RN-00142-v1`. При повторной отправке с тем же ключом новый счёт не создастся — вернётся прежний (HTTP 200, `idempotentReplay: true`). Именно это спасает, когда связь оборвалась и ответ до вас не дошёл.

**`externalOrderId`.** Ваш номер заказа. Он возвращается в webhook и работает в поиске — через него счёт связан с документом.

Если дубли уже пошли валом, первым делом остановите поток, удалив ключ: [Счета дублируются](/kb/ru/duplicate-invoices). Полное описание: [Идемпотентность](/kb/ru/idempotency).

## Массовое выставление: POST /invoices/bulk

Когда в начале месяца нужно выставить счета сразу дилерам, магазинам или точкам, отправляйте **от 1 до 100 счетов** одним запросом.

Важный порядок работы:

- **Каждый элемент проверяется отдельно.** Ошибка в одном телефоне не мешает остальным создаться, весь запрос не падает.
- **Разбирайте ответ поэлементно**: что создалось, что упало и с какой ошибкой.
- Упавшие исправьте и отправьте повторно — но с теми же `Idempotency-Key` и `externalOrderId`, иначе успешные задвоятся.
- Если счетов больше 100, разбейте на несколько запросов и не отправляйте их залпом: [Ограничения частоты запросов](/kb/ru/rate-limits).
- Кладите код дилера в `metadata` — по нему потом удобно группировать отчёт.

Подробнее: [Массовое создание счетов](/kb/ru/bulk-invoices).

## Подписки для постоянных клиентов

Если клиенту ежемесячно выставляется одна и та же сумма (сервисное обслуживание, абонентская поставка, аренда оборудования), подойдут [подписки](/kb/ru/subscriptions-api).

Но в опте важно понимать их предел: **подписка только выставляет счёт, деньги сами не списываются** — каждую оплату клиент подтверждает в Kaspi. То есть она не гарантирует поступление по договору, она решает другую задачу: не забыть выставить счёт вовремя.

Настройки: интервал `month`/`week`/`day` с кратностью `every`; шаги повтора `retryDelaysMin` (по умолчанию `[15, 60, 360]` минут, максимум 5 значений); политика пропуска `misfirePolicy` — `run_once` (по умолчанию) или `skip`, `misfireAfterMin` по умолчанию 1440. Клиент приостановил закупки — `pause`, возобновил — `resume`, нужно догнать пропущенный запуск — `{ catchUp: true }`.

Подробнее: [Бизнес по подписке](/kb/ru/for-subscription-business).

## Связка с 1С

Готового модуля нет, но типовая схема работает:

1. **HTTP-сервис или фоновое задание.** 1С по документу «Счёт на оплату» или «Реализация» отправляет `POST /api/v1/invoices`. В `externalOrderId` — номер документа.
2. **Ключ хранится на сервере 1С**, а не на машине пользователя.
3. **Оплату принимаете одним из двух способов.** Надёжнее webhook: он приходит на ваш сервер, тот пишет в 1С. Если 1С стоит в закрытом контуре, опрашивайте `GET /api/v1/invoices` по расписанию.
4. **Номенклатуру мы не получаем.** В счёте только сумма и описание, состав товара остаётся в 1С.

Руководство: https://api.qut.kz/docs/guide/1c и статья [Выставление счетов Kaspi из 1С](/kb/ru/for-1c).

## Частичная оплата и возвраты

**Частичная оплата.** Оплатить часть одного счёта нельзя — счёт Kaspi не делится. Если нужны транши, выставляйте **несколько счетов**:

- Предоплата 30%: `externalOrderId: "RN-00142-A"`, сумма 444 000.
- Остаток перед отгрузкой: `externalOrderId: "RN-00142-B"`, сумма 1 036 000.
- В `metadata` обоих держите общий `doc: "RN-00142"` — в отчёте они соберутся в один заказ.

Закрывайте заказ только когда оплачены **все** части.

**Возврат.** Доступен и полный, и частичный:

```json
POST /api/v1/invoices/{id}/refund
{ "amount": 120000, "reason": "Возврат брака по РН-00142" }
```

Частично возвращённый счёт переходит в статус `partially_refunded` и по-прежнему считается оплаченным. Если ответ пришёл в неопределённом состоянии (`refund_unknown`), не отправляйте запрос повторно вслепую — на крупной сумме это дорого: [Как не вернуть деньги дважды](/kb/ru/double-refund). Полный справочник: [API возвратов](/kb/ru/refunds-api).

## Сверка и отчётность

- **Выгрузка CSV** за период, готовая для бухгалтерии: [Экспорт CSV и отчётность](/kb/ru/csv-export).
- **Сверяйтесь по `externalOrderId`, а не по сумме.** Два заказа с одинаковой суммой — обычное дело в опте.
- **Деньги приходят напрямую на ваш счёт в Kaspi**, у нас они не задерживаются. Поэтому в выписке сумма видна как есть, с учётом условий самого Kaspi.
- **Не забывайте про поздние оплаты.** Деньги по уже закрытому счёту могут прийти позже, и `invoice.paid` придёт с пометкой `late: true` — месяц к этому моменту может быть уже закрыт: [Поздняя оплата](/kb/ru/late-payment).

## Вопросы и ответы

**Какая максимальная сумма счёта?** С нашей стороны задокументированного предела нет. Свои лимиты могут быть у Kaspi и у клиента — их устанавливает Kaspi. Начните работу с крупными суммами с одного пробного счёта.

**Сколько счетов можно отправить одним запросом?** От 1 до 100. Каждый элемент проверяется отдельно, ошибка в одном не роняет остальные.

**Может ли клиент оплатить половину суммы?** По одному счёту — нет. Для траншей выставляются отдельные счета, связанные между собой через `metadata`.

**Гарантирует ли подписка поступление по договору?** Нет. Она выставляет счёт по расписанию, а оплату подтверждает клиент. Деньги сами не списываются.

**Есть ли готовая обработка для 1С?** Готового модуля нет, но есть типовая схема и руководство: https://api.qut.kz/docs/guide/1c
