API v1

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

REST API для автоматической проверки и валидации чеков Kaspi. Загружайте PDF-чеки, проверяйте подлинность через QR-код и базу Kaspi.

Чеки обрабатываются менее чем за 1 секунду. Скорость обработки зависит от времени ответа платёжной системы. Рекомендуемый timeout для запросов: 10 секунд.

Base URL https://api.proverkacheka.kz
Полная документация для AI / разработчика
Показать содержимое

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

Получите API-ключ и отправьте первый запрос за 2 минуты.

1. Получите API-ключ

Запустите Telegram бот — вы получите 10 бесплатных проверок и API-ключ автоматически.

2. Отправьте чек на проверку

# Отправка чека через URL
curl -X POST https://api.proverkacheka.kz/upload \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "ваш-api-ключ",
    "file": "https://example.com/receipt.pdf",
    "user_id": "123456789",
    "price": 5000,
    "iin": "123456789012"
  }'
Где взять ИИН/БИН

Откройте любой чек Kaspi вашей организации — в строке "ИИН/БИН продавца" указан ваш 12-значный идентификатор. Передайте его в параметре iin. Это надёжнее, чем ip_name, т.к. ИИН уникален.

3. Получите результат

{
  "message": "Чек валиден и добавлен в базу данных.",
  "check_number": "QR13973837513",
  "amount": 1000.50,
  "company_name": "ИП АЛИБЕКОВ",
  "payment_method": "Kaspi Gold"
}

Аутентификация

Все запросы к /upload требуют API-ключ (UUID), который передаётся в теле запроса в поле api_key.

API-ключ привязан к вашему аккаунту с балансом кредитов. Вы можете получить ключ через Telegram бот или запросить у администратора.

Безопасность

Храните API-ключ в секрете. Не передавайте его в URL-параметрах и не размещайте в клиентском коде (JavaScript в браузере). Используйте серверную интеграцию.

Лимиты и ограничения

ОграничениеЗначение
Rate limit100 запросов/мин на API-ключ
Макс. размер файла5 МБ
Макс. размер запроса10 МБ
Формат файлаТолько PDF
Срок действия кредитов30 дней с момента пополнения

Загрузка и проверка чека

POST /upload API Key

Загрузить PDF-чек Kaspi для валидации. Поддерживает отправку файла через URL, base64 или multipart form.

Параметры

ПараметрТипОписание
api_key requiredstringrequiredUUID API-ключ клиента
file requiredstring / filerequiredURL на PDF, base64-строка или бинарный файл (multipart)
user_id requiredstringrequiredИдентификатор пользователя (например, Telegram ID)
pricenumberoptionalМинимальная сумма оплаты в тенге (default: 1000)
ip_name required*stringrequired*Наименование продавца (ИП/ТОО). *Не обязателен, если указан iin
iin recommendedstringrecommendedИИН/БИН продавца (12 цифр). Уникален для каждого продавца, исключает подмену
use_balance recommendedbooleanrecommendedРекомендуется true для большинства интеграций. Аккумулирует частичные оплаты до целевой суммы. Без этого недоплата приводит к полному отказу; с включённым — недоплата уходит на per-user баланс, и можно сказать пользователю, сколько ещё доплатить (default: false — для обратной совместимости)
max_ageintegeroptionalМакс. возраст чека в днях (default: 14)
max_overpaynumberoptionalМакс. допустимая переплата сверх price в тенге. По умолчанию не задано — без этого параметра принимается любая сумма ≥ price
Обратная совместимость

Старые названия параметров (club_price, date_limit, up_limit) по-прежнему принимаются. Новые названия имеют приоритет.

Примеры запроса

# Отправка чека через URL на PDF
curl -X POST https://api.proverkacheka.kz/upload \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "550e8400-e29b-41d4-a716-446655440000",
    "file": "https://example.com/receipt.pdf",
    "user_id": "123456789",
    "price": 5000,
    "ip_name": "ИП АЛИБЕКОВ",
    "iin": "123456789012"
  }'
# Отправка PDF файлом напрямую
curl -X POST https://api.proverkacheka.kz/upload \
  -F "api_key=550e8400-e29b-41d4-a716-446655440000" \
  -F "file=@/path/to/receipt.pdf" \
  -F "user_id=123456789" \
  -F "price=5000" \
  -F "ip_name=ИП АЛИБЕКОВ" \
  -F "iin=123456789012"
# Проверка с валидацией ИИН продавца (ip_name не нужен)
curl -X POST https://api.proverkacheka.kz/upload \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "550e8400-e29b-41d4-a716-446655440000",
    "file": "https://example.com/receipt.pdf",
    "user_id": "123456789",
    "price": 5000,
    "iin": "123456789012"
  }'

Успешный ответ

