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

# Оплата Kaspi по ссылке: как отправить покупателю ссылку

**TL;DR.** Да, ссылку на оплату отправить можно, и видов у неё два. `POST /invoices/qr` возвращает **`qr_token_url`** — ссылку на оплату (payment link): её можно показать покупателю QR-кодом на экране, а можно просто отправить в WhatsApp или Telegram, он откроет её на телефоне и заплатит в приложении Kaspi. Окно, в которое покупатель успевает открыть эту ссылку, задаёт Kaspi — точный момент всегда приходит в `qr_expires_at`, и это скорее «прямо сейчас», чем «завтра». Если платить будут потом — берите **`print_url`** из `POST /static-qr`: это ссылка на страницу оплаты сделки, она не истекает, пока лист не оплачен и не отключён, и годится и для печати, и для отправки в мессенджер. У счёта по номеру телефона (`POST /invoices`) ссылки для отправки нет — покупателю приходит push в приложении Kaspi, и счёт ждёт 24 часа.

## Коротко

| Вопрос | Ответ |
|---|---|
| Можно ли отправить покупателю ссылку на оплату | Да. `qr_token_url` (`POST /invoices/qr`) — «оплатить сейчас»; `print_url` (`POST /static-qr`) — «оплатить потом» |
| Нужен ли номер телефона покупателя | Для обеих ссылок — нет |
| Сколько живёт `qr_token_url` | До `qr_expires_at` из ответа; длительность окна задаёт Kaspi, константой её не зашивать |
| Сколько живёт `print_url` | Пока лист не оплачен, не отключён и не наступил заданный вами `expires_at` |
| Что делать, когда ссылка истекла | Создать новый QR-счёт: продления нет |
| Как понять, что заплатили | Вебхук со статусом `paid` (или `GET /invoices/{id}`). Событие `invoice.qr_scanned` — это скан, а не оплата |
| Лимит на создание | До 60 QR в минуту на организацию, превышение — `429 qr_rate_limit` |
| Отмена QR-счёта | Не поддерживается: `POST /invoices/{id}/cancel` отвечает `409 qr_cancel_unsupported` |

## Три способа получить оплату

| | Счёт по номеру | Оплата по ссылке или QR | Печатный QR под сделку |
|---|---|---|---|
| Эндпоинт | `POST /invoices` | `POST /invoices/qr` | `POST /static-qr` |
| Что уходит покупателю | Ничего не отправляете: приходит push в Kaspi | Ссылка `qr_token_url` или картинка `qr_image_url` | Ссылка `print_url` или напечатанный лист |
| Нужен номер покупателя | Да, `8XXXXXXXXXX` | Нет | Нет |
| Сколько ждёт оплату | 24 часа | До `qr_expires_at` — окно задаёт Kaspi | Пока не оплачен или не отключён |
| Когда выбирать | Покупатель «где-то там», реагирует на push | Покупатель в чате или у экрана **прямо сейчас** | Платить будут **потом**: акт, коробка, договор, витрина |

Одно простое правило: **ссылка «сейчас» — `qr_token_url`, ссылка «потом» — `print_url`, без ссылки вовсе — счёт по номеру телефона.**

## Когда какая ссылка подходит

- **Магазин в Instagram или WhatsApp.** Покупатель написал, договорились о сумме — отправляете `qr_token_url` прямо в переписку, он открывает и платит, не выходя из чата. Если разговор оборвался и покупатель вернулся через час, ссылка уже не сработает: выставьте новую.
- **Доставка.** Курьер у двери — `qr_token_url` в чат или QR на экране телефона курьера. Если заказ оставляют у двери и оплата ожидается позже, в коробку кладётся печатный лист (`print_url`).
- **Чат с покупателем и переписка по сделке.** Сумма согласована — ссылка уходит одним сообщением. Ссылку удобно сопровождать суммой текстом: покупатель увидит её и на странице оплаты.
- **Услуги и работы по акту.** Оплату ждут после приёмки — печатный лист под сделку. Он лежит в документах и работает через неделю так же, как в день выпуска.
- **Сайт или бот без своего сервера.** API-ключ — серверный секрет, в код, исполняемый в браузере, его класть нельзя. Пока сервера нет, выставляйте счёт в кабинете и отправляйте ссылку руками; когда сервер появится, тот же сценарий переносится в `POST /invoices/qr` без изменений для покупателя. Разбор по площадкам — «[ApiPay для интернет-магазина](/guides/apipay-dlya-internet-magazina)» и «[Kaspi-оплата в Telegram-боте](/guides/kaspi-oplata-v-telegram-bote)».

## Как получить ссылку на оплату

```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",
    "external_order_id": "order-123"
  }'
```

Ответ приходит сразу — `201` со статусом `pending`:

```json
{
  "id": 1,
  "amount": "5000.00",
  "status": "pending",
  "is_qr_token": true,
  "qr_token_url": "https://qr.kaspi.kz/...",
  "qr_image_url": "https://.../storage/qr/abc.png",
  "qr_expires_at": "2026-09-03T07:03:00+00:00"
}
```

