ApiPay.kz API Documentation

Интернет-эквайринг через Kaspi Pay (Phone Payments)

API для приёма платежей по номеру телефона через Kaspi Pay. Без договора с банком, без комиссий.

Быстрый старт

Важно! Перед созданием счетов необходимо верифицировать организацию.
  1. Войдите в личный кабинет baypay.bazarbay.site/login
  2. В приложении Kaspi Business добавьте номер 77056610934 с правами "Кассир"
  3. Верифицируйте организацию: POST /organizations/verify с вашим ИИН/БИН
  4. Дождитесь статуса "verified" (polling каждые 2 сек, таймаут 120 сек)
  5. Создавайте счета: POST /invoices
  6. Настройте webhook в личном кабинете для получения уведомлений об оплате

Базовая конфигурация

ПараметрЗначение
Base URLhttps://bpapi.bazarbay.site/api
АутентификацияHeader X-API-Key: ваш_api_ключ
Rate Limit60 запросов/минуту
Content-Typeapplication/json

Организации

POST /organizations/verify

Запускает процесс верификации. Пользователь должен подтвердить в Kaspi Business в течение 2 минут.

Request

{
  "idn": "123456789012"  // 12 цифр ИИН или БИН
}

Response

{
  "organization": {
    "id": 1,
    "status": "pending"
  },
  "message": "Verification started"
}

GET /organizations/:id/status

Проверка статуса верификации. Опрашивайте каждые 2 секунды до статуса "verified" или таймаута (120 сек).

Response

{
  "organization": {
    "id": 1,
    "idn": "123456789012",
    "status": "pending|verified",
    "time_remaining": 115
  }
}

Счета (Invoices)

POST /invoices

Требует верифицированную организацию!

Request

{
  "amount": 10000,              // Обязательно: 0.01 - 99999999.99
  "phone_number": "87001234567", // Обязательно: формат 8XXXXXXXXXX
  "description": "Оплата заказа #123",  // Опционально, макс 500 символов
  "external_order_id": "order_123",      // Опционально, ваш ID заказа
  "webhook_id": 5                        // Опционально, ID webhook из личного кабинета
}

Response

{
  "id": 42,
  "kaspi_invoice_id": "13234689513",
  "kaspi_qr_token": "abc123...",
  "payment_url": "https://kaspi.kz/pay/...",  // Редирект клиента сюда!
  "amount": "10000.00",
  "status": "pending",
  "created_at": "2025-12-25T10:30:00Z"
}

GET /invoices

Список счетов с пагинацией и фильтрами.

Query параметры

ПараметрТипОписание
pagenumberНомер страницы
per_pagenumberЗаписей на странице (1-100, default: 10)
searchstringПоиск (макс 100 символов)
status[]arrayФильтр по статусам
date_fromdateДата от
date_todateДата до

GET /invoices/:id

Получить счёт по ID.

POST /invoices/:id/cancel

Отменить счёт. Работает только для статуса "pending".

Статусы счетов

СтатусОписаниеМожно отменить
pendingОжидает оплатыДа
paidОплачен клиентомНет
cancelledОтменён вручнуюНет
expiredИстёк срок оплатыНет

Webhooks

Webhooks настраиваются в личном кабинете ApiPay.kz (раздел Настройки → Подключение). При создании webhook вы получите secret (показывается один раз). Используйте его для верификации подписи входящих уведомлений.

Вы можете создать несколько webhooks для разных сервисов и выбирать нужный при создании счёта через параметр webhook_id.

Формат Webhook события

Событие invoice.status_changed отправляется при изменении статуса счёта:

{
  "event": "invoice.status_changed",
  "invoice": {
    "id": 42,
    "external_order_id": "order_123",
    "amount": "15000.00",
    "status": "paid",
    "description": "Оплата заказа",
    "kaspi_invoice_id": "13234689513",
    "client_name": "Иван Иванов",
    "client_phone": "87071234567",
    "paid_at": "2025-12-25T14:35:00Z"
  },
  "timestamp": "2025-12-25T14:35:01Z"
}

Верификация подписи

Заголовок: X-Webhook-Signature: sha256=<HMAC-SHA256>

Node.js

const crypto = require('crypto')

function verifyWebhook(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
}

PHP

function verifyWebhook($payload, $signature, $secret) {
    $expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
    return hash_equals($expected, $signature);
}

Python

import hmac, hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

Примеры кода

JavaScript/Node.js

const response = await fetch('https://bpapi.bazarbay.site/api/invoices', {
  method: 'POST',
  headers: {
    'X-API-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 10000,
    phone_number: '87001234567',
    description: 'Payment for order #123'
  })
})
const data = await response.json()
// Redirect customer to: data.payment_url

Python

import requests

response = requests.post(
    'https://bpapi.bazarbay.site/api/invoices',
    headers={'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json'},
    json={'amount': 10000, 'phone_number': '87001234567'}
)
payment_url = response.json()['payment_url']

PHP

$ch = curl_init('https://bpapi.bazarbay.site/api/invoices');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['amount' => 10000, 'phone_number' => '87001234567']),
    CURLOPT_RETURNTRANSFER => true
]);
$response = json_decode(curl_exec($ch), true);
$payment_url = $response['payment_url'];

cURL

curl -X POST https://bpapi.bazarbay.site/api/invoices \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10000, "phone_number": "87001234567"}'

Коды ошибок

КодОписание
400Bad Request — некорректный запрос
401Unauthorized — неверный или отсутствующий API ключ
404Not Found — ресурс не найден
410Gone — ресурс истёк (например, таймаут верификации)
422Validation Error — ошибка валидации
429Too Many Requests — превышен rate limit
500Server Error — ошибка сервера

Формат ошибки

{
  "message": "Описание ошибки",
  "errors": {
    "field_name": ["детали ошибки"]
  }
}