Надёжность

Ошибки

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 GatewayKaspi отклонил операцию
503 Service UnavailableKaspi недоступен или кассир требует повторного подключения

Типы ошибок

typeHTTPОписание
invalid_request400Параметры не прошли проверку, тело не является JSON, неверный Content-Type
authentication_error401Проблема с API-ключом — см. Аутентификация
permission_error403Действие запрещено: например, сервис перенесён в архив
not_found404Платёж, возврат или событие не найдены
conflict409Состояние объекта не позволяет выполнить операцию; конфликты Idempotency-Key
rate_limited429Слишком много запросов
provider_error502, 503Ошибка на стороне Kaspi или связи с ним
api_error500Непредвиденная ошибка Sezgir Pay

Коды ошибок

codeHTTPКогда возникаетЧто делать
validation_failed400Параметр не прошёл проверку: тип, длина, диапазон. Имя — в paramИсправить запрос
unknown_parameter400Передан параметр, которого нет в API, — обычно опечатка (externalId вместо external_id). Имя — в paramИсправить имя поля
invalid_json400Тело запроса не является корректным JSONПроверить сериализацию тела
payload_too_large413Тело запроса больше 256 КБСократить metadata или описание
unsupported_media_type415Тело передано не как JSON. Пустое тело с Content-Type: application/json допустимоОтправлять JSON с Content-Type: application/json
payment_not_pending409Отмена платежа, который уже не в статусе pending (в том числе счёт, оплаченный за миг до отмены)Запросить актуальный статус платежа
payment_busy409Отмена ссылки в момент, когда покупатель получает новый QRПовторить через несколько секунд
payment_not_refundable409Возврат по неоплаченному платежуПроверить статус платежа
already_refunded409Платёж уже возвращён полностью, или остаток занят возвратом в обработкеПроверить возвраты платежа
idempotency_mismatch409Idempotency-Key уже использован с другим телом или путёмИспользовать новый ключ для новой операции
idempotency_in_progress409Запрос с этим ключом ещё выполняетсяПовторить через несколько секунд
provider_unavailable503Kaspi не отвечает, сервису не назначен кассир Kaspi или кассир требует повторного подключенияПовторить позже с тем же Idempotency-Key
kaspi_<число>502Kaspi отказал в операции и вернул свой код ошибкиПосмотреть message, решить вручную
already_exists409Объект с такими данными уже существуетНе повторять
outcome_unknown500Запрос с Idempotency-Key упал на нашей стороне, и операция могла успеть выполниться. Повтор с тем же ключом вернёт этот же ответПроверить объект через GET (например, GET /payments?external_id=…) и только потом повторять с новым ключом
route_not_found404Такого метода или пути в 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НетИсправить запрос или состояние

Готовая функция повтора — в разделе Идемпотентность.