API · v1
Документация API
Tolemflow проверяет фискальные чеки Kaspi Pay и отвечает боту, можно ли выдавать товар. Один запрос — одна проверка.
Начало работы
Зарегистрируйтесь в кабинете: сразу после регистрации вы получите API-ключ и 50 бесплатных проверок в месяц.
| Базовый адрес | https://tolemflow.kz/api |
|---|---|
| Авторизация | Заголовок X-API-Key: krv_… |
| Формат | JSON в UTF-8; для файлов — multipart/form-data |
Проверка по ссылке
Основной метод: покупатель присылает ссылку из чека Kaspi (её же содержит QR-код чека).
| Поле | Тип | Описание |
|---|---|---|
receiptUrl | строка, обязательно | Ссылка на чек, например https://receipt.kaspi.kz/web/fiscal?i=… |
userId | строка | ID покупателя в боте (Telegram ID). Нужен для истории и защиты от повторов |
purchaseId | строка | Ваш номер заказа |
expectedAmount | число | Сумма, которую вы ждёте, в тенге. Если в чеке другая — чек отклоняется |
expectedSeller | строка | ИИН/БИН (12 цифр) или название продавца. Если не передать, используется ИИН/БИН из настроек проекта |
metadata | объект | Любые ваши данные, вернутся в вебхуке |
# pip install aiohttp import aiohttp async def check_receipt(receipt_url: str, user_id: int, order_id: str, price: int) -> dict: async with aiohttp.ClientSession() as s: async with s.post( "https://tolemflow.kz/api/receipts/validate-url", headers={"X-API-Key": TOLEMFLOW_KEY}, json={"receiptUrl": receipt_url, "userId": str(user_id), "purchaseId": order_id, "expectedAmount": price}, ) as r: return await r.json()
const res = await fetch("https://tolemflow.kz/api/receipts/validate-url", { method: "POST", headers: { "X-API-Key": TOLEMFLOW_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ receiptUrl, userId: String(userId), purchaseId: orderId, expectedAmount: price }), }); const result = await res.json(); // result.success === true → выдавайте товар
curl -X POST https://tolemflow.kz/api/receipts/validate-url \ -H "X-API-Key: $TOLEMFLOW_KEY" -H "Content-Type: application/json" \ -d '{"receiptUrl":"https://receipt.kaspi.kz/web/fiscal?i=…","userId":"518204771","expectedAmount":500}'
Проверка по файлу
Для PDF или фото чека с QR-кодом: Tolemflow распознаёт QR и проверяет чек так же, как по ссылке. Форматы: PDF, JPG, PNG, до 10 МБ.
Запрос — multipart/form-data: поле file и те же поля, что выше (userId, purchaseId, expectedAmount, expectedSeller; metadata — строкой JSON). Поля передавайте до файла.
curl -X POST https://tolemflow.kz/api/receipts/validate \ -H "X-API-Key: $TOLEMFLOW_KEY" \ -F userId=518204771 -F expectedAmount=500 \ -F file=@receipt.pdf
Файлы удаляются сразу после проверки.
Ответы и ошибки
Чек принят — выдавайте товар
HTTP 200
{
"success": true, "isValid": true, "isDuplicate": false,
"message": "Чек успешно подтвержден",
"receiptId": "5b0c…",
"data": { "sum": 500, "seller": "ИП …", "sellerIIN": "…",
"receiptNumber": "QR17810724392", "dateTime": "2026-09-27 23:35:22" }
}
Чек уже использовали
HTTP 200
{ "success": false, "isDuplicate": true, "message": "…Этот чек уже был использован ранее для оплаты…" }
Чек не прошёл проверку
HTTP 400
{ "success": false, "message": "Сумма в ссылке не совпадает с суммой в чеке" }
Текст в message можно показать покупателю: он объясняет, что не так с чеком.
| Код | Что случилось | Что делать |
|---|---|---|
200 | Проверка выполнена | Смотрите success и isDuplicate |
400 | Чек не прошёл проверку или запрос некорректен | Покажите покупателю message |
401 | Нет ключа или ключ неверный | Проверьте заголовок X-API-Key |
402 | Закончились проверки бесплатного тарифа (error: "limit_reached") | Выберите тариф в кабинете |
429 | Слишком много запросов в минуту | Повторите позже |
5xx | Временная ошибка на нашей стороне или у Kaspi | Повторите через несколько секунд |
Другие методы
Проверяет, использовался ли чек, не засчитывая его. Тело: {"receiptIdentifier": "QR17810724392"} — номер чека. Ответ: {"success": true, "isDuplicate": false}.
Возвращает проверенный чек по receiptId из ответа. Доступны только чеки вашего проекта.
Вебхуки
Укажите адрес в кабинете (Проекты → Вебхук), и Tolemflow будет отправлять результат каждой проверки POST-запросом. Удобно, если чеки проверяет один сервис, а заказы обрабатывает другой.
| Событие | Когда |
|---|---|
receipt.accepted | Чек принят |
receipt.duplicate | Чек уже использовали |
receipt.rejected | Чек не прошёл проверку |
ping | Тест из кабинета |
POST https://your-bot.example.com/tolemflow
X-Tolemflow-Event: receipt.accepted
X-Tolemflow-Delivery: 6f0e…
X-Tolemflow-Timestamp: 1790540000
X-Tolemflow-Signature: sha256=…
{ "id": "6f0e…", "event": "receipt.accepted", "createdAt": "2026-09-28T09:00:00Z", "projectId": "…",
"data": { "receiptId": "…", "status": "accepted", "amount": 500, "seller": "ИП …",
"receiptNumber": "QR…", "userId": "518204771", "purchaseId": "order-1042", "metadata": {} } }
Проверка подписи
Подпись — HMAC-SHA256 от строки timestamp.тело с секретом из кабинета. Проверяйте её и отклоняйте события старше 5 минут.
# Python import hmac, hashlib, time def verify(headers, raw_body: bytes, secret: str) -> bool: ts = headers["X-Tolemflow-Timestamp"] expected = "sha256=" + hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest() fresh = abs(time.time() - int(ts)) < 300 return fresh and hmac.compare_digest(expected, headers.get("X-Tolemflow-Signature", ""))
// Node.js const crypto = require("crypto"); function verify(headers, rawBody, secret) { const ts = headers["x-tolemflow-timestamp"]; const expected = "sha256=" + crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex"); const got = headers["x-tolemflow-signature"] || ""; return Math.abs(Date.now() / 1000 - Number(ts)) < 300 && got.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got)); }
Доставка и повторы
- Ответьте кодом 2xx в течение 10 секунд. Редиректы не выполняются.
- При ошибке отправка повторяется через 1, 5, 30 минут, 2 и 6 часов. Журнал доставок и кнопка повтора — в кабинете.
- Одно событие может прийти дважды: используйте
idилиX-Tolemflow-Delivery, чтобы не обработать его повторно. - Адрес должен начинаться с
https://; внутренние и локальные адреса не принимаются.
Лимиты
- Проверки по тарифу. Проверка — любой запрос к
validateилиvalidate-url. На бесплатном тарифе после 50 проверок в месяц ответ —402, на платных проверки продолжаются сверх пакета. - Частота. По умолчанию до 100 запросов в минуту на ключ. Нужно больше — напишите нам.
- Проекты. Число проектов зависит от тарифа, у каждого проекта свои ключи.
Как защититься лучше
- Укажите ИИН/БИН продавца в настройках проекта: чек, оплаченный другому продавцу, будет отклонён.
- Передавайте
expectedAmount: чек на меньшую сумму не пройдёт. - Передавайте
userIdиpurchaseId: так проще разбирать спорные случаи в кабинете. - Включите уведомления в Telegram, чтобы узнавать о попытках обмана сразу.