> Источник: https://apipay.kz/guides/vybit-fiskalnyy-chek-kaspi · Обновлено: 2026-10-24 · apipay.kz
> ApiPay — независимый сервис приёма платежей поверх вашего Kaspi Pay.

# Фискальный чек Kaspi для наличных и чужого POS: как выбить через API

**TL;DR.** Если покупатель заплатил **наличными** или **картой через POS другого банка**,
оплата прошла мимо Kaspi QR, и Kaspi **не создаёт по ней фискальный чек сам**. Такой чек
выбивается в Kaspi OFD через ApiPay: кнопкой в кабинете или запросом `POST /api/v1/receipts`
с `payment_type` `3` (наличные) или `5` (POS другого банка); нужен подключённый кассир Kaspi.
Уже пробитый чек из Kaspi Pos или с терминала Kaspi — найти, вытащить повторно, распечатать —
ищите в самом Kaspi, см. [справку Kaspi](https://guide.kaspi.kz/).

## Коротко

| Вопрос | Ответ |
|---|---|
| Когда нужно | Оплата наличными (`payment_type=3`) или через POS другого банка (`payment_type=5`) |
| Что нужно от товара | Позиция из каталога. С НТИН — чек с маркировкой Нацкаталога, без НТИН и без штрихкода (например, услуга) — без маркировки |
| Как отдаётся | Асинхронно: чек `pending` → `issued`/`failed`, узнаёте поллингом или вебхуком |
| Старый чек из Kaspi Pos | Ищите в Kaspi — см. [справку Kaspi](https://guide.kaspi.kz/). В ApiPay такие чеки не отображаются |
| История чеков ApiPay | `GET /api/v1/receipts` — фильтры по статусу, способу оплаты, счёту и периоду |

## Выбить новый чек или найти уже пробитый?

Это две разные задачи, и делаются они в разных местах.

| Задача | Где это делается |
|---|---|
| Выбить чек по оплате наличными или через POS другого банка | В ApiPay: [из кабинета](/guides/kak-vybit-chek-v-kabinete-apipay) или по API — эта статья |
| Найти, повторно вытащить или распечатать чек, пробитый в Kaspi Pos или на терминале Kaspi | В самом Kaspi — см. [справку Kaspi](https://guide.kaspi.kz/). Чеки, пробитые в Kaspi Pos мимо ApiPay, в ApiPay не отображаются |
| Найти чек по счёту, оплаченному через ApiPay | В карточке счёта в кабинете — кнопка «Чек», или запросом `GET /api/v1/invoices/{id}/receipt`. Это чек Kaspi по оплате счёта, в истории выбитых чеков его нет |
| Найти чек, выбитый через ApiPay | В истории чеков кабинета или запросом `GET /api/v1/receipts`. У выбитого чека есть ссылка на его страницу `receipt.kaspi.kz` — её можно открыть, отправить покупателю или распечатать |

**Вы покупатель и вам нужен чек за покупку?** Обратитесь к продавцу: чек выбивает он.
ApiPay — инструмент для продавца. Если вы продавец — читайте дальше.

## Что нужно, чтобы выбить чек через ApiPay?

1. **Активная подписка на ApiPay.** Без неё `POST /receipts` и `POST /receipts/preview` отдают
   `403 tariff_inactive` (в теле `expires_at` и `reason`). Чтение истории чеков работает всегда.
2. **Кассир Kaspi подключён** (активная сессия). Нет активного кассира →
   `409 kaspi_session_not_configured`. Как подключить кассира за несколько минут —
   [apipay.kz/connect-cashier](/connect-cashier).
3. **Подключена Kaspi Касса (ОФД).** Фискальные чеки выбивает Kaspi Касса; вместе с ней в
   ApiPay появляются каталог и раздел «Касса». Как подключить Kaspi Кассу — в
   [справке Kaspi](https://guide.kaspi.kz/partner/ru/cashier/connection/q2479). Если у вас уже
   работают QR-счета через API, сначала прочитайте
   «[Переход на каталог товаров](/guides/perehod-na-katalog-tovarov)»: после включения каталога
   QR-счета без состава покупки перестают приниматься.
4. **Смена на кассе открыта.** Открывается в приложении Kaspi Pos. Если закрыта — чек
   вернётся с `error_code: shift_closed`.
5. **Товары есть в каталоге.** Позиция с НТИН уходит в чек с маркировкой Нацкаталога.
   Позиция без НТИН и без штрихкода (например, услуга) уходит в чек без маркировки.
   Для произвольной суммы заведите универсальную позицию вроде «Услуга» и передайте сумму
   в `price` строки `cart_items`.
   `item_not_fiscal` приходит, если позиции нет в каталоге, если в бою она ещё не
   синхронизирована с Kaspi (`in_kaspi_catalog=false`) или если у неё есть штрихкод, но нет
   НТИН (`ntin_missing=true`). Такой НТИН найдите через `POST /catalog/scan`, сохраните в позиции
   (`PATCH /catalog/{id}`) и повторите чек. Несинхронизированную позицию повторите, когда
   `in_kaspi_catalog` станет `true` (`GET /catalog` или вебхук `catalog.item_processed`). См.
   [Каталог, корзина и Нацкаталог](/guides/katalog-korzina-nackatalog).
6. **В чеке нет позиций со ставкой НДС.** Такие чеки не выбиваются — чек вернётся с
   `error_code: receipt_vat_not_supported`.

## Какой способ оплаты указать: наличные или POS другого банка?

| `payment_type` | Что это |
|---|---|
| `3` | Наличные |
| `5` | Через POS другого банка |

Для наличных можно передать `received_amt` (полученная сумма, может быть больше итога — для
сдачи). Для чужого POS `received_amt` всегда равен сумме чека.

## Как выбить чек по API?

Полная спецификация запросов и ответов — [apipay.kz/docs](/docs).

### Шаг 1 — превью (необязательно, но удобно)

```bash
curl -X POST https://api.apipay.kz/api/v1/receipts/preview \
  -H "X-API-Key: <ваш ключ>" -H "Content-Type: application/json" \
  -d '{ "payment_type": 3, "total_price": "10" }'
```
Ответ — готовый предпросмотр чека:
```json
{ "data": [
  { "Title": "Сумма", "Subtitle": "10 ₸", "isBoldText": true },
  { "Title": "Способ оплаты", "Subtitle": "Наличные", "isBoldText": false }
] }
```

### Шаг 2 — выбить чек

```bash
curl -X POST https://api.apipay.kz/api/v1/receipts \
  -H "X-API-Key: <ваш ключ>" -H "Content-Type: application/json" \
  -d '{
    "payment_type": 3,
    "client_operation_id": "pos-2026-07-12-0042",
    "cart_items": [ { "catalog_item_id": 15041503, "quantity": 1, "price": 10 } ],
    "received_amt": "500"
  }'
```
Ответ `202` — чек принят в обработку:
```json
{ "id": 4210, "status": "pending", "client_operation_id": "pos-2026-07-12-0042" }
```

**`client_operation_id`** — ключ идемпотентности, уникален в пределах организации.
Сгенерируйте его один раз на попытку (например uuid). Пока попытка в `pending` или завершилась
`issued`, повтор с тем же ключом вернёт `409 duplicate_client_operation_id` (в теле —
`receipt_id` и `status`) и второго фискального документа не создаст. После `failed` документа
нет, и ключ снова свободен — тот же запрос можно переслать без изменений. При освобождении ключ
снимается со старой неудачной записи, найти её по нему уже нельзя — **храните `id` чека из
ответа `202`**.

### Шаг 3 — узнать результат

Поллинг:
```bash
curl https://api.apipay.kz/api/v1/receipts/4210 -H "X-API-Key: <ваш ключ>"
```
```json
{
  "id": 4210, "status": "issued", "total_price": "10.00",
  "fpd": "000000000000", "operation_id": "KKM00000000", "shift_number": null,
  "link": "https://receipt.kaspi.kz/web/fiscal?i=000000000000&f=000000000000&s=10&t=2026-07-12%2015%3A25%3A43",
  "error_code": null
}
```
Либо — вебхук: при терминальном статусе чека уходит `receipt.issued` (успех) или
`receipt.failed` (причина в `receipt.error_code`). Событие получают **все активные ключи
организации, у которых сохранён `webhook_url`** (дедуп по URL). Дедуплицируйте у себя по
`(event, receipt.id)`.

Статусы: `pending` → `issued` (готово, есть `fpd`/`link`) или `failed` (см. `error_code`).

**`shift_number`** у новых чеков приходит `null`. Не делайте это поле обязательным у себя.

**`link`** — публичная страница чека
`receipt.kaspi.kz/web/fiscal?i={ФПД}&f={РНМ кассы}&s={сумма}&t={время операции}`: открывается
в любом браузере, можно отправить покупателю, распечатать или показать по QR. Все четыре
параметра сверяются на стороне Kaspi — **используйте ссылку целиком, как она пришла**.
В песочнице и в редком ответе Kaspi без РНМ кассы в `link` приходит внутренняя ссылка вида
`/preview/cashier`: она рисует чек только внутри приложения Kaspi, поле не обнуляется.

### Шаг 4 — история чеков

`GET /api/v1/receipts` — чеки организации, свежие сверху, конверт `{current_page, data, total}`;
элемент — та же форма, что у `GET /receipts/{id}`. Фильтры: `status` (`pending|issued|failed`),
`payment_type` (`3|5`), `invoice_id`, `from`/`to` по `created_at`, `page`, `per_page` (1..100,
default 20). Окно `from`/`to` — в зоне Asia/Almaty: голая дата в `to` включает весь день,
`to` раньше `from` → `422`. Боевая организация видит только боевые чеки, тестовая — только
тестовые. **Если исход прошлой попытки неизвестен, сначала найдите её здесь или через
`GET /receipts/{id}` — и только потом решайте, повторять ли.**

## Что делать, если чек не выбился?

| error_code | Что значит и что делать |
|---|---|
| `shift_closed` | Смена закрыта — откройте смену в приложении Kaspi Pos и повторите |
| `item_not_fiscal` | Позиции нет в каталоге, в бою она не синхронизирована с Kaspi или у неё есть штрихкод, но нет НТИН — найдите НТИН через `POST /catalog/scan`, сохраните его (`PATCH /catalog/{id}`) и повторите |
| `receipt_vat_not_supported` | В чеке позиция со ставкой НДС — такие чеки не выбиваются |
| `kaspi_session_not_configured` | `409` — нет активного кассира, переавторизуйте кассу |
| `kaspi_session_invalid` | Сессия кассира Kaspi недействительна — переподключите кассира и повторите чек |
| `kaspi_session_expired` | `409` — сессия кассира истекла, чек не выбит. Переподключите кассира и повторите |
| `receipt_ofd_token_revoked` | Отозвана фискальная привязка кассы. Перепривяжите ОФД в приложении Kaspi и повторите чек; приём оплат при этом продолжает работать |
| `rfo_missing` | Не определён код торговой точки. Подключите Kaspi Kassa (ОФД) к точке в приложении Kaspi Pay, затем переподключите кассира в ApiPay. ⚠️ Это может включить каталог товаров — см. «[Переход на каталог товаров](/guides/perehod-na-katalog-tovarov)» |
| `receipt_kaspi_error` | Kaspi отклонил чек — текст в `error_message` |
| `receipt_dispatch_error` | Технический сбой, фискальный документ **не создан** — перешлите тот же запрос (после `failed` прежний `client_operation_id` свободен) |
| `duplicate_client_operation_id` | `409` — по этому ключу чек уже есть (`receipt_id` и `status` в теле). После `failed` ключ освобождается и повтор разрешён |
| `connection_ambiguous` | `422` — несколько активных касс, передайте `kaspi_connection_id` |
| `receipt_unavailable` | Выбивание чеков временно приостановлено на нашей стороне. Фискальный документ **не создан**, `client_operation_id` свободен — повторите тот же запрос позже. Синхронный ответ `503` несёт заголовок `Retry-After` |
| `tariff_inactive` | `403` — подписка на ApiPay не активна. `POST /receipts` и `/receipts/preview` заблокированы, история чеков (`GET`) доступна |

## Как проверить чек в песочнице?

В песочнице Kaspi не вызывается и фискальный документ не пишется. Правило
«штрихкод без НТИН → `failed` / `item_not_fiscal`» работает так же, как в бою. Одно отличие:
`in_kaspi_catalog` в песочнице всегда `false`, но чек выбивается — отказ по несинхронизированной
позиции там не воспроизводится, поэтому обработайте `item_not_fiscal` до выхода в бой. Про сами режимы —
[Песочница и рабочий режим](/guides/pesochnitsa-i-rabochiy-rezhim).

Ошибки воспроизводятся полем `simulate` (только в песочнице; на боевой организации вернётся
`403 not_sandbox`, чек не создастся):

```bash
curl -X POST https://api.apipay.kz/api/v1/receipts \
  -H "X-API-Key: <ключ песочницы>" -H "Content-Type: application/json" \
  -d '{
    "payment_type": 3,
    "client_operation_id": "sb-001",
    "cart_items": [ { "catalog_item_id": 12, "quantity": 2 } ],
    "simulate": { "status": "failed", "error_code": "shift_closed" }
  }'
```
`simulate.status` — `issued` или `failed`; `simulate.error_code` — `shift_closed`,
`item_not_fiscal` или `receipt_kaspi_error` (по умолчанию `receipt_kaspi_error`). Форсированная
ошибка выигрывает всегда, даже если позиции фискально корректны.

Вебхуки `receipt.issued` / `receipt.failed` в песочнице уходят так же, как в бою. Доставки
`receipt.*` видны в журнале `GET /webhook-logs`. Если вебхук не дошёл после всех повторов,
итог берите поллингом `GET /receipts/{id}`.

То же самое без кода — [из кабинета](/guides/kak-vybit-chek-v-kabinete-apipay).

## Частые вопросы

**Как выбить чек Kaspi, если платили наличными?**
В кабинете ApiPay откройте «Создать счёт», переключитесь в режим «Фискальный чек (без счёта)», выберите способ оплаты «Наличные», добавьте товары из каталога и нажмите «Выбить чек» — [пошагово](/guides/kak-vybit-chek-v-kabinete-apipay). По API — `POST /api/v1/receipts` с `payment_type: 3`; полученную от покупателя сумму можно передать в `received_amt`, чтобы посчитать сдачу.

**Как отбить чек, если оплата была картой другого банка?**
Так же, но со способом оплаты «POS другого банка» — `payment_type: 5`. Сумма, полученная от покупателя, здесь всегда равна сумме чека.

**Как повторно вытащить или распечатать старый чек Kaspi?**
Чек, пробитый в Kaspi Pos или на терминале Kaspi, ищите в самом Kaspi — по [справке Kaspi](https://guide.kaspi.kz/). Чек, выбитый через ApiPay, находится в истории чеков: откройте ссылку на его страницу `receipt.kaspi.kz` и распечатайте её. Чек по счёту, оплаченному через ApiPay, открывается кнопкой «Чек» в карточке счёта.

**Как выбить чек в Kaspi для ТОО и ИП?**
Порядок одинаковый: кнопки и запрос в ApiPay от формы организации не зависят. Нужны активная подписка ApiPay, подключённая Kaspi Касса, подключённый кассир, открытая смена и товары в каталоге. Позиции со ставкой НДС в чек через ApiPay не выбиваются.

**Можно ли отменить или переделать чек?**
Нет — фискальный документ необратим. Ошиблись — это вопрос возврата по правилам ОФД, не удаление чека.

---

ApiPay — независимый сервис и не аффилирован с АО «Kaspi Bank». Kaspi и Kaspi Pay — товарные знаки их правообладателя.
База знаний: https://apipay.kz/guides
