API · v1
Документация API
Tolemflow проверяет фискальные чеки Kaspi Pay и отвечает боту, можно ли выдавать товар. Один запрос — одна проверка.
Начало работы
Зарегистрируйтесь в кабинете: сразу после регистрации вы получите API-ключ и 50 бесплатных проверок в месяц.
| Базовый адрес | https://tolemflow.kz/api |
|---|---|
| Авторизация | Заголовок X-API-Key: krv_… |
| Формат | JSON в UTF-8; для файлов — multipart/form-data |
Проверка чека
Покупатель присылает боту PDF-чек из приложения Kaspi, бот передаёт файл в Tolemflow. Только PDF, до 10 МБ. Файлы удаляются сразу после проверки.
Запрос — multipart/form-data: поле file и необязательные поля ниже (metadata — строкой JSON). Поля передавайте до файла.
| Поле | Тип | Описание |
|---|---|---|
file | файл | PDF-чек из приложения Kaspi |
userId | строка | ID покупателя в боте (Telegram ID). Нужен для истории и защиты от повторов |
purchaseId | строка | Ваш номер заказа |
expectedAmount | число | Сумма, которую вы ждёте, в тенге. Если в чеке другая — чек отклоняется |
expectedSeller | строка | ИИН/БИН (12 цифр) или название продавца. Если не передать, используется ИИН/БИН из настроек проекта |
metadata | объект | Любые ваши данные, вернутся в вебхуке |
# pip install aiohttp import aiohttp async def check_receipt(pdf: bytes, user_id: int, order_id: str, price: int) -> dict: form = aiohttp.FormData() form.add_field("userId", str(user_id)) form.add_field("purchaseId", order_id) form.add_field("expectedAmount", str(price)) form.add_field("file", pdf, filename="receipt.pdf", content_type="application/pdf") async with aiohttp.ClientSession() as s: async with s.post("https://tolemflow.kz/api/receipts/validate", headers={"X-API-Key": TOLEMFLOW_KEY}, data=form) as r: return await r.json()
const form = new FormData(); form.append("userId", String(userId)); form.append("purchaseId", orderId); form.append("expectedAmount", String(price)); form.append("file", new Blob([pdf], { type: "application/pdf" }), "receipt.pdf"); const res = await fetch("https://tolemflow.kz/api/receipts/validate", { method: "POST", headers: { "X-API-Key": TOLEMFLOW_KEY }, body: form, }); const result = await res.json(); // result.success === true → выдавайте товар
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
Если бот не умеет отправлять файлы
Конструкторы ботов обычно дают публичную ссылку на присланный файл. Отправьте на тот же адрес JSON, где вместо file — поле fileUrl со ссылкой на PDF: Tolemflow сам скачает файл.
curl -X POST https://tolemflow.kz/api/receipts/validate \ -H "X-API-Key: $TOLEMFLOW_KEY" -H "Content-Type: application/json" -d '{"fileUrl":"<ссылка на PDF-файл>","userId":"518204771","expectedAmount":500}'
Ответы и ошибки
Чек принят — выдавайте товар
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": "❌ Неверная сумма платежа. Ожидалось: 500 ₸, получено: 300 ₸" }
Текст в message можно показать покупателю: он объясняет, что не так с чеком.
| Код | Что случилось | Что делать |
|---|---|---|
200 | Проверка выполнена | Смотрите success и isDuplicate |
400 | Чек не прошёл проверку, запрос некорректен или прислан не PDF | Покажите покупателю message |
401 | Нет ключа или ключ неверный | Проверьте заголовок X-API-Key |
402 | Закончились проверки бесплатного тарифа (error: "limit_reached") | Выберите тариф в кабинете |
429 | Слишком много запросов в минуту | Повторите позже |
5xx | Временная ошибка проверки | Повторите через несколько секунд |
Конструкторы ботов
Для Salebot и других конструкторов, которые умеют отправлять HTTP-запросы с JSON:
- Ответ всегда с кодом 200. Добавьте к адресу
?always200=1: при отказе ответ придёт с кодом 200,success: false, причиной вmessageи исходным кодом вhttpStatus. Многие конструкторы не читают тело ответа с кодом 4xx. - PDF по ссылке. Если конструктор даёт ссылку на присланный файл, передайте её в
fileUrl— Tolemflow сам скачает PDF. - Числа строками.
expectedAmount,userIdиpurchaseIdможно передавать строками:"24900". - Повтор по тому же заказу. Если тот же чек пришёл повторно с теми же
purchaseIdиuserIdв течение 15 минут, проверка не спишется, а в ответе будутsuccess: falseиreplayed: true. Товар второй раз выдавать не нужно: оплата уже засчитана первым ответом. Если первый ответ до вас не дошёл из-за обрыва связи,replayed: trueозначает, что чек принят.
Пошаговая инструкция: Salebot.
Другие методы
Проверяет, использовался ли чек, не засчитывая его. Тело: {"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. На бесплатном тарифе после 50 проверок в месяц ответ —402, на платных проверки продолжаются сверх пакета. - Частота. По умолчанию до 100 запросов в минуту на ключ. Нужно больше — напишите нам.
- Проекты. Число проектов зависит от тарифа, у каждого проекта свои ключи.
Как защититься лучше
- Укажите ИИН/БИН продавца в настройках проекта: чек, оплаченный другому продавцу, будет отклонён.
- Передавайте
expectedAmount: чек на меньшую сумму не пройдёт. - Передавайте
userIdиpurchaseId: так проще разбирать спорные случаи в кабинете. - Включите уведомления в Telegram, чтобы узнавать о попытках обмана сразу.