API документация
REST-API сервиса удалённой оплаты Kaspi. Твои продукты (сайт, бот, 1С) выставляют счета и получают вебхук об оплате.
Base URL: http://localhost:3200 (локально). Все тела — JSON, кодировка UTF-8.
Авторизация
Публичные эндпоинты счетов требуют заголовок X-API-Key — ключ магазина (получаешь при создании магазина, формат kpk_…).
X-API-Key: kpk_35a046ba417358733cf53862163ccb40ccef33ed
Форматы номеров
| Контекст | Формат | Пример |
|---|---|---|
| Клиент (в счёте) | 11 цифр, начинается с 7 | 77001234567 |
| Кассир (онбординг) | 10 цифр, начинается с 7 (без 8 и без +7) | 7001234567 |
Суммы — целые, в тенге (минимальная единица — 1 ₸).
Счета
Основной сценарий: создаёшь счёт → клиент платит в Kaspi → тебе прилетает вебхук. Все эндпоинты требуют X-API-Key.
Выставить счёт с push-уведомлением в приложение клиента.
| Поле | Описание | |
|---|---|---|
| phone | required | Номер клиента, 11 цифр (77XXXXXXXXX) |
| amount | required | Сумма в тенге, целое > 0 |
| comment | optional | Комментарий, до 255 символов |
| idempotencyKey | optional | Ключ идемпотентности — повтор с тем же ключом вернёт существующий счёт (200) |
# запрос curl -X POST http://localhost:3200/invoices \ -H "X-API-Key: kpk_…" -H "Content-Type: application/json" \ -d '{"phone":"77001234567","amount":1500,"comment":"Заказ №42","idempotencyKey":"order-42"}'
// 201 Created { "id": "16286362815", "kaspiInvoiceId": "16286362815", "status": "PENDING", "amount": 1500, "phone": "77001234567", "kind": "phone", "createdAt": "2026-07-01T07:08:39.000Z" }
409 {"code":"NEEDS_REAUTH"} — сессия кассира истекла, нужен повторный вход. 502 — ошибка провайдера Kaspi.
Создать оплату по ссылке (QR-токен Kaspi). Номер клиента не нужен — ссылку pay.kaspi.kz отправляешь в любой мессенджер.
| Поле | Описание | |
|---|---|---|
| amount | required | Сумма в тенге |
| comment | optional | Комментарий |
| idempotencyKey | optional | Ключ идемпотентности |
curl -X POST http://localhost:3200/invoices/link \ -H "X-API-Key: kpk_…" -H "Content-Type: application/json" \ -d '{"amount":1500}'
// 201 Created { "id": "16286370001", "kaspiInvoiceId": "16286370001", "status": "PENDING", "amount": 1500, "kind": "link", "payUrl": "https://pay.kaspi.kz/pay/abc123", "expireAt": "2026-07-01T07:20:00.000Z", "createdAt": "2026-07-01T07:08:39.000Z" }
Список счетов магазина (новые сверху, до 50). Возвращает массив Invoice.
Один счёт по внутреннему id. 404 если не найден.
Отменить счёт. Возвращает обновлённый Invoice со статусом CANCELED.
Возврат по оплаченному счёту. Тело {"amount": 500} — необязательно (по умолчанию полная сумма).
curl -X POST http://localhost:3200/invoices/ID/refund \ -H "X-API-Key: kpk_…" -H "Content-Type: application/json" \ -d '{"amount":500}' # → {"ok":true,"refunded":500}
Имя клиента Kaspi по номеру (11 цифр) — для подтверждения перед выставлением счёта.
curl http://localhost:3200/clients/lookup?phone=77001234567 \ -H "X-API-Key: kpk_…" # → {"name":"Иван И."}
Вебхуки
При смене статуса счёта сервис делает POST на webhook.url магазина. Ретраи 5с/30с при неуспехе.
Заголовки: X-Webhook-Signature: sha256=<hmac>, X-Webhook-Id, X-Idempotency-Key: invoiceId:event.
// тело POST на твой endpoint { "event": "invoice.paid", // paid | failed | expired | canceled "invoiceId": "16286362815", "kaspiInvoiceId": "16286362815", "status": "PAID", "amount": 1500, "phone": "77001234567", "occurredAt": "2026-07-01T07:10:12.000Z" }
Проверка подписи (Node.js)
import { createHmac, timingSafeEqual } from 'node:crypto'; function verify(rawBody, header, secret) { const mac = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex'); const a = Buffer.from(mac), b = Buffer.from(header || ''); return a.length === b.length && timingSafeEqual(a, b); }
Кассир · онбординг
Трёхшаговый вход по SMS. processId из шага 1 прокидывается дальше. Номер кассира — 10 цифр (см. форматы).
Инициализация. Ответ: {"success":true,"processId":"…"}.
Тело {"phoneNumber":"7001234567","processId":"…"}. Kaspi отправит код (SMS или пуш в приложение — зависит от аккаунта). Ответ содержит success, view, desc.
Тело {"otp":"123456","processId":"…"}. Ответ {"connected":true,"orgName":"…"} — сессия кассира сохранена.
KPEnterLoginPassword, обычно бизнес-профили) текущим флоу не поддерживаются — используй клиентский номер кассира с SMS-входом.Отключить кассира (удалить сессию на нашей стороне). Полностью отозвать «устройство» можно только в приложении Kaspi владельца: Настройки → Безопасность → Устройства.
Магазины
Управление арендаторами (админ). Каждый магазин = свой API-ключ + webhook + выделенный sidecar.
Создать магазин. Тело {"name":"Мой магазин","webhookUrl":"https://shop/hook"}.
// 201 — секреты показываются один раз { "id": "m-f2b547a7", "name": "Мой магазин", "apiKey": "kpk_…", "webhookSecret": "87ba…", "sidecarUrl": "http://sidecar1:3000" }
Список магазинов со статусом кассира (connected, sessionStatus, orgName, webhookUrl).
Изменить name / webhookUrl / webhookSecret. Тело — любые из этих полей.
Удалить магазин (каскадно чистит сессию и счета, освобождает слот пула sidecar).
Отправить пробное invoice.paid на webhook магазина. Ответ {"delivered":true,"statusCode":200,"attempts":1}.
Статус и метрики
{"sidecarUp":true,"connected":true,"sessionStatus":"ACTIVE","orgName":"…"}
{ "todayRevenue": 12500, "todayPaidCount": 8, "pendingCount": 2,
"totalCount": 40, "conversion": 0.65,
"series": [{ "day": "06-25", "revenue": 3000 }, … ] }Доставки вебхуков
Журнал отправок: event, invoiceId, delivered, statusCode, attempts, lastAt.
Повторить доставку. Ответ {"delivered":true,"statusCode":200}.
Объект Invoice
| Поле | Тип | Описание |
|---|---|---|
| id | string | Внутренний id счёта |
| kaspiInvoiceId | string | id операции в Kaspi (QrOperationId) |
| status | string | См. статусы |
| amount | number | Сумма, ₸ |
| phone | string | Номер клиента (пусто для ссылки) |
| kind | string | phone | link |
| payUrl | string? | Ссылка pay.kaspi.kz (для link) |
| expireAt | string? | Истечение ссылки (ISO) |
| comment | string? | Комментарий |
| receiptUrl | string? | Квитанция Kaspi ОФД |
| createdAt / paidAt | string | Время (ISO 8601) |
Статусы счёта
PENDING ожидает оплату PAID оплачено FAILED отклонено EXPIRED истёк срок CANCELED отменён
KSPX · внутренний API. Механизм — реверс мобильного POS Kaspi, продовое использование на свой риск.