# API отвечает 403 — не хватает прав

> 403 значит, что ключ распознан, но на это действие прав нет. Причин пять: не хватает scope, неактивный тариф, чужая организация, привязка ключа к кассиру, действие только для песочницы.

## Коротко

Если пришёл `403`, ваш ключ распознан — это хорошая новость. Дело уже не в ключе, а в **правах**. Читайте поле `error` в ответе: оно принимает одно из пяти значений, и решение у каждого своё. `insufficient_scope` — добавить право ключу. `tariff_inactive` — оплатить тариф. `forbidden` — ресурс не принадлежит вашей организации. `not_sandbox` — действие доступно только в песочнице. `account_blocked` — написать в поддержку.

Никогда не пишите код, ориентируясь только на HTTP-статус. `403` слишком общий, решение — в поле `error`.

## Пять ошибок, пять решений

| `error` | Что произошло | Что делать |
|---|---|---|
| `insufficient_scope` | Ключу не выдано право на это действие | Добавьте нужный scope в кабинете |
| `tariff_inactive` | Тариф неактивен или пробный период закончился | Кабинет → Тариф |
| `forbidden` | Ресурс не виден вашей организации или вашему ключу | Проверьте, к одной ли организации относятся ключ и счёт |
| `not_sandbox` | Действие работает только в песочнице | Например, `simulate` в боевом режиме недоступен |
| `account_blocked` | Аккаунт заблокирован | Напишите в [поддержку](https://qut.kz/app) |

## Если не хватает scope

Scope — метка права, ограничивающая то, что ключ может делать. Их шесть:

| Scope | Что открывает |
|---|---|
| `invoices:read` | Чтение списка счетов и статуса одного счёта |
| `invoices:write` | Создание и отмена счетов |
| `refunds:write` | Возвраты |
| `subscriptions:manage` | Управление подписками |
| `webhooks:manage` | Добавление и изменение адресов вебхуков |
| `partner:manage` | Партнёрские методы |

Самый частый случай: ключ выдан только на чтение, а код пытается создать счёт. Или при возврате не хватает `refunds:write` — это право намеренно вынесено отдельно, возврат самое опасное действие.

Как добавить: [кабинет](https://qut.kz/app) → Интеграции → открыть ключ и отметить нужное право. Создавать новый ключ не нужно, старый продолжает работать.

**Не выдавайте прав больше, чем нужно.** Сайту магазина хватает `invoices:read` и `invoices:write`. Если ключ утечёт, ущерб ограничится этими правами.

## Если тариф неактивен

`tariff_inactive` приходит в двух случаях: пробный период закончился и тариф не выбран, либо тариф не оплачен. Пробный период начинается **с первого боевого счёта**, а не со дня регистрации, — поэтому довод «я же только вчера зарегистрировался» здесь не работает, отсчёт идёт от первого live-счёта.

В песочнице этой ошибки не бывает: с ключом `qp_test_` работа продолжается, даже если тариф неактивен. Поэтому если в песочнице всё работало, а в боевом режиме пришёл 403, проверять надо в первую очередь именно это.

## forbidden: ресурс вам не виден

`forbidden` означает, что запрошенный счёт существует, но он не ваш. Так бывает в трёх случаях.

**1. Ключ от другой организации.** Если в аккаунте несколько организаций, у каждой свои ключи. Запрос счёта одной организации ключом другой даёт ровно эту ошибку. К какой организации относится ключ, видно в кабинете.

**2. Ключ привязан к конкретному кассиру.** Боевые счета привязанного ключа идут только через этого кассира. Счёт, созданный другим кассиром, такому ключу не виден. Чаще в этом случае приходит `invoice_not_found` (404), иногда `forbidden`. О работе с несколькими кассирами: [Можно ли подключить несколько кассиров](/kb/ru/two-cashiers).

**3. Идентификатор взят из другой среды.** Запросить `id` счёта из песочницы боевым ключом — частая путаница, особенно сразу после перехода с тестов.

Разделить просто: вызовите тем же ключом `GET /api/v1/invoices`. Пришёл список — ключ рабочий, дело в конкретном счёте. Посмотрите, есть ли в этом списке счёт, который вы ищете.

## not_sandbox

Некоторые методы существуют только в песочнице. Самый частый — симуляция оплаты:

```bash
# Работает только в песочнице
curl -X POST https://api.qut.kz/api/v1/invoices/INV_ID/simulate \
  -H "X-API-Key: qp_test_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"status":"paid"}'
```

Отправьте это боевым ключом — получите `not_sandbox`. Это защита: счёт, по которому реальные деньги не двигались, нельзя пометить оплаченным.

Если ваши автотесты случайно пошли с боевым ключом, они упрутся именно в эту ошибку. Убедитесь, что в тестовом окружении стоит ключ `qp_test_`.

## Несовпадение организации

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

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

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

1. Прочитайте поле `error` в ответе — ориентируйтесь на него, а не на HTTP-код
2. `insufficient_scope` — добавьте право ключу в кабинете
3. `tariff_inactive` — откройте раздел «Тариф»
4. `forbidden` — запросите `GET /api/v1/invoices` и посмотрите, какие счета видит ключ
5. Список пуст — ключ от другой организации или привязан к другому кассиру
6. Всё выглядит верно: [Проблема у вас или у Kaspi](/kb/ru/is-it-us-or-kaspi)

Если не распознаётся сам ключ, придёт не 403, а 401: [API отвечает 401](/kb/ru/api-401).

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

**Нужно ли менять ключ после добавления scope?** Нет. Право вступает в силу сразу, старый ключ продолжает работать.

**Имеет ли смысл повторять запрос при 403?** Нет. Пока права не изменились, ответ не изменится.

**Можно ли отвязать ключ от кассира?** Да, привязку можно снять в кабинете. Но пока к кассиру привязан ключ, удалить самого кассира нельзя — сначала снимите привязку.

**Заработает ли сразу после оплаты тарифа?** Да, как только тариф становится активным, `tariff_inactive` исчезает.

**Почему приходит `account_blocked`?** Это редкий случай, и самостоятельно его не решить. Напишите в поддержку: WhatsApp +7 778 881 3333 или Telegram @qutpaybot.