- **`qr_token_url` — это и есть ссылка на оплату.** Отправьте её покупателю в мессенджер: он открывает её на телефоне, где установлено приложение Kaspi, и платит там — сканировать ничего не нужно. Открытая на компьютере ссылка к оплате не приведёт: покажите рядом `qr_image_url`, чтобы человек навёл на экран телефон.
- `qr_image_url` — готовая картинка QR той же оплаты: показывайте её на экране, если покупатель рядом. Рисовать QR самим не нужно.
- `qr_expires_at` — момент, до которого ссылку успевают открыть. Считайте остаток как `qr_expires_at − now` и не зашивайте длительность окна константой: её задаёт Kaspi.

То же самое из кода:

```js
const res = await fetch('https://api.apipay.kz/api/v1/invoices/qr', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.APIPAY_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 5000,
    description: 'Заказ №123',
    external_order_id: 'order-123',
    external_order_id_idempotency: 'order-123',
  }),
})

const invoice = await res.json()

// Ссылка на оплату — отправляем покупателю в чат
await sendMessage(chatId, `Оплата 5000 ₸: ${invoice.qr_token_url}`)
// invoice.qr_expires_at — до этого момента ссылку успеют открыть
```

Ключ `X-API-Key` живёт только на сервере. Ссылку покупателю отправляет ваш код, а не браузер покупателя.

## Ссылка перестала открываться — что делать

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

Если ссылку регулярно не успевают открыть — это сигнал, что сценарий не «сейчас», а «потом»: перенесите его на печатный лист или на счёт по номеру телефона.

Ссылки **сосуществуют**: новая не отменяет прежние, каждая созданная оплачиваема до своего истечения. Двум покупателям в очереди можно спокойно выдать по своей ссылке.

## Как понять, что покупатель заплатил

Ждите вебхук со статусом `paid` — или, если вебхуков ещё нет, читайте `GET /invoices/{id}`. Настройка — «[Как настроить вебхуки ApiPay](/guides/nastroyka-webhookov-apipay)».

⚠️ **Событие `invoice.qr_scanned` — не оплата.** Оно приходит, когда покупатель открыл оплату: статус счёта остаётся `pending`, добавляется маркер `qr_substate: "scanned"`. Как и любое событие, оно может продублироваться при повторной доставке — дедуплицируйте по паре `(invoice.id, invoice.status)`. После него возможны и `paid`, и `cancelled` — покупатель мог закрыть приложение, не подтвердив. Интерфейс кассы должен уметь вернуться из «Ожидается подтверждение» обратно в исходное состояние.

Отменить QR-счёт нельзя: `POST /invoices/{id}/cancel` отвечает `409 qr_cancel_unsupported`, статус не меняется. Делать при этом ничего не нужно — ссылка гаснет сама и счёт уезжает в `expired`. Отмена работает у счетов по номеру телефона. Если покупатель успел оплатить счёт с неверной суммой, деньги возвращаются обычным возвратом `POST /invoices/{id}/refund`, а не отменой.

⚠️ **В песочнице отмена ведёт себя иначе:** тестовый QR-счёт отменяется как обычный — `200` и статус `cancelled`. Не калибруйте по этому боевую логику: в рабочем режиме придёт `409 qr_cancel_unsupported`. Подробнее — «[Сколько живёт QR-счёт](/guides/qr-schet-ttl-i-limity)».

## Что нужно знать до первого запроса

- **Описание — до 100 символов.** Это наименование позиции в чеке Kaspi.
- **Частота — до 60 QR в минуту на организацию.** Превышение даёт `429 qr_rate_limit`; лимит общий на организацию, не на ключ и не на кассира, и действует в том числе в песочнице. Отдельно работает суточный лимит тарифа — «[Дневной лимит счетов по тарифу](/guides/limit-schetov-po-tarifu)».
- **Организация с каталогом.** И ссылку на оплату, и печатный лист такой организации выдаёт только запрос с корзиной: `POST /invoices/qr` и `POST /static-qr` с одним `amount` вернут `422` с `error_code: catalog_requires_cart_items`. Передавайте `cart_items` — «[Счета с корзиной](/guides/scheta-s-korzinoy-cart-items-ofd)».
- **Песочница.** В тестовом режиме реальных оплат нет; поле `simulate` (`paid`, `cancelled`, `expired`) позволяет проверить все исходы — «[Песочница и рабочий режим](/guides/pesochnitsa-i-rabochiy-rezhim)».

## Долгоживущая ссылка: печатный лист под сделку

Когда платить будут не сейчас, счёт выпускается один раз и ждёт покупателя:

```bash
curl -X POST https://api.apipay.kz/api/v1/static-qr \
  -H "X-API-Key: ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 45000,
    "description": "Ремонт стиральной машины",
    "external_order_id": "deal_1024"
  }'
```

