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

Счета массово падают — что делать

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

Коротко

Если счета падают не по одному, а пачками, первым делом остановите отправку. Причина чаще всего в частоте: через одного кассира за короткое время ушло слишком много запросов. Kaspi может ограничить частоту запросов кассира, а мы не переотправляем упавший счёт сами — повтор это задача вашего кода. Значит, нужно остановить цикл, посмотреть на код ошибки и переотправить по очереди.

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

Сначала остановитесь

Порядок действий при массовом падении:

  1. Остановите процесс отправки. Cron, очередь, скрипт — что бы это ни было.
  2. Соберите поле error у последних 50 ошибок. Одинаковые они или разные — от этого зависит решение.
  3. Отправьте вручную один счёт. Прошёл — дело в частоте. Упал — причина в другом.
  4. Выставьте счёт вручную из кабинета. Получилось — привязка Kaspi жива.

В экстренном случае, например если точно известно, что код ушёл в цикл, самый надёжный стоп-кран — удалить этот API-ключ в кабинете. После удаления ключа не создаётся ни один счёт. Новый ключ сделаете позже.

Разбор по кодам ошибок

errorЧто означаетЧто делать
rate_limited, request_rate_limitedПревышена частота запросовПрочитайте заголовок Retry-After и выждите указанное время
too_many_attemptsСлишком частые повторы одного действияПодождите минуту
tariff_daily_burstСработала суточная защитаЭто не бизнес-лимит. Проверьте, нет ли цикла в коде
tariff_limit_reachedИсчерпан месячный лимит счетов по тарифуПовысьте тариф или дождитесь нового месяца
invoice_create_failedKaspi не принял счётМожно повторить с задержкой
kaspi_session_expiredПривязка кассира оборваласьПереподключите кассира
insufficient_scope, tariff_inactiveПрава или тарифAPI отвечает 403
unauthorizedКлюч не распознанAPI отвечает 401

Если код у всех один и тот же — причина одна, и чинится она легко. Если коды смешанные — чаще всего дело в частоте: система отбивает запросы в разных местах.

Не путайте tariff_daily_burst и tariff_limit_reached. Первое — суточная защита, обычно следствие цикла в коде. Второе — месячный лимит вашего тарифа, то есть настоящий бизнес-показатель.

Автоматических повторов нет

Это важно понимать точно: если запрос на создание счёта упал, мы не отправляем его заново сами. Так сделано намеренно — повторив без вашего ведома, мы рискуем отправить покупателю два счёта.

Повторы должны быть на вашей стороне и по таким правилам:

const res = await fetch('https://api.qut.kz/api/v1/invoices', {
  method: 'POST',
  headers: {
    'X-API-Key': key,
    'Content-Type': 'application/json',
    'Idempotency-Key': `order-${orderId}`,
  },
  body: JSON.stringify({ amount, description, externalOrderId: String(orderId) }),
});

В качестве Idempotency-Key берите собственный номер заказа — тогда повтор безопасен и счёт не раздваивается.

Отправляйте по очереди

Отправлять сто счетов за секунду незачем. Кассир — всего лишь одна роль в Kaspi, и частота его запросов тоже ограничена.

Схема, которая работает на практике:

async function sendQueue(orders) {
  const failed = [];
  for (const order of orders) {
    try {
      await createInvoice(order);
    } catch (e) {
      failed.push({ order, error: e.code });
      if (e.code === 'rate_limited' || e.code === 'tariff_daily_burst') {
        await sleep(60_000); // минута паузы, потом продолжаем
      }
    }
    await sleep(300); // небольшая пауза между счетами
  }
  return failed;
}

Три главных принципа:

Если в одном запросе действительно нужно несколько счетов, вместо отдельных вызовов используйте POST /api/v1/invoices/bulk: от 1 до 100 счетов за запрос, каждый проверяется отдельно, и в ответе видно, какие прошли, а какие упали.

Режим накопления

В системах с постоянным большим потоком самая надёжная схема — накапливать и отправлять постепенно:

  1. Каждое событие, требующее счёта, кладите не сразу в API, а в свою очередь
  2. Один рабочий процесс забирает из очереди и отправляет по очереди
  3. Упавшее остаётся в очереди и переотправляется с задержкой
  4. Если и после трёх попыток не прошло, уходит уведомление человеку

Такая схема сглаживает пики: даже если покупатели сделают сто заказов разом, в API пойдёт ровный поток. И главное — если система упадёт, заказы не потеряются, а останутся в очереди.

Чтобы не повторялось

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

Создадутся ли упавшие счета позже сами? Нет. Переотправка — ваша задача.

Упёрся в суточную защиту, как её снять? Она отпускает сама со временем. Но сначала найдите причину: чаще всего в коде есть цикл.

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

Если подключить несколько кассиров, станет быстрее? Нагрузка распределится, но это не основное решение. Сначала приведите в порядок логику отправки.

Как понять, что дело не во мне, а в Kaspi? Есть двухминутная диагностика: Проблема у вас или у Kaspi.

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

API отвечает 403 — не хватает прав403 значит, что ключ распознан, но на это действие прав нет. Причин пять: не хватает scope, неактивный тариф, чужая организация, привязка ключа к кассиру, действие только для песочницы.Проблема у вас или у Kaspi — диагностика за две минутыТри вопроса показывают, на чьей стороне сбой: в вашей интеграции, в привязке Kaspi или в самом сервисе. К каждому ответу — конкретное действие и список того, что собрать для поддержки.API отвечает 401 — ключ не принимается401 unauthorized означает, что в запросе нет действующего API-ключа. Причины, порядок проверки и рабочий пример curl. Чаще всего виноват заголовок или префикс Bearer.

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

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