Надёжность
Ошибки
API использует стандартные HTTP-коды: 2xx — успех, 4xx — проблема в запросе, 5xx — проблема на стороне Sezgir Pay или Kaspi. Тело ошибки всегда имеет один и тот же формат.
Формат ошибки
Ответ · 400 Bad Request
{
"error": {
"type": "invalid_request",
"code": "validation_failed",
"message": "amount: сумма в целых тенге",
"param": "amount"
}
}error.typestring- Категория ошибки — см. типы. Есть всегда.
error.codestring- Машиночитаемый код для ошибок, которые стоит обрабатывать отдельно, — см. коды. Может отсутствовать.
error.messagestring- Описание для человека на русском языке. Подходит для логов и для показа сотрудникам, но текст может меняться — не разбирайте его в коде.
error.paramstring- Параметр, из-за которого возникла ошибка, например
amount,phoneилиmetadata.order_id. Может отсутствовать.
Поля code и param не передаются, если к ошибке они не относятся, — проверяйте их наличие.
HTTP-коды
| Код | Значение |
|---|---|
200 OK | Запрос выполнен |
201 Created | Платёж или возврат создан |
202 Accepted | Возврат принят, но результат пока неизвестен — см. requires_action |
400 Bad Request | Неверные параметры запроса или некорректный JSON |
401 Unauthorized | Ключ не передан, неверного формата или отозван |
403 Forbidden | Сервис ключа в архиве |
404 Not Found | Объект не найден в этом сервисе и режиме |
409 Conflict | Операция невозможна в текущем состоянии объекта или конфликт Idempotency-Key |
413 Payload Too Large | Тело запроса больше 256 КБ |
415 Unsupported Media Type | Тело передано не как application/json |
429 Too Many Requests | Превышен лимит 300 запросов в минуту |
500 Internal Server Error | Внутренняя ошибка Sezgir Pay; с Idempotency-Key — код outcome_unknown |
502 Bad Gateway | Kaspi отклонил операцию |
503 Service Unavailable | Kaspi недоступен или кассир требует повторного подключения |
Типы ошибок
| type | HTTP | Описание |
|---|---|---|
invalid_request | 400 | Параметры не прошли проверку, тело не является JSON, неверный Content-Type |
authentication_error | 401 | Проблема с API-ключом — см. Аутентификация |
permission_error | 403 | Действие запрещено: например, сервис перенесён в архив |
not_found | 404 | Платёж, возврат или событие не найдены |
conflict | 409 | Состояние объекта не позволяет выполнить операцию; конфликты Idempotency-Key |
rate_limited | 429 | Слишком много запросов |
provider_error | 502, 503 | Ошибка на стороне Kaspi или связи с ним |
api_error | 500 | Непредвиденная ошибка Sezgir Pay |
Коды ошибок
| code | HTTP | Когда возникает | Что делать |
|---|---|---|---|
validation_failed | 400 | Параметр не прошёл проверку: тип, длина, диапазон. Имя — в param | Исправить запрос |
unknown_parameter | 400 | Передан параметр, которого нет в API, — обычно опечатка (externalId вместо external_id). Имя — в param | Исправить имя поля |
invalid_json | 400 | Тело запроса не является корректным JSON | Проверить сериализацию тела |
payload_too_large | 413 | Тело запроса больше 256 КБ | Сократить metadata или описание |
unsupported_media_type | 415 | Тело передано не как JSON. Пустое тело с Content-Type: application/json допустимо | Отправлять JSON с Content-Type: application/json |
payment_not_pending | 409 | Отмена платежа, который уже не в статусе pending (в том числе счёт, оплаченный за миг до отмены) | Запросить актуальный статус платежа |
payment_busy | 409 | Отмена ссылки в момент, когда покупатель получает новый QR | Повторить через несколько секунд |
payment_not_refundable | 409 | Возврат по неоплаченному платежу | Проверить статус платежа |
already_refunded | 409 | Платёж уже возвращён полностью, или остаток занят возвратом в обработке | Проверить возвраты платежа |
idempotency_mismatch | 409 | Idempotency-Key уже использован с другим телом или путём | Использовать новый ключ для новой операции |
idempotency_in_progress | 409 | Запрос с этим ключом ещё выполняется | Повторить через несколько секунд |
provider_unavailable | 503 | Kaspi не отвечает, сервису не назначен кассир Kaspi или кассир требует повторного подключения | Повторить позже с тем же Idempotency-Key |
kaspi_<число> | 502 | Kaspi отказал в операции и вернул свой код ошибки | Посмотреть message, решить вручную |
already_exists | 409 | Объект с такими данными уже существует | Не повторять |
outcome_unknown | 500 | Запрос с Idempotency-Key упал на нашей стороне, и операция могла успеть выполниться. Повтор с тем же ключом вернёт этот же ответ | Проверить объект через GET (например, GET /payments?external_id=…) и только потом повторять с новым ключом |
route_not_found | 404 | Такого метода или пути в API нет | Проверить URL и метод |
Некоторые ошибки приходят без code — их достаточно различать по type и param. Например, счёт без телефона:
Ответ · 400 Bad Request
{
"error": {
"type": "invalid_request",
"message": "Для счёта нужен номер телефона покупателя в Kaspi (+7 7XX XXX XX XX)",
"param": "phone"
}
}Ошибки Kaspi
Ошибки с типом provider_error различаются по смыслу, и обрабатывать их нужно по-разному:
- 503, provider_unavailable — запрос не дошёл до Kaspi или Kaspi не ответил. Платёж не был выставлен покупателю, возврат не выполнен. Повторите позже с тем же Idempotency-Key. Если ошибка не проходит, проверьте в кабинете, что сервису назначен кассир (Сервис → Настройки) и что он подключён (раздел Kaspi).
- 502 — Kaspi получил запрос и отказал. Текст причины от Kaspi — в
message, код — вcodeвидаkaspi_-7, если Kaspi его вернул. Повтор того же запроса, скорее всего, приведёт к тому же результату. - Неоднозначный исход возврата (таймаут, оборванный ответ) — это не ошибка, а
202сrequires_action: true: дождитесьrefund.succeededилиrefund.failed(см. Возвраты).
{
"error": {
"type": "provider_error",
"code": "provider_unavailable",
"message": "Сервису не назначен кассир Kaspi — выберите кассира в настройках сервиса"
}
}Не всякая проблема с Kaspi — ошибка
Когда исход денежной операции неизвестен, API не возвращает ошибку, а сообщает об этом явно: счёт создаётся с флагом requires_review, а возврат возвращается с кодом
202 и requires_action.Что повторять
| Ответ | Повторять? | Как |
|---|---|---|
| Сетевая ошибка или таймаут | Да | С тем же Idempotency-Key — дубликата не будет |
429 | Да | Через retry-after секунд |
409 idempotency_in_progress | Да | Через несколько секунд, с тем же ключом |
500, 503 | Да | С экспоненциальной задержкой и тем же ключом |
500 outcome_unknown | Нет | Сначала проверить объект через GET; повтор с тем же ключом вернёт тот же ответ |
502 | Нет | Разобраться с причиной из message |
400, 401, 403, 404, другие 409 | Нет | Исправить запрос или состояние |
Готовая функция повтора — в разделе Идемпотентность.