# API кілттер — жасау, сақтау, ауыстыру

> qp_live_ және qp_test_ кілттерінің айырмашылығы, кілтті кабинетте жасау, қайда сақтау керек және қайда мүлдем сақтамау керек, әр интеграцияға бөлек кілт, үзіліссіз ауыстыру реті және жою салдары.

## Қысқаша

API кілт — сұраудың `X-API-Key` тақырыбында жүретін құпия жол. Ол API алдында сіздің ұйымыңызды танытады.

```http
POST /api/v1/invoices
X-API-Key: qp_live_a1b2c3d4…
```

Екі түрі бар: **`qp_live_…`** нақты ақшамен жұмыс істейді, **`qp_test_…`** sandbox-та жүреді. Кілт кабинетте жасалады және **бір-ақ рет көрсетіледі** — сол сәтте көшіріп алмасаңыз, қайта көру мүмкін емес, жаңасын жасауға тура келеді.

Ең басты ереже: кілт **тек серверде** тұруы керек.

## Кілт түрлері

| Префикс | Режим | Не болады |
|---|---|---|
| `qp_test_` | Sandbox | Kaspi шақырылмайды, нақты ақша жүрмейді, төлемді өзіңіз симуляциялайсыз |
| `qp_live_` | Нақты | Нақты Kaspi QR, нақты ақша, Kaspi кассирі керек |

Кілттер режимдер арасында араласпайды: sandbox кілтімен live счётты көре алмайсыз және керісінше. Режимді шатастыру — «менде бәрі жұмыс істеді, продакшенде істемей қалды» дегеннің ең жиі себебі: [Sandbox пен нақты режимнің айырмашылығы](/kb/sandbox-vs-live).

Кілттің пішімі бұзылса `invalid_api_key`, кілт жарамсыз немесе өшірілген болса `unauthorized` келеді: [API 401 қайтарады](/kb/api-401).

## Жасау

Кабинет → **Интеграциялар** → API кілттері → кілт жасау. Жасаған кезде үш нәрсені шешесіз:

| Не | Түсініктеме |
|---|---|
| Атауы | Өзіңіз үшін: «Сайт», «Telegram бот», «1С». Кейін қайсысы не істеп жүргенін осыдан тапсыз |
| Құқықтар (scopes) | Тек қажеттісін қосыңыз: [Құқықтар (scopes)](/kb/scopes) |
| Кассир | Қаласаңыз, кілтті нақты бір кассирге байлайсыз |

Кілт экранда **бір рет** көрсетіледі. Сол жерде көшіріп алып, бірден серверіңіздің құпия қоймасына немесе `.env` файлына салыңыз. Кейін кабинеттен кілттің тек атауы мен соңғы белгілері көрінеді.

## Қайда сақтау керек

| Орын | Бола ма |
|---|---|
| Сервердегі `.env` файлы | Иә |
| Хостингтің немесе CI-дің құпия айнымалылары | Иә |
| Vault сияқты құпия қоймасы | Иә |
| Браузерде орындалатын JavaScript | **Жоқ** |
| Мобильді қосымшаның ішінде (APK/IPA) | **Жоқ** |
| Жария репозиторий, git тарихы | **Жоқ** |
| Скриншот, чат, тапсырма трекері | **Жоқ** |
| Тікелей код ішінде жазылған жол | **Жоқ** |

Себебі қарапайым: браузерге де, қосымшаға да түскен кілтті кез келген адам шығарып ала алады. Мобильді қосымшада реті былай болуы керек: **қосымша → өз серверіңіз → Qut Pay → Kaspi**.

`.env` файлын `.gitignore` тізіміне қосуды ұмытпаңыз, ал кодта `process.env.QUTPAY_API_KEY` арқылы оқыңыз:

```js
// дұрыс
const KEY = process.env.QUTPAY_API_KEY;

// дұрыс емес — кілт кодпен бірге репозиторийге түседі
const KEY = 'qp_live_a1b2c3d4e5f6';
```

Кілт сыртқа шығып кеткен болса, бірінші әрекет — оны **сол сәтте жою**, содан кейін жаңасын жасау.

## Әр интеграцияға бөлек кілт

Барлық жүйеге бір кілт беру — ыңғайлы көрінгенмен, қате жол. Әр интеграцияға бөлек кілт жасаңыз:

| Артықшылығы | Не береді |
|---|---|
| Көріну | Журналда қай счётты қайсысы жасағаны көрінеді |
| Оқшаулау | Біреуі сыртқа шықса, тек соны жоясыз, қалғаны істей береді |
| Ең аз құқық | Ботқа тек `invoices:write`, есеп жүйесіне тек `invoices:read` |
| Есеп | Нүктелер немесе жобалар бойынша бөлек есеп |