// 200 OK
{
  "message": "Чек валиден и добавлен в базу данных.",
  "check_number": "QR13973837513",
  "amount": 1000.50,
  "company_name": "ИП АЛИБЕКОВ",
  "payment_method": "Kaspi Gold",
  "balance": null,
  "due": null
}

Ответ при дубликате

// 200 OK — чек уже был обработан ранее
{
  "message": "Чек уже обработан ранее.",
  "check_number": "QR13973837513",
  "amount": 1000.50,
  "company_name": "ИП АЛИБЕКОВ",
  "previous_user_id": "123456789",
  "payment_method": "Kaspi Gold"
}

Ответ в режиме накопления

// 200 OK — use_balance: true, сумма < price
{
  "message": "Баланс пополнен",
  "check_number": "QR13973837513",
  "amount": 500.00,
  "company_name": "ИП АЛИБЕКОВ",
  "balance": 500.00,
  "due": 500.00,
  "payment_method": "Kaspi Gold"
}

Ответ при отклонении (недоплата / переплата)

// 200 OK — сумма чека ниже price (чек не сохранён, можно повторить)
{
  "message": "Сумма чека должна быть не меньше 5000 тенге.",
  "check_number": null,
  "amount": 3500.00,
  "company_name": "ИП АЛИБЕКОВ",
  "payment_method": "Kaspi Gold",
  "balance": null,
  "due": null
}

// 200 OK — сумма превышает price + max_overpay (чек не сохранён, можно повторить)
{
  "message": "Сумма чека превышает допустимый предел.",
  "check_number": null,
  "amount": 8200.00,
  "company_name": "ИП АЛИБЕКОВ",
  "payment_method": "Kaspi Gold",
  "balance": null,
  "due": null
}

Транзиентная ошибка Kaspi (нужен ретрай)

// 200 OK — Kaspi API временно недоступен (HTTP 5xx, таймаут или сетевая ошибка).
// Кредиты не списаны, чек не зарегистрирован — ретрай тем же PDF безопасен.
// Канонический сигнал — поле retry_after (а не текст message).
{
  "message": "Failed to fetch receipt data from Kaspi.",
  "check_number": null,
  "amount": 220.00,
  "company_name": "ИП АЛИБЕКОВ",
  "payment_method": "Kaspi Gold",
  "balance": null,
  "due": null,
  "retry_after": 5
}

Ошибки

КодСообщениеПричина
400Missing API key.Не передан api_key
400Invalid file type. Only PDF files are allowed.Файл не PDF
400Файл слишком большой.Файл > 5 МБ
401Invalid API key.Неверный ключ
402Insufficient credits.Кредиты закончились
408Timeout при скачивании файла.URL не отвечает 10с
413Request too largeЗапрос > 10 МБ
429Rate limit exceeded> 100 запросов/мин
Сообщения валидации

При ошибке валидации чека (неверная сумма, не тот продавец, устаревший чек) API возвращает 200 с описанием в поле message. Проверяйте текст message для определения результата.

GET /health Без аутентификации

Проверка состояния сервиса и доступности базы данных.

curl https://api.proverkacheka.kz/health
// 200 OK
{
  "status": "healthy",
  "service": "proverkacheka-api"
}

Система кредитов

Каждый успешный запрос на проверку чека расходует 1 кредит. Кредиты действительны 30 дней с момента последнего пополнения.

Как это работает

Бесплатный тариф

Новые пользователи получают 10 бесплатных проверок через Telegram бот. Для пополнения кредитов свяжитесь с поддержкой.

Накопление баланса РЕКОМЕНДУЕТСЯ

Режим накопления позволяет принимать частичные оплаты. Включается параметром use_balance: true в запросе /upload.

Когда включать

В большинстве прод-ботов use_balance стоит выставлять в true. Без него любая недоплата (например, 200 ₸ за тариф 500 ₸) превращается в жёсткий отказ; с включённым — вы видите balance и due в ответе и можете попросить пользователя доплатить разницу. Оставлять false имеет смысл только для одноразовой покупки с фиксированной ценой, где частичная оплата бессмысленна.

Логика работы

Пример сценария

// price = 10000

// Чек #1 — 6000 тенге
{ "balance": 6000, "due": 4000 }

// Чек #2 — 4000 тенге, оплата завершена
{ "balance": 10000, "due": 0 }

ИИН/БИН валидация

Самый надёжный способ валидации. Используйте ИИН/БИН вместо имени продавца (ip_name) — это гарантирует точную идентификацию. Имена ИП/ТОО могут совпадать у разных продавцов, и чек другой организации с таким же названием пройдёт проверку по ip_name. ИИН/БИН уникален для каждого продавца, поэтому подмена исключена.

Как использовать

Где найти ваш ИИН/БИН

