Qut Pay Сайт Кабинет База знаний Инструкции Документация API ҚАЗРУС
ГлавнаяБаза знаний → Решение проблем

API отвечает 401 — ключ не принимается

Обновлено: 2026-09-14 · Версия в Markdown

Коротко

401 и {"error":"unauthorized"} означают ровно одно: в запросе не пришёл действующий API-ключ. К счёту, сумме, кассиру и тарифу это отношения не имеет — с идеально составленным телом запроса 401 придёт точно так же. Три самые частые причины: заголовок X-API-Key вообще не отправлен, вместо него написан Authorization: Bearer, либо ключ удалён в кабинете. Пять шагов ниже находят причину.

Причина по симптому

Что вы видитеПричинаЧто делать
401 unauthorized на всех эндпоинтахЗаголовка X-API-Key нетДобавьте заголовок
401 с ключом, который вчера работалКлюч удалён или отключён в кабинетеСоздайте новый ключ и обновите интеграцию
401 в коде, но в Postman тот же ключ работаетКод берёт ключ из другой переменной, приходит пустая строкаПроверьте, загружен ли .env и перезапущен ли сервис
422 invalid_api_keyФормат ключа нарушенКлюч должен быть qp_live_… или qp_test_…
401, хотя ключ выглядит правильнымКлюч отправлен с префиксом BearerПередавайте чистый ключ, без префикса

401 и 403 — разные вещи. 401 значит «я не знаю, кто вы». 403 значит «я знаю, кто вы, но прав на это действие нет». Если пришёл 403, смотрите API отвечает 403.

Порядок проверки

1. Сверьте имя заголовка посимвольно. Оно — X-API-Key. Вариант X-Api-Key тоже подойдёт (регистр в HTTP-заголовках не важен), а X_API_KEY, ApiKey и api-key — нет. Некоторые фреймворки не превращают подчёркивание в дефис, поэтому пишите заголовок именно так.

2. Не пишите Bearer. Это самая частая ошибка. Наш API не использует схему Authorization: Bearer …. Ключ передаётся в заголовке X-API-Key, без префикса, в чистом виде.

Верно:    X-API-Key: qp_live_xxxxxxxxxxxxxxxx
Неверно:  Authorization: Bearer qp_live_xxxxxxxxxxxxxxxx
Неверно:  X-API-Key: Bearer qp_live_xxxxxxxxxxxxxxxx

3. Посмотрите на сам ключ. Он начинается с qp_live_ или qp_test_. При копировании в начало или конец часто попадают пробел, перевод строки или кавычка. Обрежьте их в коде:

const key = (process.env.QUTPAY_API_KEY || '').trim();
if (!key.startsWith('qp_')) throw new Error('API-ключ не загружен');

Если такая проверка выполняется при старте сервиса, вы увидите проблему сразу, а не в проде.

4. Убедитесь, что ключ есть в кабинете. Список ключей — кабинет → раздел «Интеграции». Удалённый ключ не восстанавливается: нужно создать новый и обновить интеграцию.

5. Проверьте, ключ какого режима вы используете. qp_test_ — песочница, qp_live_ — боевой режим. Если интеграция работает в одном режиме, а ключ от другого, путаница начинается именно здесь. О разнице режимов: Что такое Qut Pay.

Рабочий пример

Действителен ли сам ключ, выясняется одним запросом:

curl -i https://api.qut.kz/api/v1/invoices \
  -H "X-API-Key: qp_test_ВАШ_КЛЮЧ"

Пришёл 200 — ключ рабочий, дело в том, как ваш код отправляет заголовок. Пришёл 401 — дело в самом ключе.

Создание счёта:

curl -i -X POST https://api.qut.kz/api/v1/invoices \
  -H "X-API-Key: qp_test_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"amount":1000,"description":"Тестовый счёт"}'

Node.js:

const res = await fetch('https://api.qut.kz/api/v1/invoices', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.QUTPAY_API_KEY.trim(),
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ amount: 1000, description: 'Тестовый счёт' }),
});

В PHP с cURL заголовок пишется целой строкой:

curl_setopt($ch, CURLOPT_HTTPHEADER, [
  'X-API-Key: ' . trim(getenv('QUTPAY_API_KEY')),
  'Content-Type: application/json',
]);

Пять типичных промахов

Если всё верно, а 401 остаётся

Ключ новый, заголовок правильный, пробелов нет, а 401 продолжает приходить — проверьте, не на нашей ли стороне дело:

curl -s https://api.qut.kz/api/v1/status

Этот эндпоинт отвечает и без ключа. Если он молчит, причина не в вашем ключе. Как разделить стороны: Проблема у вас или у Kaspi.

Обращаясь в поддержку, приложите первые десять символов ключа (никогда не присылайте ключ целиком), время запроса, имя эндпоинта и полный текст ответа.

Вопросы и ответы

Стоит ли повторять запрос при 401? Нет смысла. Пока запрос не изменился, ответ будет тем же. Цикл повторов только упрётся в суточную защиту.

Если сменить ключ, пропадут ли старые счета? Нет. Счета принадлежат организации, а не ключу. С новым ключом вы увидите всё как раньше.

Что делать, если ключ утёк? Немедленно удалить его в кабинете и создать новый. Удалённым ключом создать счёт уже нельзя.

Может ли один ключ обслуживать несколько серверов? Может. Но удобнее выдать каждой точке свой ключ — тогда видно, кто какой трафик создаёт.

Можно ли создать боевой счёт ключом песочницы? Нет. Ключ qp_test_ работает только в песочнице, реальные деньги при этом не двигаются.

Связанные статьи

API отвечает 403 — не хватает прав403 значит, что ключ распознан, но на это действие прав нет. Причин пять: не хватает scope, неактивный тариф, чужая организация, привязка ключа к кассиру, действие только для песочницы.Проблема у вас или у Kaspi — диагностика за две минутыТри вопроса показывают, на чьей стороне сбой: в вашей интеграции, в привязке Kaspi или в самом сервисе. К каждому ответу — конкретное действие и список того, что собрать для поддержки.Счета массово падают — что делатьЕсли отправить много счетов разом, Kaspi может ограничить частоту запросов кассира. Автоматических повторов нет. Пауза, отправка по очереди и разбор кодов ошибок.Что такое Qut Pay и как он устроенQut Pay — независимый сервис поверх Kaspi Pay: API и кабинет для приёма Kaspi QR через роль «Кассир». Деньги приходят напрямую на ваш счёт в Kaspi и никогда не попадают к нам.

Остались вопросы? WhatsApp +77788813333 · kazprose@gmail.com
Написать можно и из кабинета: Поддержка.

Qut Pay — независимый сервис, не аффилирован с АО «Kaspi Bank». Kaspi и Kaspi Pay — товарные знаки их правообладателя.