# Права доступа (scopes) — что может ключ

> Полная таблица шести scope: invoices:read, invoices:write, refunds:write, subscriptions:manage, webhooks:manage, partner:manage. Какие методы открывает каждый, принцип минимальных прав и разбор ошибки insufficient_scope.

## Коротко

Scope — это право API-ключа. При создании ключа вы выбираете, какие действия ему разрешены, и больше он ничего сделать не сможет. При вызове метода без нужного права придёт **`insufficient_scope`** (HTTP 403).

Всего есть шесть scope. Главный принцип простой: **каждому ключу выдавайте только необходимое**. Сайту, например, достаточно `invoices:write` и `invoices:read` — ни возвраты, ни подписки, ни управление вебхуками ему не нужны.

## Шесть прав

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

## Какое право открывает какой метод

| Метод | Нужное право |
|---|---|
| `GET /api/v1/invoices` | `invoices:read` |
| `GET /api/v1/invoices/{id}` | `invoices:read` |
| `POST /api/v1/invoices` | `invoices:write` |
| `POST /api/v1/invoices/bulk` | `invoices:write` |
| `POST /api/v1/invoices/{id}/cancel` | `invoices:write` |
| `POST /api/v1/invoices/{id}/simulate` | `invoices:write` (только песочница) |
| `POST /api/v1/invoices/{id}/refund` | `refunds:write` |
| `GET /api/v1/subscriptions` | `subscriptions:manage` |
| `POST /api/v1/subscriptions` | `subscriptions:manage` |
| `PATCH /api/v1/subscriptions/{id}` | `subscriptions:manage` |
| `POST /api/v1/subscriptions/{id}/pause` \| `/resume` \| `/cancel` \| `/run` | `subscriptions:manage` |
| Управление адресами вебхуков | `webhooks:manage` |
| Партнёрские методы | `partner:manage` |
| `GET /api/v1/status` | Права не нужны |

Обратите внимание: **возврат не входит в `invoices:write`**. Это отдельное право `refunds:write`. Причина очевидна: выставить счёт и вернуть деньги — действия совершенно разного уровня риска.

## Принцип минимальных прав

Не выдавать ключу лишнего — самая дешёвая и самая эффективная мера безопасности. Если ключ утечёт, посторонний сможет действовать только в пределах выданных прав.

Той части сайта, которая принимает заказы, хватает двух прав:

```
invoices:write   — создать счёт по заказу
invoices:read    — проверить, прошла ли оплата
```

Конкретные примеры:

| Интеграция | Достаточные права |
|---|---|
| Интернет-магазин, сайт | `invoices:write`, `invoices:read` |
| Telegram-бот | `invoices:write`, `invoices:read` |
| Система отчётности или аналитики | `invoices:read` |
| Панель оператора поддержки | `invoices:read`, `refunds:write` |
| Платформа с подписками | `subscriptions:manage`, `invoices:read` |
| Скрипт мониторинга или CI | ничего (`/status` открыт) |
| Партнёрская платформа | `partner:manage` и остальное по необходимости |

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

## Ошибка insufficient_scope

```json
{
  "error": "insufficient_scope",
  "message": "У ключа недостаточно прав для этого действия"
}
```

HTTP-статус — **403**. Эта ошибка не означает «ключ недействителен»: ключ верный, просто у него нет права на запрошенное действие.

У 403 есть и другие причины, не путайте их:

| Код | Что случилось |
|---|---|
| `insufficient_scope` | У ключа нет нужного scope |
| `forbidden` | Ресурс принадлежит другой организации |
| `tariff_inactive` | Тариф неактивен или закончился пробный период |
| `account_blocked` | Аккаунт заблокирован |
| `not_sandbox` | Действие доступно только в песочнице |

А `unauthorized` (401) означает, что недействителен сам ключ — это совсем другая история. Порядок разбора: [API отвечает 403](/kb/ru/api-403).

## Как добавить право ключу

Кабинет → **Интеграции** → API-ключи → откройте нужный ключ и измените права.

Важная деталь: **менять ключ ради изменения прав не нужно**. Сам ключ остаётся прежним, изменение вступает в силу сразу — ни переменную на сервере, ни код править не приходится.

Когда начинаете использовать новый метод, порядок обычный:

1. Выпишите, какие методы вызывает ваш код.
2. Найдите в таблице выше нужное право для каждого.
3. Добавьте ключу только их.
4. Проверьте в песочнице.

В обратную сторону так же: перестали использовать метод — уберите его право.

## Права и привязка к кассиру — это разные вещи

Их часто путают:

| | Scope | Привязка к кассиру |
|---|---|---|
| Что ограничивает | **Какое действие** можно выполнить | **Какие счета** видны |
| Код ошибки | `insufficient_scope` (403) | `invoice_not_found` (404) |
| Пример | Не может сделать возврат | Не видит счёт другого кассира |

То есть, если у ключа есть `refunds:write`, но счёт принадлежит другому кассиру, возврат всё равно не пройдёт — только ошибка будет другая. Подробнее: [API-ключи](/kb/ru/api-keys).

## Чек-лист проверки

Перед выходом в прод пройдитесь по своим ключам:

- [ ] У каждой интеграции свой ключ
- [ ] У каждого ключа только нужные права
- [ ] `refunds:write` стоит действительно только там, где нужен
- [ ] `partner:manage` есть только у партнёрской платформы
- [ ] Ни у одного ключа не включено «всё сразу, чтобы не думать»
- [ ] Старые неиспользуемые ключи удалены

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

**Можно ли просто включить все права?** Технически работать будет, но это многократно увеличивает ущерб от утечки ключа. Принцип минимальных прав — работа на одну минуту.

**Если убрать право, старые счета пропадут?** Нет. Scope влияет только на будущие запросы.

**Разве `invoices:write` не покрывает возврат?** Не покрывает. Для возврата нужен отдельный `refunds:write`: [API возвратов](/kb/ru/refunds-api).

**Сколько прав нужно для подписок?** Одно — `subscriptions:manage`. Для чтения выставленных подписками счетов пригодится ещё `invoices:read`: [API подписок](/kb/ru/subscriptions-api).

**Действуют ли права в песочнице?** Да, точно так же. Поэтому набор прав удобно обкатать сначала в песочнице.