Откройте любой чек Kaspi вашей организации — в нём будет строка "ИИН/БИН продавца" с 12-значным номером. Это и есть ваш ИИН/БИН, который нужно передать в параметре iin.

Лучшие практики для Telegram-ботов

Рекомендации по обработке платежных чеков в Telegram-ботах, основанные на реальном опыте интеграций.

Состояние ожидания чека

После отправки пользователю ссылки на оплату Kaspi, установите флаг/состояние «ожидание чека» для этого пользователя:

Управление ссылками на оплату

Сохраняйте message_id сообщения со ссылкой на оплату Kaspi:

Обработка PDF вне контекста

Пользователи отправляют PDF на любом экране бота — не игнорируйте их:

Готовый рецепт: ретрай + накопление баланса (Python)

Минимальная обёртка вокруг /upload с правильной обработкой транзиентных ошибок Kaspi и включённым use_balance. Ретрай срабатывает по полю retry_after в ответе — это устойчивее, чем сравнивать строку message.

import asyncio, httpx

async def validate_receipt(pdf_bytes, user_id, price, iin, api_key, notify):
    """
    notify(text): async callback для статус-сообщений между ретраями
                  ("проверяем чек, подождите несколько секунд…")
    Возвращает JSON-ответ /upload (последняя попытка, если все были транзиентными).
    """
    data = {
        "api_key": api_key,
        "user_id": str(user_id),
        "iin": iin,
        "price": str(price),
        "use_balance": "true",  # рекомендуется для большинства интеграций
    }
    files = {"file": ("receipt.pdf", pdf_bytes, "application/pdf")}
    async with httpx.AsyncClient(timeout=15) as client:
        for attempt in range(3):
            r = await client.post(
                "https://api.proverkacheka.kz/upload",
                data=data, files=files,
            )
            body = r.json()
            if "retry_after" not in body:
                return body  # окончательный результат — успех или перманентный отказ
            if attempt < 2:
                await notify("⏳ Проверяем чек, подождите несколько секунд…")
                await asyncio.sleep(body["retry_after"])
        return body  # три транзиентные подряд — отдаём как есть

Коды ошибок

КодОписание
200Успешный запрос (проверяйте message для результата валидации)
400Некорректный запрос — отсутствуют параметры или неверный формат
401Неавторизован — неверный API-ключ
402Недостаточно кредитов
408Таймаут загрузки файла по URL
413Файл или запрос слишком большой
429Превышен лимит запросов (100/мин)
500Внутренняя ошибка сервера

Сообщения валидации (200 OK)

Следующие сообщения возвращаются с кодом 200 и означают проблему с самим чеком, а не с запросом:

messageЗначение
Чек уже обработан ранее.Дубликат — этот чек уже использовался
Чек не принадлежит {ip_name}.Продавец в чеке не совпадает с указанным
Сумма чека не совпадает с данными из Kaspi.Данные в PDF не соответствуют Kaspi API
Сумма чека должна быть не меньше {N} тенге.Сумма ниже price — чек не сохранён, можно повторить с другим price
Сумма чека превышает допустимый предел.Сумма выше price + max_overpay — чек не сохранён, можно повторить с другим max_overpay
Чек слишком старый.Превышен max_age
ИИН/БИН не совпадает.ИИН продавца в чеке не совпадает с указанным
Не удалось извлечь номер чека из PDF.PDF не содержит читаемого чека
Поведение при отклонении

Все отклонённые чеки возвращают поле amount в ответе. В базу данных сохраняются только два результата: успешная проверка («Чек валиден...») и дубликат («Чек уже обработан ранее.»). Все остальные отклонения не сохраняют чек — его можно повторно отправить с исправленными параметрами. max_overpay не имеет значения по умолчанию: без него верхняя граница суммы не ограничена.

Транзиентные ошибки Kaspi (ретрай безопасен)

Фискальное API Kaspi обычно отвечает за 1–3 секунды, но изредка кратковременно «5xx-ит» или таймаутит. На HTTP 5xx (быстрая ошибка — самый частый случай флапа) сервер сам делает один повторный запрос через 1 секунду — большинство таких флапов вы не видите. На медленных ошибках (таймаут, обрыв соединения) сервер не ретраит — там вторая попытка точно так же зависнет. Если и повтор не помог (или это медленная ошибка), /upload возвращает 200 OK с одним из сообщений ниже и дополнительным полем retry_after: 5. Кредиты не списаны, чек не зарегистрирован — тот же PDF можно отправить ещё раз через несколько секунд.

messageКогда возникает
Failed to fetch receipt data from Kaspi.Kaspi API ответил HTTP 5xx
Kaspi API не отвечает. Попробуйте позже.Таймаут запроса к Kaspi (10с)
Нет связи с Kaspi API. Попробуйте позже.Сетевая ошибка до Kaspi
Ошибка при получении данных по QR-ссылке.Иная неожиданная ошибка
Политика ретраев

