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

# Сколько живёт QR-счёт Kaspi и что это меняет?

**TL;DR.** QR-счёт Kaspi, выставленный через ApiPay (`POST /invoices/qr`), живёт **меньше трёх минут**: столько длится окно на скан, точный момент приходит в поле `qr_expires_at` ответа, продлить его нельзя. Поэтому QR-счёт — только для оплаты сразу: показать QR на экране кассы или отправить ссылку Kaspi на этот QR (`qr_token_url`) покупателю, который платит прямо сейчас. Истёкший QR покупатель увидит как «Попробуйте позже» — нужен новый счёт, а каждый созданный QR, в том числе сгоревший, занимает место в дневном лимите тарифа. Покупатель оплатит потом — [счёт по номеру телефона](/guides/kak-sozdat-schet-kaspi-po-nomeru) (24 часа) или [статический QR](/guides/pechatnyy-qr-dlya-oplaty-po-sdelke) (`print_url`, действует, пока сделка не оплачена или не отключена).

## Коротко

| Вопрос | Ответ |
|---|---|
| Эндпоинт | `POST https://api.apipay.kz/api/v1/invoices/qr` |
| Окно на скан | Меньше трёх минут; точный момент — `qr_expires_at` в ответе, длительность константой не зашивать; продления нет |
| Ответ | `201` сразу со статусом `pending` + `qr_token_url` (ссылка Kaspi на этот QR) + `qr_image_url` (готовый PNG) |
| Как доставить покупателю | Показать QR на экране или отправить `qr_token_url` в мессенджер — при условии, что покупатель оплатит в течение окна |
| Описание | До 100 символов (у счёта по номеру — до 60) |
| Скидка | Только целый процент; скидка строки округляется вверх до целого тенге |
| ИИН/БИН покупателя | Необязательно: `buyer_bin` — строка ровно из 12 цифр |
| Несколько QR одновременно | Да: QR-счета сосуществуют, новый не отменяет старые |
| Отмена QR-счёта | Не поддерживается: `POST /invoices/{id}/cancel` отвечает `409 qr_cancel_unsupported` |
| «Попробуйте позже» у покупателя | Почти всегда — QR истёк; создать новый |
| Скан виден | Вебхук `invoice.qr_scanned` — один раз на QR |
| Альтернатива на 24 часа | Счёт по номеру телефона (push в Kaspi) |
| Когда подходит | Только когда покупатель платит сразу |
| Лимит тарифа | Каждый созданный QR-счёт — место в лимите, даже если он сгорел без оплаты |
| Ссылка «на потом» | Ссылка на оплату `payment_url` (`POST /invoices/qr` со `"static": true` или `POST /static-qr`), выпущенная в рабочем режиме |

## Сколько на самом деле живёт QR?

Окно на скан задаёт Kaspi — **меньше трёх минут**. Точный момент приходит в `qr_expires_at`, оставшееся время считайте как `qr_expires_at − now` и не зашивайте длительность константой.

Окно ограничивает только **скан**: оплата, начатая под конец окна, завершится уже после `qr_expires_at`.

Терминальный статус (`paid`/`cancelled`/`expired`) ставит Kaspi и приносит вебхуком — ориентируйтесь на него, а не на локальный отсчёт. Продления нет: нужен новый QR — создавайте новый счёт. Помните, что каждый пересозданный QR — ещё одно место в лимите тарифа.

Показывайте покупателю таймер до `qr_expires_at`, а по его истечении — кнопку «Создать новый QR».

Когда покупатель сканирует истёкший QR, приложение Kaspi показывает «Попробуйте позже»: ждать бесполезно, нужен новый QR. Разбор остальных причин этого экрана — «[QR показывает «Попробуйте позже»](/guides/qr-poprobuyte-pozzhe)».

## Как создать QR-счёт через API?

```bash
curl -X POST https://api.apipay.kz/api/v1/invoices/qr \
  -H "X-API-Key: ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "description": "Заказ №123"
  }'
```

Ответ — сразу `201` со статусом `pending` (QR-создание синхронное, в отличие от счёта по номеру):

```json
{
  "id": 1,
  "amount": "5000.00",
  "status": "pending",
  "qr_token_url": "https://qr.kaspi.kz/...",
  "qr_image_url": "https://.../storage/qr/abc.png",
  "qr_expires_at": "2026-07-02T12:05:00+05:00"
}
```

- `qr_image_url` — готовая PNG-картинка QR на хранилище ApiPay: показывайте её как есть, рендерить QR самим не нужно. Картинка живёт до `qr_expires_at + 60 секунд`, дальше отдаёт `404` — это ожидаемо, перевыпустите QR, а не перезагружайте картинку.
- `qr_token_url` — **ссылка Kaspi на уже выпущенный QR-счёт**, а не ссылка на оплату «на потом». На телефоне покупателя она открывает оплату в приложении Kaspi — сканировать ничего не нужно: её можно отправить в WhatsApp или Telegram покупателю, который на связи. Работает ссылка в том же окне, что и QR-картинка: покупатель должен оплатить до `qr_expires_at` (минуты), иначе понадобится новый счёт. Ссылка на оплату, которую можно отправить «на потом», — поле `payment_url` («[Оплата по ссылке Kaspi](/guides/oplata-po-ssylke-kaspi)»); если режим ссылок выключен, отправляют `print_url` листа [статического QR](/guides/pechatnyy-qr-dlya-oplaty-po-sdelke).
- Телефон покупателя не нужен — в этом смысл QR-формата.
- В песочнице доступно поле `simulate: paid | cancelled | expired` — протестировать все исходы без реальной оплаты.

