Документация

1pay API

Принимайте платежи через Kaspi Pay по REST API. Все запросы используют JSON, авторизуются Bearer-ключом и возвращают нормализованную модель платежа — единую для счетов на телефон, платёжных ссылок и QR.

Базовый URL

https://pay.1app.kz

Нет ключа? Зарегистрируйтесь, подключите устройство и создайте API-ключ в дашборде.

Начало

Авторизация

Каждый запрос к /v1/* должен содержать заголовок Authorization с вашим API-ключом вида 1pay_live_…. Ключ привязан к устройству и показывается один раз при создании.

Authorization
Authorization: Bearer 1pay_live_xxxxxxxxxxxx
Храните ключ только на сервере. Не используйте его в браузере или мобильном клиенте.
POST/v1/payments

Создать счёт на телефон

Выставляет счёт в Kaspi на указанный номер. Покупатель подтверждает оплату в приложении Kaspi. Тип платежа — invoice.

ПолеТипОписание
amountобяз.numberСумма в тенге (KZT).
payer_phoneобяз.stringТелефон плательщика, формат +7XXXXXXXXXX.
commentstringНазначение платежа, видно покупателю.
merchant_order_idstringВаш идентификатор заказа. Обеспечивает идемпотентность — повтор вернёт 409 DUPLICATE.
metadataobjectПроизвольные данные, вернутся в вебхуке.

Запрос

POST /v1/payments
curl -X POST https://pay.1app.kz/v1/payments \
  -H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1500,
    "payer_phone": "+77011234567",
    "comment": "Заказ #1042",
    "merchant_order_id": "order_1042"
  }'

Ответ · 201 Created

JSON
{
  "id": "pay_3kQ7v2",
  "status": "PENDING",
  "type": "invoice",
  "amount": 1500,
  "currency": "KZT",
  "payer_phone": "+77011234567",
  "comment": "Заказ #1042",
  "merchant_order_id": "order_1042",
  "payment_link": null,
  "receipt_url": null,
  "created_at": "2026-06-02T09:14:00Z",
  "updated_at": "2026-06-02T09:14:00Z"
}
ПолеТипОписание
amountобяз.numberСумма в тенге (KZT).
commentstringНазначение платежа.
merchant_order_idstringВаш идентификатор заказа (идемпотентность).
metadataobjectПроизвольные данные.

Запрос

POST /v1/payments/link
curl -X POST https://pay.1app.kz/v1/payments/link \
  -H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4990,
    "comment": "Подписка Pro",
    "merchant_order_id": "sub_771"
  }'

Ответ · 201 Created

JSON
{
  "id": "pay_8Lm2qX",
  "status": "PENDING",
  "type": "link",
  "amount": 4990,
  "currency": "KZT",
  "payer_phone": null,
  "comment": "Подписка Pro",
  "merchant_order_id": "sub_771",
  "payment_link": "https://pay.kaspi.kz/pay/abc123",
  "receipt_url": null,
  "created_at": "2026-06-02T09:20:00Z",
  "updated_at": "2026-06-02T09:20:00Z"
}
GET/v1/payments/:id

Получить статус платежа

Возвращает текущее состояние платежа из базы 1pay. Статус обновляется поллером каждые 3 секунды.

Запрос

GET /v1/payments/:id
curl -X GET https://pay.1app.kz/v1/payments/pay_3kQ7v2 \
  -H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"

Ответ · 200 OK

JSON
{
  "id": "pay_3kQ7v2",
  "status": "COMPLETED",
  "type": "invoice",
  "amount": 1500,
  "currency": "KZT",
  "payer_phone": "+77011234567",
  "comment": "Заказ #1042",
  "merchant_order_id": "order_1042",
  "payment_link": null,
  "receipt_url": "https://kaspi.kz/receipt/...",
  "created_at": "2026-06-02T09:14:00Z",
  "updated_at": "2026-06-02T09:15:12Z"
}
POST/v1/payments/:id/cancel

Отменить платёж

Отменяет платёж в статусе PENDING. Уже оплаченные платежи отменить нельзя — используйте возврат.

Запрос

POST /v1/payments/:id/cancel
curl -X POST https://pay.1app.kz/v1/payments/pay_3kQ7v2/cancel \
  -H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"

Ответ · 200 OK

JSON
{
  "id": "pay_3kQ7v2",
  "status": "CANCELLED",
  "type": "invoice",
  "amount": 1500,
  "currency": "KZT",
  "payer_phone": "+77011234567",
  "merchant_order_id": "order_1042",
  "created_at": "2026-06-02T09:14:00Z",
  "updated_at": "2026-06-02T09:16:40Z"
}
POST/v1/refunds

Сделать возврат

Возвращает средства по проведённому платежу. Поддерживается полный и частичный возврат. Платёж переходит в статус REFUNDED.

ПолеТипОписание
payment_idобяз.stringID платежа 1pay (pay_...).
amountобяз.numberСумма возврата в тенге, не больше суммы платежа.

Запрос

POST /v1/refunds
curl -X POST https://pay.1app.kz/v1/refunds \
  -H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_id": "pay_3kQ7v2",
    "amount": 1500
  }'

Ответ · 200 OK

JSON
{
  "id": "pay_3kQ7v2",
  "status": "REFUNDED",
  "type": "invoice",
  "amount": 1500,
  "currency": "KZT",
  "payer_phone": "+77011234567",
  "merchant_order_id": "order_1042",
  "created_at": "2026-06-02T09:14:00Z",
  "updated_at": "2026-06-02T10:02:00Z"
}

Справочники

Коды ошибок

Ошибки возвращаются с соответствующим HTTP-статусом и полем code в теле ответа.

HTTPКодОписание
400VALIDATION_ERRORНекорректное тело запроса или параметры.
401UNAUTHORIZEDОтсутствует или недействителен API-ключ.
402SESSION_EXPIREDСессия устройства истекла — переавторизуйте устройство.
404NOT_FOUNDПлатёж или ресурс не найден.
409DUPLICATEmerchant_order_id уже использован.
422KASPI_ERRORKaspi отклонил операцию.
500INTERNAL_ERRORВнутренняя ошибка сервиса.

Справочники

Вебхуки

1pay отправляет POST-запрос на ваш URL при изменении статуса платежа. Тело — JSON с конвертом события и нормализованным платежом в поле data. Настройте вебхуки в дашборде.

payment.completed

Платёж успешно проведён (статус COMPLETED).

payment.failed

Платёж отклонён или произошла ошибка (FAILED).

payment.cancelled

Платёж отменён мерчантом или плательщиком (CANCELLED).

payment.expired

Истёк срок действия счёта или QR (EXPIRED).

payment.refunded

Выполнен возврат средств (REFUNDED).

payment.refund_failed

Возврат не удалось выполнить.

Пример payload

POST на ваш endpoint
{
  "id": "wh_9aB3cD",
  "event": "payment.completed",
  "created_at": "2026-06-02T09:15:12Z",
  "data": {
    "id": "pay_3kQ7v2",
    "status": "COMPLETED",
    "type": "invoice",
    "amount": 1500,
    "currency": "KZT",
    "payer_phone": "+77011234567",
    "comment": "Заказ #1042",
    "merchant_order_id": "order_1042",
    "payment_link": null,
    "receipt_url": "https://kaspi.kz/receipt/...",
    "created_at": "2026-06-02T09:14:00Z",
    "updated_at": "2026-06-02T09:15:12Z"
  }
}

Проверка подписи и доставка

verify.js
// Заголовок каждого вебхука:
//   X-Webhook-Signature: sha256=<hmac>
// Проверка подписи (Node.js):

import crypto from 'crypto';

function verify(rawBody, signatureHeader, secret) {
  const expected =
    'sha256=' + crypto.createHmac('sha256', secret)
      .update(rawBody)
      .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expected),
  );
}

// Ретраи доставки: 5с → 30с, до 3 попыток. Таймаут 10с.
// Отвечайте 2xx как можно быстрее, обработку делайте асинхронно.

Справочники

Маппинг статусов Kaspi → 1pay

Поллер опрашивает Kaspi каждые 3 секунды и приводит внутренние статусы к нормализованной модели.

QR / платёжные ссылки
ProcessedCOMPLETED
CancelledByUser, NotConfirmedByUser, Rejected, Error, Insufficient*, Iris*FAILED
QrTokenDiscarded, ExpiredEXPIRED
QrTokenCreated, WaitPENDING
Счета (invoice)
ProcessedCOMPLETED
RemotePaymentCanceled, RemotePaymentRejectedFAILED
ExpiredEXPIRED
RemotePaymentCreatedPENDING