Аутентификация
Каждый запрос к API подписывается секретным ключом сервиса. Ключ одновременно определяет сервис, к которому относятся данные, и режим — тестовый или боевой.
API-ключи
Ключи создаются в кабинете: Сервисы → сервис → вкладка API-ключи. Полный ключ показывается один раз, при создании, — в кабинете потом видны только его начало и последние символы.
| Префикс | Режим | Что происходит |
|---|---|---|
sk_test_ | Тестовый | Платежи не уходят в Kaspi, оплату можно симулировать. См. Тестовый режим. |
sk_live_ | Боевой | Реальные платежи через кассира Kaspi, привязанного к сервису. Создавать боевые ключи могут только администраторы. |
Формат ключа: префикс и 32 символа из латинских букв и цифр — sk_(live|test)_[0-9A-Za-z]{32}. Тестовые и боевые данные полностью разделены: тестовый ключ не видит боевые платежи и наоборот. Ключи одного сервиса не дают доступа к платежам другого — для чужого платежа API вернёт 404.
Передача ключа
Передавайте ключ в заголовке Authorization по схеме Bearer. Если ваш HTTP-клиент или прокси использует Authorization для чего-то своего, подойдёт заголовок X-API-Key. Все запросы — только по HTTPS.
curl https://pay.sezgir.com/api/v1/me \
-H "Authorization: Bearer $SEZGIR_API_KEY"Authorization: Bearer.Проверка ключа
Запрос GET /me ничего не меняет и подходит для проверки конфигурации при запуске сервиса: он возвращает режим ключа, сервис, к которому ключ относится, и кассира Kaspi, назначенного сервису.
{
"object": "api_key",
"livemode": true,
"project": {
"id": "prj_7HcTq2LwZ9mRk4VbN1sXe8Dy",
"name": "Интернет-магазин",
"icon": "🛍️"
},
"kaspi_cashier": {
"name": "Основная касса",
"organization": "ТОО «Пример»",
"status": "active"
}
}Перед боевым запуском убедитесь, что kaspi_cashier не null и его status равен active: иначе создание боевых платежей вернёт 503 provider_unavailable. Другие значения статуса — needs_reauth (сессия кассира истекла, его нужно переподключить в разделе «Kaspi») и disconnected.
Ошибки аутентификации
| HTTP | type | Когда |
|---|---|---|
| 401 | authentication_error | Ключ не передан |
| 401 | authentication_error | Строка не похожа на ключ (неверный формат — например, лишние пробелы или обрезанный ключ) |
| 401 | authentication_error | Ключ не найден или отозван |
| 403 | permission_error | Сервис, которому принадлежит ключ, перенесён в архив |
{
"error": {
"type": "authentication_error",
"message": "API-ключ недействителен или отозван"
}
}Хранение и ротация
- Храните ключ в переменных окружения или менеджере секретов, а не в репозитории.
- Используйте ключ только на сервере. Сайт, мобильное приложение и бот обращаются к вашему backend, а тот — к Sezgir Pay.
- Заведите отдельный ключ на каждое окружение и приложение — так проще отозвать один, не трогая остальные.
- Ключи, созданные сотрудником, отзываются автоматически, когда его отключают в разделе Команда. Для продакшена создавайте ключи от имени администратора, который не уйдёт вместе с подрядчиком.
Как заменить ключ без простоя
Создайте новый ключ, разверните его во всех местах, где используется старый, убедитесь по времени последнего использования в кабинете, что старый ключ больше не используется, и отзовите его. Отзыв действует сразу: следующий запрос со старым ключом получит 401.
Лимиты запросов
На каждый ключ действует лимит 300 запросов в минуту. При превышении API отвечает 429 с типом ошибки rate_limited. Ответы содержат заголовки x-ratelimit-limit, x-ratelimit-remaining и x-ratelimit-reset, а ответ 429 — ещё и retry-after с числом секунд до сброса окна.
{
"error": {
"type": "rate_limited",
"message": "Слишком много запросов, попробуйте позже"
}
}Лимит рассчитан с запасом на обычную работу. Если вы в него упираетесь, скорее всего, вы опрашиваете статус платежей в цикле — подпишитесь на вебхуки и используйте GET /events для сверки.