## Какие ограничения у QR-счёта надо знать заранее?

- **Описание — до 100 символов.** Больше — ошибка «Описание QR-счёта не должно превышать 100 символов». У счёта по номеру — до 60 символов.
- **Частота.** Потолок — **200 QR в минуту на организацию**, превышение даёт `429 qr_rate_limit`. Заголовка `Retry-After` в этом ответе нет — повторите запрос примерно через минуту. Лимит общий на организацию (не на ключ и не на кассира) и действует в том числе в песочнице. Отдельно действует суточный лимит тарифа — «[Дневной лимит счетов по тарифу](/guides/limit-schetov-po-tarifu)». В него входит каждый QR-счёт, созданный по API-ключу вне песочницы, в любом статусе: и оплаченный, и сгоревший. Поэтому не пересоздавайте QR-счёт по кругу, пока покупатель думает.
- **Ошибки создания:** `409 kaspi_session_expired`, реже `503` с телом `{"error": "kaspi_session_invalid"}` (поля `error_code` в нём нет — разбирайте `error`), — авторизация кассира оборвана, QR **не создан** и в кабинете не появится, повтор запроса не поможет: переподключите кассира в «Настройки → Авторизация Kaspi». Статусом `409` приходит и дубль ключа идемпотентности `duplicate_idempotency_key` — ветвитесь по коду, а не по статусу. Тем же статусом `503` приходит `invoices_disabled` — приём QR-счетов временно приостановлен, счёт не создан, кассира переподключать не нужно: повторите позже. Счета по номеру телефона (`POST /invoices`) в это время могут приниматься и ждать в статусе `processing`. Различайте причины по полю `error`. Дальше: `403 tariff_inactive` — подписка ApiPay неактивна, льготного периода нет (в песочнице этот гейт не действует); `502 kaspi_error` — ошибка на стороне Kaspi; `500 qr_render_failed` — не удалось сформировать картинку, повторите создание.
- **Возврат.** Обычный `POST /invoices/{id}/refund` применим и к оплате по QR; если Kaspi отказал — «[Возврат по QR через API](/guides/vozvrat-po-qr-cherez-api)».
- **Pending-вебхука нет:** статус `pending` вы уже получили синхронно в `201`; следующий вебхук будет `paid`/`cancelled`/`expired`.
- **Организация с каталогом.** QR-счёт такой организации создаётся только с корзиной: запрос с одним `amount` вернёт `422` с `error_code: catalog_requires_cart_items` (текст «This organization requires cart items»). Передавайте `cart_items` — так же, как в счёте с корзиной.
- **Скидка — по правилу Kaspi.** `discount_percentage` на QR — только целый процент от 1 до 99, дробный отбивается `422`. Скидка каждой строки округляется вверх до целого тенге, поэтому на дешёвой позиции она больше заявленной. Позиция с ценой в тиынах или скидка, обнуляющая позицию, дают `422 qr_discount_unsupported`. Итог берите из ответа (`amount`, `discount_sum`). Правило и примеры — «[Счета с корзиной](/guides/scheta-s-korzinoy-cart-items-ofd)».
- **ИИН/БИН покупателя.** Необязательное поле `buyer_bin` — строка ровно из 12 цифр, числом не передавайте: потеряется ведущий ноль. Если у организации подключена Kaspi Касса, номер попадёт в чек Kaspi. Kaspi номер не проверяет — сверьте все 12 цифр. Ссылке на оплату (`static: true`) номер не задаётся: покупатель заранее неизвестен.

## Можно ли держать несколько активных QR одновременно?

**Да.** QR-счета сосуществуют: создание нового QR **не отменяет** предыдущие, каждый созданный QR оплачиваем до своего истечения. Два параллельных запроса на создание оба получают `201`. Реагируйте на `paid`/`cancelled`/`expired` по каждому `invoice.id` отдельно: при оплате нескольких QR придёт несколько `paid`. `cancelled` по QR-счёту означает реальную отмену покупателем — он закрыл оплату или свернул приложение, не подтвердив.

Практическое следствие: для нескольких покупателей в очереди можно спокойно создавать по QR каждому. Каждый такой QR занимает место в лимите тарифа.

## Можно ли отменить QR-счёт?

**Нет.** `POST /invoices/{id}/cancel` для QR-счёта (`is_qr_token: true`) отвечает `409 qr_cancel_unsupported`: статус счёта не меняется, в Kaspi ничего не уходит. В теле ответа приходит `expires_at` — момент, после которого QR перестанет быть оплачиваемым.