В ответе — `print_url`, восьмисимвольный `short_code` для ручного ввода, `manual_url` (куда этот код вводят) и `qr_image_url` — непротухающая картинка QR для печати.

**`print_url` — тоже ссылка на оплату, только долгоживущая.** Её зашивают в QR-код на бумаге, но точно так же можно отправить в мессенджер: покупатель откроет страницу с названием магазина и суммой, нажмёт «Открыть Kaspi» и заплатит. Если приложение не открылось, на той же странице есть запасной путь — покупатель вводит свой номер телефона и получает запрос на оплату push-уведомлением. Что видит покупатель на самом счёте в Kaspi — «[Что видит покупатель](/guides/chto-vidit-pokupatel)»: сама оплата в обоих случаях проходит в приложении Kaspi.

Лист привязан к одной сделке: после оплаты повторное открытие показывает «Оплачено». Сумма изменилась или сделка отменилась — отключите лист (`DELETE /api/v1/static-qr/{id}`) и выпустите новый; описание у выпущенного листа не меняется. Ссылка листа и её токен — это и есть доступ к оплате: не выкладывайте лист туда, где он не нужен. Подробности печати и вёрстки — «[Печатный QR для оплаты по счёту или сделке](/guides/pechatnyy-qr-dlya-oplaty-po-sdelke)».

## А поле kaspi_qr_link — это тоже ссылка?

У обычного счёта по номеру телефона в карточке есть поле `kaspi_qr_link` — ссылка на оплату **этого** счёта по QR. Она вычисляется из идентификатора, который Kaspi присваивает счёту, поэтому появляется не сразу: пока счёт в `processing`, поле `null`, и в песочнице оно `null` всегда.

Строить на нём сценарий «отправить покупателю ссылку» не стоит: для этого есть `qr_token_url` — он приходит сразу в ответе на создание. Про сам счёт по номеру — «[Как создать счёт по номеру](/guides/kak-sozdat-schet-kaspi-po-nomeru)».

## Как это выглядит в кабинете

Разработчик для ссылки не обязателен. В кабинете: **Счета → Создать счёт → переключатель «Ссылка или QR-код»**. Номер покупателя вводить не нужно — достаточно суммы и описания.

После создания под QR-кодом видна сама ссылка, а рядом две кнопки: **«Открыть в Kaspi»** — проверить, как это выглядит у покупателя, и **«Скопировать ссылку»** — вставить её в WhatsApp или Telegram.

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

**Можно ли отправить ссылку на оплату Kaspi в WhatsApp?**
Да. Создайте QR-счёт (`POST /invoices/qr`) и отправьте покупателю `qr_token_url` из ответа — на телефоне покупателя она открывает оплату в приложении Kaspi. В кабинете тот же результат даёт кнопка «Скопировать ссылку». Одно условие: покупатель должен открыть ссылку в отведённое окно, поэтому отправляйте её, когда человек на связи.

**Сколько живёт ссылка на оплату?**
`qr_token_url` действует до `qr_expires_at` из ответа — длительность этого окна задаёт Kaspi, поэтому берите поле, а не константу в коде. Продлить нельзя: нужен новый QR-счёт. Ссылка печатного листа (`print_url`) живёт, пока лист не оплачен, не отключён и не наступил заданный вами `expires_at`.

**Чем оплата по ссылке отличается от печатного QR?**
Сроком жизни и сценарием. `qr_token_url` — для «платим прямо сейчас»: покупатель в чате или у экрана. `print_url` — для «заплатят потом»: акт, коробка с заказом, договор, витрина. Технически обе ссылки ведут покупателя к одной и той же оплате в приложении Kaspi.

**Нужен ли номер телефона покупателя?**
Нет. Ни для `qr_token_url`, ни для `print_url` номер не нужен — в этом их смысл. Номер требуется только счёту по номеру телефона (`POST /invoices`), где покупателю приходит push.

**Как понять, что по ссылке заплатили?**
По вебхуку со статусом `paid` или запросом `GET /invoices/{id}`. Событие `invoice.qr_scanned` означает только, что покупатель открыл оплату: статус остаётся `pending`, и после скана возможна отмена. Дожидайтесь `paid`.

**Можно ли отменить ссылку, если покупатель передумал?**
У QR-счёта отмены нет — `POST /invoices/{id}/cancel` вернёт `409 qr_cancel_unsupported`. Делать ничего не нужно: ссылка перестанет работать сама. Печатный лист отключается запросом `DELETE /api/v1/static-qr/{id}`.

Смотрите также: [QR-счёт: сколько живёт и какие лимиты](/guides/qr-schet-ttl-i-limity) · [Печатный QR под сделку](/guides/pechatnyy-qr-dlya-oplaty-po-sdelke) · [Счёт по номеру телефона](/guides/kak-sozdat-schet-kaspi-po-nomeru) · пиллар «[Как принимать оплату Kaspi через API](/kaspi-api)».

---

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