Коротко
Каждая ошибка приходит в виде { "error": "код", "message": "пояснение" }. HTTP-статус говорит о типе: 4xx — что-то не так в запросе, нужно исправить и повторить; 429 — лимит, нужно подождать; 5xx — временный сбой у нас или на стороне Kaspi, повтор допустим.
Пишите интеграцию всегда по коду error, а не по тексту message: текст может измениться, код — нет.
Авторизация и ключ
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
unauthorized | 401 | Ключ не передан или недействителен | Проверьте заголовок X-API-Key |
invalid_api_key | 422 | Неверный формат ключа | Ключ должен быть qp_live_… или qp_test_… |
insufficient_scope | 403 | У ключа нет прав на это действие | Добавьте нужный scope ключу в кабинете |
forbidden | 403 | Ресурс принадлежит не вашей организации | Проверьте, что ключ и счёт из одной организации |
account_blocked | 403 | Аккаунт заблокирован | Напишите в поддержку |
organization_inactive | 410 | Организация в архиве или удалена | Напишите в поддержку |
not_sandbox | 403 | Действие доступно только в песочнице | Например, симуляция оплаты не работает в боевом режиме |
forbidden и invoice_not_found связаны и с привязкой ключа к кассиру: привязанный ключ не видит счета другого кассира. Подробно: Привязка API-ключа к кассиру.
Привязка Kaspi
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
kaspi_session_expired | 409 | Привязка кассира оборвалась | Переподключите: Привязка оборвалась |
kaspi_session_not_configured | 409 | Кассир ещё не подключён | Кабинет → Kaspi → Добавить кассира |
connection_not_active | 400 | Подключение есть, но неактивно | Переподключите этого кассира |
connection_not_found | 404 | Указанный connection_id не найден | Проверьте идентификатор |
no_provider | 409 | В организации нет ни одного рабочего кассира | Подключите кассира или перейдите в песочницу |
connection_has_keys | 409 | К кассиру привязан API-ключ, удалить нельзя | Сначала переведите ключ на другого кассира |
cashier_number_rejected | 502 | Kaspi не показал экран ввода кода | Номер не подходит: Три условия |
Создание счёта
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
invalid_amount | 422 | Сумма отсутствует или не число | Передайте положительное число |
amount_too_small | 422 | Сумма меньше минимума | Увеличьте сумму |
amount_too_large | 422 | Сумма больше максимума | Уменьшите или разбейте на части |
amount_must_be_whole_tenge | 422 | Переданы тиыны | Передавайте целые тенге, Kaspi не принимает копейки |
invalid_phone | 422 | Неверный формат телефона | Формат 7XXXXXXXXXX, 11 цифр |
invalid_kind | 422 | Неизвестный тип счёта | qr или phone |
invoice_create_failed | 502 | Kaspi не принял счёт | Повторите; если повторяется — в поддержку |
invoice_not_found | 404 | Счёта нет или он вам не виден | Проверьте идентификатор и кассира у ключа |
Статус счёта, отмена, возврат
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
invoice_not_open | 409 | Счёт не открыт: оплачен, истёк или отменён | Прочитайте статус через GET /invoices/{id} |
invoice_changed | 409 | Статус счёта изменился, пока вы работали | Перечитайте статус и решите заново |
invoice_not_refundable | 409 | Этот счёт вернуть нельзя | Проверьте, оплачен ли он и не вышел ли срок |
invalid_refund_amount | 422 | Неверная сумма возврата | Не должна превышать оплаченную |
refund_failed | 502 | Kaspi не выполнил возврат | Проверьте, хватает ли средств на счёте Kaspi |
refund_unknown | 502 | Kaspi не ответил, результат неизвестен | Не повторяйте, прочитайте статус счёта |
refund_pending_unknown | 409 | Результат прошлого возврата ещё неизвестен | Подождите, не отправляйте второй раз |
refund_state_conflict | 409 | Состояние возврата отличается от ожидаемого | Перечитайте статус счёта |
cancel_failed | 502 | Kaspi не отменил счёт | Повторите или дождитесь, пока счёт истечёт сам |
Если при возврате пришёл refund_unknown или refund_pending_unknown, не повторяйте запрос — можно вернуть деньги дважды. Прочитайте статус счёта и узнайте результат оттуда.
Тариф и лимиты
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
tariff_limit_reached | 429 | Месячный лимит счетов исчерпан | Поднимите тариф или дождитесь нового месяца |
tariff_daily_burst | 429 | Слишком много счетов за сутки | Это не бизнес-лимит, а защита от зациклившейся интеграции. Проверьте код |
tariff_inactive | 403 | Тариф неактивен или пробный период закончился | Кабинет → Тариф |
rate_limited | 429 | Превышена частота запросов | Смотрите заголовок Retry-After и повторите |
request_rate_limited | 429 | Превышена общая частота запросов | Снизьте частоту |
too_many_attempts | 429 | Слишком частые повторы одного действия | Подождите минуту |
tariff_daily_burst и tariff_limit_reached — разные вещи. Первое суточная защита, обычно это цикл в коде. Второе — месячный лимит вашего тарифа. Подробно: Тарифы и лимиты.
Вебхуки
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
invalid_url | 422 | Неверный адрес | Укажите полный адрес |
webhook_url_requires_https | 422 | HTTP-адрес не принимается | Используйте HTTPS |
webhook_url_requires_domain | 422 | IP или адрес без домена | Укажите настоящий домен |
webhook_url_tunnel_forbidden | 422 | Адрес временного туннеля | Используйте постоянный домен |
invalid_events | 422 | Неверный список событий | Сверьтесь со списком поддерживаемых событий |
too_many_endpoints | 422 | Превышено число вебхуков | Удалите ненужные |
endpoint_not_found | 404 | Вебхук не найден | Проверьте идентификатор |
hook_paused | 410 | Форм-хук остановлен | Включите заново в кабинете |
Если вебхук не доходит, причина чаще не в коде ошибки: Вебхук не приходит.
Подписки
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
invalid_interval | 422 | Неверный интервал | day, week или month |
invalid_every | 422 | Неверная кратность | Целое положительное число |
invalid_retry | 422 | Неверная лестница повторов | Не больше 5 значений, каждое положительное |
invalid_misfire | 422 | Неверная политика пропуска | run_once или skip |
invalid_max_runs | 422 | Неверное максимальное число запусков | Целое положительное число |
subscription_closed | 409 | Подписка завершена или остановлена | Создайте новую |
subscription_not_found | 404 | Подписка не найдена | Проверьте идентификатор |
Ссылки на оплату
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
slug_taken | 409 | Такой адрес уже занят | Выберите другое имя |
link_invalid | 410 | Ссылка недействительна | Создайте новую |
link_paused | 410 | Ссылка остановлена | Включите заново в кабинете |
too_many_links | 409 | Превышено число ссылок | Удалите ненужные |
Вход в кабинет
| Код | HTTP | Что случилось | Что делать |
|---|---|---|---|
invalid_code | 400 | Неверный код | Введите заново |
challenge_expired | 410 | Срок кода истёк | Запросите новый |
challenge_used | 409 | Код уже использован | Запросите новый |
no_channel | 503 | Нет канала для отправки кода | Напишите в поддержку |
channel_forbidden | 403 | Этот канал вам недоступен | Выберите другой |
Можно ли повторять
| Тип | Повтор |
|---|---|
| 4xx (422, 400, 403, 404, 409) | Нет. Повторять без исправления запроса бессмысленно |
| 429 | Да, но после времени из Retry-After |
| 502, 503 | Да, с растущей паузой (например 1, 2, 4, 8 секунд) |
refund_unknown, refund_pending_unknown | Нет. Сначала прочитайте статус счёта |
Чтобы повтор при создании счёта не создал дубль, передавайте idempotencyKey: при повторной отправке с тем же ключом вернётся прежний счёт, а не новый.
Вопросы и ответы
Текст ошибки приходит на русском? Поле message приходит на казахском. Пишите интеграцию по коду error.
Пришёл код, которого нет в списке. Смотрите полную спецификацию на api.qut.kz/docs или напишите в поддержку.
Какую ошибку можно показать покупателю? Никакую напрямую. Покажите клиенту «оплата не прошла, попробуйте ещё раз», а технический текст запишите в свой журнал.