ДокументацияВведение
Коды ошибок

Приём платежей

QR и счета через API

Прямые вызовы для POS и push-инвойсов

QR и счета — это два прямых способа принять оплату через Kaspi Pay из вашего кода: POST /v2/qr создаёт Kaspi QR-код для сканирования на кассе или в приложении, а POST /v2/invoices отправляет push-счёт прямо на телефон плательщика по его номеру. Оба эндпоинта требуют API-ключ (X-API-Key), обязательный заголовок Idempotency-Key и возвращают operation_id, по которому вы затем опрашиваете статус оплаты. Это низкоуровневый путь для собственного POS или бэкенда — если вам нужна готовая страница оплаты, используйте платёжные ссылки.

Все суммы — целые тенге (₸), минимум 100. Для аккаунтов с несколькими подключёнными Kaspi-кошельками добавляйте заголовок X-Kaspi-Account: ; без него берётся аккаунт по умолчанию.

Как создать QR-код для оплаты

Отправьте POST /v2/qr с суммой в тенге и обязательным заголовком Idempotency-Key. В ответ придёт operation_id, сырой qr_token (для отрисовки собственного QR), deep_link (открывает приложение Kaspi на телефоне) и время истечения expires_at — обычно около 5 минут.

bash
Скачать
curl -X POST https://api.paybot.kz/v2/qr \
  -H "X-API-Key: kp_live_00112233445566778899aabbccddeeff" \
  -H "Idempotency-Key: 7c1e9b2a-4d5f-4a8c-9e10-2b3d6f8a0c11" \
  -H "X-Kaspi-Account: acc_01H..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "comment": "Заказ #1234",
    "items": [{"name": "Кофе", "price": 1500, "qty": 1}]
  }'
python
Скачать
import requests, uuid

resp = requests.post(
    "https://api.paybot.kz/v2/qr",
    headers={
        "X-API-Key": "kp_live_00112233445566778899aabbccddeeff",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"amount": 5000, "comment": "Заказ #1234"},
)
qr = resp.json()
print(qr["operation_id"], qr["deep_link"], qr["expires_at"])

Пример ответа 200 OK:

json
Скачать
{
  "operation_id": "1450012345",
  "qr_token": "3010100100AC0000QRTOKEN...",
  "deep_link": "https://kaspi.kz/pay?qr=3010...",
  "expires_at": "2026-07-16T10:05:00Z",
  "status": "created"
}

Поля тела запроса: amount (обязателен, целые тенге, минимум 100), comment (опционально, ≤255 символов, виден плательщику) и items — опциональная корзина [{name, price, qty}]. Отрисуйте qr_token в QR-код в своём интерфейсе или дайте покупателю deep_link на телефоне.

Как проверить статус QR-операции

GET /v2/qr/{op_id} синхронизирует статус с Kaspi и возвращает нормализованное состояние, сумму, ФИО плательщика и сырой статус Kaspi для отладки.

bash
Скачать
curl https://api.paybot.kz/v2/qr/1450012345 \
  -H "X-API-Key: kp_live_00112233445566778899aabbccddeeff"
json
Скачать
{
  "operation_id": "1450012345",
  "status": "paid",
  "amount": 5000,
  "sender_name": "IVAN I.",
  "transaction_id": "TX1234567890",
  "paid_at": "2026-07-16T10:03:12Z",
  "raw_kaspi_status": "Processed"
}

Поле raw_kaspi_status (Wait, Processed, Cancelled, Expired, …) полезно для поддержки, когда нормализованного status недостаточно. Опрашивать статус в цикле нужно не всегда — надёжнее подписаться на вебхук payment.completed и не поллить вручную.

Как отправить счёт (push на телефон)

POST /v2/invoices отправляет push-уведомление со счётом прямо в приложение Kaspi на телефоне плательщика — покупателю не нужно ничего сканировать. Требуется номер телефона в формате 7XXXXXXXXX (10–15 символов) и обязательный Idempotency-Key.

bash
Скачать
curl -X POST https://api.paybot.kz/v2/invoices \
  -H "X-API-Key: kp_live_00112233445566778899aabbccddeeff" \
  -H "Idempotency-Key: 9a2f4b6c-1d3e-4f8a-8c20-5e7b9d1f0a22" \
  -H "Content-Type: application/json" \
  -d '{"phone": "7771234567", "amount": 5000, "comment": "Заказ #1234"}'