Мысал бөлу:

```
Сайт            → invoices:write, invoices:read
Telegram бот    → invoices:write, invoices:read
Есеп жүйесі     → invoices:read
Қайтару панелі  → invoices:read, refunds:write
```

## Кассирге байлау

Кілтті нақты бір Kaspi кассиріне байлауға болады. Сонда:

- сол кілтпен жасалған live счёттар **тек сол кассир арқылы** жүреді;
- кілт басқа кассирдің счёттарын мүлдем көрмейді — оларға `invoice_not_found` қайтады;
- webhook адресін де сол кілтке байласаңыз, әр жоба өз оқиғаларын ғана алады.

Бір ұйымда бірнеше нүкте немесе бірнеше жоба болса, бұл — бөлудің ең таза жолы: [Бір ұйымға бірнеше кассир](/kb/two-cashiers).

Байланысы бар кассирді жою мүмкін емес: алдымен кілтті басқа кассирге ауыстыру керек, әйтпесе `connection_has_keys` қатесі келеді.

Sandbox счёттары кассирге тіркелмейді — олар ұйымның ортақ тест деректері.

## Кілтті үзіліссіз ауыстыру

Кілтті мезгіл-мезгіл ауыстырып тұрған дұрыс: әзірлеуші жұмыстан кеткенде, кілт бөгде жерге көрінгенде немесе жай ғана жоспар бойынша.

Қызметті тоқтатпай ауыстыру реті:

1. **Жаңа кілт жасаңыз.** Ескісін әлі жоймаңыз — екеуі қатар жұмыс істей береді.
2. **Жаңа кілтке сол құқықтарды және сол кассирді** беріңіз.
3. **Серверде айнымалыны ауыстырып**, қосымшаны қайта іске қосыңыз.
4. **Тексеріңіз:** бір sandbox счёты немесе бір шағын live счёт жасап көріңіз.
5. Бірнеше сағат бақылаңыз — ескі кілтті қолданатын ұмыт қалған жер бар ма.
6. **Ескі кілтті жойыңыз.**

Асығыс жағдайда (кілт сыртқа шықты) реті керісінше: алдымен ескісін жойып, сосын жаңасын қоясыз. Бірнеше минут үзіліс болады, бірақ бөтен адамның сіздің атыңыздан счёт жасауынан қауіпсіз.

## Жою

Кілтті жою — **сол сәттен бастап** күшіне енеді. Кідіріс жоқ, «жұмсақ өшіру» жоқ.

| Не болады | Түсініктеме |
|---|---|
| Сұраулар | Сол кілтпен келген барлық сұрау `unauthorized` (401) алады |
| Бұрынғы счёттар | Жойылмайды, кабинетте көрінеді, төлене береді |
| Webhook | Бұрынғы счёттар бойынша оқиғалар келе береді |
| Жазылымдар | Кестесі бұзылмайды, олар кассирге байланған |

Яғни жоғалатыны — тек қолжетімділік. Абайсызда жойып алсаңыз, қалпына келтіру мүмкін емес: жаңасын жасап, интеграцияларды жаңартасыз: [API кілтті жойып алдым](/kb/deleted-key).

## Қателерге қатысы

| Код | HTTP | Себебі |
|---|---|---|
| `unauthorized` | 401 | Кілт жіберілмеген, жарамсыз немесе жойылған |
| `invalid_api_key` | 422 | Кілттің пішімі дұрыс емес |
| `insufficient_scope` | 403 | Кілтте бұл әрекетке құқық жоқ |
| `forbidden` | 403 | Ресурс басқа ұйымға тиесілі |
| `invoice_not_found` | 404 | Кілт байланған кассирдің счёты емес |

## Жиі қойылатын сұрақтар

**Кілтті қайта көруге бола ма?** Жоқ. Ол бір рет қана көрсетіледі. Жоғалтсаңыз — жаңасын жасайсыз.

**Бір ұйымда неше кілт болады?** Бірнешеу. Әр интеграцияға бөлек жасауға ештеңе кедергі емес.

**Кілттің мерзімі бітеді ме?** Өздігінен бітпейді. Оны сіз жоясыз немесе ауыстырасыз.

**Sandbox кілтін продакшенде қолдансам не болады?** Счёттар жасалады, бірақ Kaspi-ге кетпейді — клиент ешқашан төлей алмайды. Бұл «төлем келмей жатыр» деген шағымның ең жиі себебі.

**Кілтті әзірлеушіге беруге бола ма?** Оған бөлек кілт жасап беріңіз, ең аз құқықпен. Жұмыс біткенде сол кілтті ғана жоясыз, қалған интеграцияларға тиіспейсіз.