Делать при этом ничего не нужно: QR гаснет сам по истечении окна на скан и уезжает в `expired`. Нужен другой счёт — просто выставьте новый, старый не мешает.

Пока счёт не перешёл в `expired`, считайте QR активным: оплатить его могут до конца окна на скан, даже если ваш код уже пометил заказ отменённым.

В песочнице отмена QR-счёта отвечает так же — `409 qr_cancel_unsupported`: песочница здесь повторяет бой.

Отмена по-прежнему работает для счетов на номер телефона — там ответ `202` и статус `cancelling`.

## Как узнать, что покупатель отсканировал QR?

Событие `invoice.qr_scanned` приходит вебхуком **один раз на QR**: статус счёта остаётся `pending`, добавляется маркер `qr_substate: "scanned"`. Это удобно для UI кассы («Клиент сканирует…»), но помните: скан — не оплата. После скана возможны и `paid`, и `cancelled` (покупатель закрыл или свернул приложение) — интерфейс должен уметь вернуться из «Ожидается подтверждение» в исходное состояние. Настройка вебхуков — «[Как настроить вебхуки ApiPay](/guides/nastroyka-webhookov-apipay)».

## Можно ли принимать QR-оплату Kaspi через API в ресторане или кафе?

Да, тем же QR-счётом — отдельного «ресторанного» режима в API нет. Когда гость просит счёт, ваша касса или учётная система вызывает `POST /invoices/qr` на сумму чека (с `cart_items`, если у организации подключён каталог) и показывает `qr_image_url` на экране кассы или планшете. Гость сканирует QR сразу, в пределах окна до `qr_expires_at`. Итог приходит вебхуком `invoice.status_changed`, а скан — событием `invoice.qr_scanned`. Если гость платит не сразу, выпускайте новый QR в момент оплаты, а не заранее к заказу. Эндпоинты и поля — в [документации API](/docs), обзор сценариев — «[Как принимать оплату Kaspi через API](/kaspi-api)».

## QR или счёт по номеру: как выбрать?

| Критерий | QR-счёт | Счёт по номеру |
|---|---|---|
| Окно на скан | Меньше трёх минут (точный момент — `qr_expires_at`); оплата, начатая до конца окна, завершается позже | 24 часа |
| Покупатель | Рядом, платит сейчас (касса, витрина, самовывоз, оплата на сайте «здесь и сейчас») | Удалённо, оплатит когда увидит push |
| Нужен ли номер телефона | Нет | Да (формат 8XXXXXXXXXX, номер должен быть в Kaspi) |
| Описание | ≤100 символов | ≤60 символов |
| Создание | Синхронное: `201 pending` + QR сразу | Асинхронное: `201 processing`, затем вебхук |
| Канал доставки | QR на экране, картинка `qr_image_url` или ссылка `qr_token_url` в мессенджер | Push в приложении Kaspi |

Простое правило: **QR-счёт — только для оплаты сразу: покупатель перед вами, перед экраном или в переписке и платит сейчас. Покупатель оплатит потом — счёт по номеру, статический QR (`print_url`) или одноразовая ссылка `payment_url`.** У статического QR и ссылки счёт создаётся, только когда покупатель нажал «Оплатить в Kaspi», поэтому пока он думает, лимит не тратится. Подробнее — «[Какой QR выбрать: QR-счёт или статический QR](/guides/kakoy-qr-vybrat-qr-schet-ili-staticheskiy)».

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

**Сколько действует QR-счёт Kaspi?**
Меньше трёх минут: столько длится окно на скан, точный момент — в поле `qr_expires_at` ответа. Продлить нельзя. Нужно дольше — счёт по номеру телефона (24 часа) или статический QR.

**Как дать покупателю ссылку на оплату Kaspi?**
Ссылка на оплату — поле `payment_url`: его отдают `POST /invoices/qr` со `static: true` и `POST /static-qr`. Она работает, пока сделка не оплачена и не отключена; выпускайте её в рабочем режиме — ссылка из песочницы остаётся тестовой навсегда. Покупателю, который платит прямо сейчас, подойдёт и `qr_token_url` QR-счёта — ссылка Kaspi на уже выпущенный QR, действует до `qr_expires_at`.

**Как создать QR-счёт, если у организации подключён каталог?**
Только с корзиной: передавайте `cart_items` вместо одного `amount`.

Смотрите также: [Какой QR выбрать](/guides/kakoy-qr-vybrat-qr-schet-ili-staticheskiy) · [Оплата по ссылке Kaspi](/guides/oplata-po-ssylke-kaspi) · [Как создать счёт по номеру](/guides/kak-sozdat-schet-kaspi-po-nomeru) · [Kaspi-оплата на сайте](/guides/kaspi-oplata-na-sayte) · [Документация API](/docs) · [Вебхуки ApiPay](/guides/nastroyka-webhookov-apipay) · пиллар «[Как принимать оплату Kaspi через API](/kaspi-api)».

---

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