Главная › Документация API
Reference · v1Документация API
Полный технический референс Kaspi Pay invoice API: авторизация по SMS,
создание счёта, статусы, отмена, возвраты, вебхуки с
X-Webhook-Signature: sha256=..., коды ошибок.
Правовые положения
Отказ от ответственности
Сервис PayProverkaBot (pay.proverkacheka.kz) не связан и не аффилирован с АО «Kaspi Bank» или любыми другими организациями группы Kaspi. Мы не являемся платёжным сервисом, эквайрингом или финансовой организацией. Мы не являемся партнёрами, представителями или агентами Kaspi.
PayProverkaBot предоставляет техническую услугу — программный интерфейс к функции «удалённый счёт» приложения Kaspi Pay для бизнеса от имени самого мерчанта, после его добровольной авторизации по SMS на его собственный номер.
Ответственность пользователя
Используя сервис, вы подтверждаете, что:
- Вы являетесь владельцем (или уполномоченным представителем) аккаунта Kaspi Pay для бизнеса, по которому проходит авторизация.
- Вы соблюдаете законодательство Республики Казахстан и условия Kaspi.
- Вы используете сервис в законных целях — автоматизация выставления счетов, интеграция с CRM, чат-ботами, кассовыми системами.
- Вы не используете сервис для незаконной деятельности, отмывания денег, уклонения от налогов или иных противоправных действий.
Администрация PayProverkaBot не несёт ответственности за прямые или косвенные убытки, возникшие в результате использования сервиса, блокировки аккаунта Kaspi или технических сбоев на стороне Kaspi.
Начало работы
Как получить API-ключ
- Откройте @PayProverkaBot в Telegram.
- Нажмите
/start— получите персональныйAPI_KEY. - Авторизуйтесь в Kaspi Pay:
/login→ отправьте номер телефона ИП/ТОО → введите SMS-код. - Готово — можете выставлять счета через бота (
/invoice 87019009393 1500 За кофе) или через REST API.
/apikey в боте покажет ваш ключ повторно.
Команда /account покажет, к какому аккаунту Kaspi привязана сессия.
Базовый URL и заголовки
- Базовый URL:
https://pay.proverkacheka.kz/api - Авторизация: заголовок
X-API-Key: <ваш_ключ> - Content-Type:
application/jsonдля всех POST/PUT
Что делает сервис
- Создаёт удалённый счёт Kaspi Pay — клиенту приходит push-уведомление в Kaspi.kz, где он подтверждает оплату одним нажатием.
- Возвращает
paymentIdдля отслеживания статуса. - Поллит статус в фоне и доставляет вебхук, как только клиент оплатил, отказался или счёт истёк.
- Поддерживает отмену неоплаченного счёта и возврат (полный / частичный) оплаченного.
Проверка API-ключа
Сам онбординг (SMS-логин в Kaspi) проходит через Telegram-бота — это внутренний процесс сервиса. Через API доступна только проверка выданного ключа:
GET/v1/auth/me
Возвращает информацию о привязанной сессии Kaspi.
curl https://pay.proverkacheka.kz/api/v1/auth/me \
-H "X-API-Key: $API_KEY"
Создание счёта
POST/v1/invoice/create
Создаёт удалённый счёт Kaspi Pay с корзиной товаров. Клиенту приходит push-уведомление
в Kaspi.kz. Сумма счёта рассчитывается автоматически как Σ(items[i].price × items[i].count).
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
phoneNumber required | string | Номер клиента. Сервис автоматически нормализует — принимаются форматы 87019009393, 77019009393, 7019009393, +7 701 900 93 93. На вход в Kaspi уходит каноничный 8XXXXXXXXXX. На невалидный формат — 400 invalid_phone. |
items required | array | 1–50 позиций корзины. См. ниже. |
comment optional | string | Описание счёта. По умолчанию — названия позиций через запятую. |
Структура items[i]
| Поле | Тип | Описание |
|---|---|---|
name required | string (1–200) | Название товара/услуги — показывается в чеке клиента. |
price required | number > 0 | Цена за единицу в тенге. |
count optional | integer > 0 | Количество. По умолчанию 1. |
Пример
curl -X POST https://pay.proverkacheka.kz/api/v1/invoice/create \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "87019009393",
"comment": "Заказ #42",
"items": [
{ "name": "Капучино", "price": 1200, "count": 2 },
{ "name": "Чизкейк", "price": 1800, "count": 1 }
]
}'
{
"paymentId": "14918505280",
"cartId": "c8a91b...",
"amount": 4200.0,
"status": "RemotePaymentCreated",
"receiptUrl": null
}
Статус и список
GET/v1/invoice/{paymentId}
Возвращает актуальный статус и (после оплаты) ссылку на чек.
curl https://pay.proverkacheka.kz/api/v1/invoice/14918505280 \
-H "X-API-Key: $API_KEY"
{
"paymentId": "14918505280",
"status": "Processed",
"amount": "4 200 ₸",
"clientMobile": "87019009393",
"receiptUrl": "https://receipt.kaspi.kz/..."
}
Возможные статусы
| Status | Значение |
|---|---|
RemotePaymentCreated | ⏳ Ожидает оплаты клиентом |
Processed | ✅ Оплачен |
RemotePaymentRejected | ❌ Клиент отказался |
RemotePaymentCanceled | 🚫 Отменён мерчантом |
RemotePaymentExpired | ⌛ Истёк срок (~24 часа) |
Refunded | ↩️ Полностью возвращён |
PartiallyRefunded | ↩️ Частично возвращён |
GET/v1/invoice
Список активных (не финализированных) счетов, отслеживаемых сервисом.
curl https://pay.proverkacheka.kz/api/v1/invoice \
-H "X-API-Key: $API_KEY"
Отмена счёта
POST/v1/invoice/{paymentId}/cancel
Отменяет ожидающий счёт (статус RemotePaymentCreated). Уже оплаченные — см. возврат.
curl -X POST https://pay.proverkacheka.kz/api/v1/invoice/14918505280/cancel \
-H "X-API-Key: $API_KEY"
{ "cancelled": true, "paymentId": "14918505280", "status": "RemotePaymentCanceled" }
Возврат
POST/v1/invoice/{paymentId}/refund
Возвращает деньги по оплаченному счёту (Processed).
Поддерживается полный и частичный возврат. Если amount опущен —
возвращается весь остаток AvailableReturnAmount.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
amount optional | number > 0 | Сумма возврата в тенге. Опустите для полного возврата. |
# Частичный возврат
curl -X POST https://pay.proverkacheka.kz/api/v1/invoice/14918505280/refund \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 1200}'
{
"paymentId": "14918505280",
"refundedAmount": 1200.0,
"isFull": false,
"remainingRefundable": 3000.0,
"refundsTotal": 1
}
GET/v1/invoice/{paymentId}/refunds
История возвратов по счёту.
Вебхуки
Подпишитесь на события платежей — сервис будет POST'ить на ваш URL JSON-пейлоад каждый раз, когда меняется финальный статус. Это рекомендуемый способ интеграции вместо поллинга.
События
| Event | Когда срабатывает |
|---|---|
payment.success | Клиент оплатил счёт |
payment.failed | Клиент отказался или мерчант отменил |
payment.expired | Истёк срок ожидания оплаты |
payment.refunded | Произведён возврат (полный или частичный) |
* | Подписка на все события сразу |
POST/v1/webhooks
curl -X POST https://pay.proverkacheka.kz/api/v1/webhooks \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/kaspi/webhook",
"events": ["payment.success", "payment.refunded"],
"secret": "my-shared-secret-min-8-chars"
}'
{ "id": 7, "url": "https://example.com/...", "events": ["payment.success","payment.refunded"], "has_secret": true, "is_active": true }
GET/v1/webhooks · DELETE/v1/webhooks/{id}
Просмотр и удаление подписок.
Формат пейлоада
POST https://example.com/kaspi/webhook
Content-Type: application/json
X-Webhook-Event: payment.success
X-Webhook-Attempt: 1
X-Webhook-Signature: sha256=<hex-hmac>
User-Agent: kaspipayinvoice-webhooks/1.0
{
"event": "payment.success",
"paymentId": "14918505280",
"type": "invoice",
"status": "Processed",
"amount": 4200.0,
"clientMobile": "87019009393",
"receiptUrl": "https://receipt.kaspi.kz/...",
"extras": {},
"timestamp": 1747049280
}
Проверка подписи
Заголовок X-Webhook-Signature = sha256= +
HMAC-SHA256 от сырого тела запроса, ключ — ваш secret.
Считайте подпись на своей стороне и сравнивайте константно (hmac.compare_digest).
import hmac, hashlib
def verify(body_bytes: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body_bytes, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header)
2xx или таймаут
сервис повторит доставку с экспоненциальным backoff (несколько попыток в течение суток).
Возвращайте 2xx только после того, как успешно приняли событие.
Ошибки
| HTTP | Когда |
|---|---|
401 | Отсутствует или невалиден X-API-Key. |
400 | Неподдерживаемое событие вебхука, попытка возврата суммы больше AvailableReturnAmount, отмена уже завершённого счёта, небезопасный URL вебхука. |
404 | Вебхук не найден. |
412 | kaspi_session_required — сессия Kaspi отсутствует или была сброшена (например, вы залогинились в приложении Kaspi Pay на телефоне). Заново пройдите SMS-флоу. |
422 | Pydantic-валидация тела запроса (например, пустой items, price ≤ 0). |
502 | bad_gateway — Kaspi вернул ошибку. detail содержит {"kaspi": "...", "code": N}. |
500 | Внутренняя ошибка сервиса — администраторы уже получили алерт. |
Частые причины
- «kaspi_session_required» — вы или ваш сотрудник вошли в Kaspi Pay на смартфоне, и Kaspi выгнал нашу сессию. Зайдите в бот →
/login→ пройдите SMS заново. - Номер телефона неверен (
400 invalid_phone) — сервис принимает 10 или 11 цифр (с 8 или 7 в начале, можно с пробелами/скобками/плюсом). Если получили эту ошибку — в строке скорее всего меньше 10 цифр или есть лишние. - Клиент не получил push — у клиента не установлен Kaspi.kz или отключены уведомления. Сумма всё равно зачислится после оплаты вручную в приложении.
Пример интеграции (Python)
import os, requests
API = "https://pay.proverkacheka.kz/api"
KEY = os.environ["KASPI_API_KEY"]
H = {"X-API-Key": KEY, "Content-Type": "application/json"}
# 1. Выставить счёт
r = requests.post(f"{API}/v1/invoice/create", headers=H, json={
"phoneNumber": "87019009393",
"comment": "Заказ #42",
"items": [
{"name": "Капучино", "price": 1200, "count": 2},
{"name": "Чизкейк", "price": 1800, "count": 1},
],
})
r.raise_for_status()
payment_id = r.json()["paymentId"]
print("Счёт создан:", payment_id)
# 2. (Опционально) проверить статус — но лучше подписаться на вебхук
status = requests.get(f"{API}/v1/invoice/{payment_id}", headers=H).json()
print(status["status"])
# 3. Подписаться на вебхук один раз при старте бота/CRM
requests.post(f"{API}/v1/webhooks", headers=H, json={
"url": "https://my-bot.example.com/kaspi/webhook",
"events": ["payment.success", "payment.failed", "payment.expired", "payment.refunded"],
"secret": "long-random-shared-secret",
})
Пример приёма вебхука (Flask)
from flask import Flask, request, abort
import hmac, hashlib, os
SECRET = os.environ["KASPI_WEBHOOK_SECRET"].encode()
app = Flask(__name__)
@app.post("/kaspi/webhook")
def webhook():
body = request.get_data()
sig = request.headers.get("X-Webhook-Signature", "")
expected = "sha256=" + hmac.new(SECRET, body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
abort(401)
event = request.json
if event["event"] == "payment.success":
notify_customer(event["paymentId"], event["amount"])
return "", 200
Лимиты и особенности
| Параметр | Значение |
|---|---|
| Срок действия неоплаченного счёта | ~24 часа (контролируется Kaspi) |
| Позиций в корзине | 1–50 |
| Формат номера клиента | 10/11 цифр, любой казахстанский формат (нормализуется в 8XXXXXXXXXX) |
| Минимальная сумма позиции | > 0 ₸ |
| Активных счетов одновременно | без жёсткого лимита (поллим все) |
| Webhook retry | экспоненциальный backoff, до суток |
| Алгоритм подписи webhook | HMAC-SHA256 над сырым телом |
Краткая справка по эндпоинтам
| Метод | Путь | Описание |
|---|---|---|
| GET | /v1/auth/me | Информация о ключе и привязанной сессии Kaspi |
| POST | /v1/invoice/create | Создать счёт |
| GET | /v1/invoice/{id} | Статус счёта |
| GET | /v1/invoice | Активные счета |
| POST | /v1/invoice/{id}/cancel | Отменить ожидающий счёт |
| POST | /v1/invoice/{id}/refund | Возврат оплаченного счёта |
| GET | /v1/invoice/{id}/refunds | История возвратов |
| POST | /v1/webhooks | Подписаться на события |
| GET | /v1/webhooks | Список подписок |
| DELETE | /v1/webhooks/{id} | Удалить подписку |