Не показывайте пользователю эти сообщения как финальную ошибку. Рекомендуется до 3 попыток с интервалом 5 секунд. Канонический сигнал — наличие поля retry_after в ответе (не парсинг строки message). Между попытками покажите статус («проверяем чек, подождите несколько секунд…») — без этого 5-секундная пауза выглядит как зависший бот, и пользователь начинает слать дубли.

Быстрая шпаргалка: что вернулось → что делать

ОтветДействие
«Чек валиден и добавлен в базу данных.»Засчитать оплату
«Баланс пополнен»due > 0)Принять частичную оплату, сказать пользователю, сколько ещё доплатить
Любое сообщение + retry_afterТранзиентная ошибка — подождать 5 сек, ретрай (до 3 раз). Кредиты не списаны
«Чек уже обработан ранее.»Чек уже использован — попросить новый
«ИИН/БИН не совпадает.», «Чек слишком старый.», «Не удалось извлечь номер чека из PDF.», «Сумма чека не совпадает с данными из Kaspi.»Перманентный отказ — показать ошибку пользователю

Встраиваемый виджет BETA

Beta — свяжитесь перед использованием

Встраиваемый виджет находится в стадии бета-тестирования. Перед установкой свяжитесь с @sanzhar в Telegram для поддержки и помощи с интеграцией.

Добавьте проверку чеков на ваш сайт одной строкой HTML. Виджет использует HMAC-подписанные токены — параметры проверки (цена, продавец, срок) зашиты в токен и не могут быть изменены пользователем.

<div data-proverkacheka-widget
     data-api-key="ВАШ_API_KEY"
     data-token="СГЕНЕРИРОВАННЫЙ_ТОКЕН"
     data-user-id="order-123"></div>
<script src="https://api.proverkacheka.kz/widget.js"></script>

Атрибуты

АтрибутОбязателенОписание
data-api-keyДаВаш API ключ
data-tokenДаHMAC-подписанный токен с параметрами проверки
data-user-idНетИдентификатор пользователя/заказа (по умолчанию "widget-user")

Генерация токена

Токен генерируется на вашем сервере с использованием вашего API ключа как секрета HMAC. Формат: base64url(JSON).hmac_sha256_hex

Параметры токена (JSON)

ПолеТипОписание
pricenumberМинимальная сумма чека (тенге)
ip_namestringНазвание продавца
iinstringИИН/БИН продавца (12 цифр)
max_agenumberМаксимальный возраст чека в днях
expnumberUnix timestamp истечения токена

Python

import hmac, hashlib, base64, json, time

def generate_token(params, api_key):
    payload = base64.urlsafe_b64encode(
        json.dumps(params).encode()
    ).rstrip(b'=').decode()
    signature = hmac.new(
        api_key.encode(), payload.encode(), hashlib.sha256
    ).hexdigest()
    return f"{payload}.{signature}"

token = generate_token({
    "price": 5000,
    "iin": "123456789012",
    "max_age": 7,
    "exp": int(time.time()) + 3600  # 1 час
}, "ВАШ_API_KEY")

Node.js

const crypto = require('crypto');

function generateToken(params, apiKey) {
  const payload = Buffer.from(JSON.stringify(params))
    .toString('base64url');
  const signature = crypto
    .createHmac('sha256', apiKey)
    .update(payload)
    .digest('hex');
  return `${payload}.${signature}`;
}

const token = generateToken({
  price: 5000,
  iin: '123456789012',
  max_age: 7,
  exp: Math.floor(Date.now() / 1000) + 3600
}, 'ВАШ_API_KEY');

PHP

function generateToken(array $params, string $apiKey): string {
    $payload = rtrim(strtr(base64_encode(
        json_encode($params)
    ), '+/', '-_'), '=');
    $signature = hash_hmac('sha256', $payload, $apiKey);
    return "{$payload}.{$signature}";
}

$token = generateToken([
    'price' => 5000,
    'iin' => '123456789012',
    'max_age' => 7,
    'exp' => time() + 3600,
], 'ВАШ_API_KEY');

Kommo CRM виджет

Виджет для автоматизации приёма оплаты через Kaspi в Kommo CRM. Проверка чеков, валидация суммы и продавца, автоматическое продвижение сделок по воронке — всё без участия менеджера.

Только индивидуальная установка

Публичный виджет в маркетплейсе Kommo пока недоступен. На данный момент виджет устанавливается приватно — мы настроим интеграцию под ваш аккаунт Kommo.

Возможности

Заказать установку

Для подключения виджета к вашему Kommo аккаунту свяжитесь с нами:

Заказать установку → @sanzhar

Напишите в Telegram — обсудим детали и настроим виджет под ваш аккаунт.