python
Скачать
import requests, uuid

resp = requests.post(
    "https://api.paybot.kz/v2/invoices",
    headers={
        "X-API-Key": "kp_live_00112233445566778899aabbccddeeff",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"phone": "7771234567", "amount": 5000, "comment": "Заказ #1234"},
)
print(resp.json())

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

json
Скачать
{
  "operation_id": "1450098765",
  "status": "created",
  "expires_at": "2026-07-17T10:00:00Z"
}

Счёт живёт около 24 часов (expires_at) — гораздо дольше QR. Поля запроса: phone (обязателен), amount (обязателен, целые тенге, минимум 100), comment (≤255, виден в push-уведомлении).

Как узнать статус счёта

GET /v2/invoices/{op_id} возвращает статус счёта, сумму, телефон плательщика и время оплаты.

bash
Скачать
curl https://api.paybot.kz/v2/invoices/1450098765 \
  -H "X-API-Key: kp_live_00112233445566778899aabbccddeeff"
json
Скачать
{
  "operation_id": "1450098765",
  "status": "paid",
  "amount": 5000,
  "phone": "7771234567",
  "paid_at": "2026-07-16T10:07:45Z"
}

Как отменить счёт

POST /v2/invoices/{op_id}/cancel отменяет ещё не оплаченный счёт. В отличие от v1, этот вызов тоже требует заголовок Idempotency-Key.

bash
Скачать
curl -X POST https://api.paybot.kz/v2/invoices/1450098765/cancel \
  -H "X-API-Key: kp_live_00112233445566778899aabbccddeeff" \
  -H "Idempotency-Key: e1c3a5b7-2d4f-4a6c-8e90-1b3d5f7a9c33"

Какие бывают статусы платежа

Нормализованный status в ответах QR и счёта принимает единый набор значений.

СтатусЗначение
createdОперация создана, ждём оплату.
paidОплачено.
expiredИстёк срок (QR ~5 минут, счёт ~24 часа).
cancelledОтменено.
failedОплата не удалась.
refundedПо операции сделан возврат.

Как правильно опрашивать статус

Опрос статуса нужен, когда вы не используете вебхуки. Соблюдайте несколько правил, чтобы не упереться в лимит API (20 запросов в минуту на боевой ключ).

  • Опрашивайте GET /v2/qr/{op_id} или GET /v2/invoices/{op_id} с интервалом в несколько секунд, а не в тугом цикле.
  • Останавливайте поллинг, как только status стал финальным (paid, expired, cancelled, failed).
  • Для QR прекращайте опрос после expires_at — обновлять QR имеет смысл только выдав новый.
  • По возможности вообще замените поллинг на вебхук payment.completed — это надёжнее и не тратит лимит.

Заголовок Idempotency-Key обязателен на всех мутирующих вызовах (POST /v2/qr, POST /v2/invoices, POST /v2/invoices/{op_id}/cancel); генерируйте один ключ на одно намерение пользователя — подробнее в разделе Идемпотентность.

FAQ

Чем QR отличается от счёта?

QR (POST /v2/qr) создаёт код, который плательщик сам сканирует камерой или в приложении Kaspi — подходит для кассы, витрины и оплаты «здесь и сейчас». Счёт (POST /v2/invoices) отправляет push-уведомление прямо на телефон по номеру, и покупателю ничего сканировать не нужно — это удобно для дистанционной продажи, когда вы знаете номер клиента. QR живёт ~5 минут, счёт — ~24 часа.

Как долго живёт QR?

Около 5 минут — точное время истечения приходит в поле expires_at (UTC), ориентируйтесь на него, а не на константу. Когда QR истёк, а оплата ещё нужна, создайте новый вызовом POST /v2/qr. Счёт, в отличие от QR, действует примерно сутки.

Как отличить тестовый платёж от боевого?

По префиксу API-ключа: kp_test_... работает в песочнице (sandbox), kp_live_... — в бою. В тестовом режиме обходятся rate-limit и проверка живости Kaspi-сессии, а операции не списывают реальные деньги. Подробнее — в разделе о тестировании.

Нужен ли `X-Kaspi-Account`, если кошелёк один?

Нет. Заголовок X-Kaspi-Account нужен только при нескольких подключённых Kaspi-аккаунтах, чтобы выбрать, на какой из них принять оплату. Если аккаунт один, PayBot возьмёт его по умолчанию.