> Источник: https://apipay.kz/guides/integratsiya-apipay-s-pomoshchyu-ii · Обновлено: 2026-10-26 · apipay.kz
> ApiPay — независимый сервис приёма платежей поверх вашего Kaspi Pay.

# Интеграция с ApiPay с помощью ИИ

**TL;DR.** Дайте своему ИИ-ассистенту любую из машинных ссылок — `https://apipay.kz/llms.txt` или `https://apipay.kz/openapi.json` — и он построит приём платежей Kaspi: base URL `https://api.apipay.kz/api/v1`, авторизация заголовком `X-API-Key`. Помощник, который работает в вашем проекте с терминалом (Claude Code, Codex), сначала попросит подключить MCP на экране «Подключить с ИИ». Отличие ApiPay — **тест-цикл в песочнице из 3 шагов**: агент создаёт тестовый счёт, симулирует его статус через `POST /invoices/{id}/simulate-status` и проверяет результат — статус счёта через `GET /invoices/{id}` или, если подключены уведомления, доставку вебхука через `GET /webhook-logs` — без реального Kaspi и без единого телефонного номера. Для старта вебхук не обязателен: об оплате достаточно узнавать опросом статуса с сервера. Общий лимит — до 200 запросов в минуту на ключ.

## С чего начать и нужен ли MCP?

Песочница открывается сразу после регистрации: анкета и кассир для неё не нужны. Пошаговый плейбук для помощника — [apipay.kz/for-ai](/for-ai). Если ваш ИИ-клиент поддерживает MCP, настройку подключения берите на экране [«Подключить с ИИ»](/setup/ai) в кабинете. MCP — помощник для настройки, а не замена API: счета и возвраты создаёт ваше приложение, и всё, что ниже, работает без MCP. Но помощник, который работает прямо в проекте с терминалом (Claude Code, Codex), без MCP подключение не начнёт: он попросит сначала подключить MCP. Подробнее — [ApiPay и MCP](/guides/podklyuchenie-apipay-mcp).

API-ключ и webhook secret (он есть, только если подключены уведомления) нельзя вставлять в чат. Значения в env-файл кладёт программа ApiPay после того, как вы подтвердите выпуск в кабинете по ссылке помощника ([как это устроено](/guides/podklyuchenie-apipay-mcp)), или вписываете вы сами; помощнику не разрешайте читать этот файл и выводить его содержимое. Кнопка кабинета «Скопировать инструкцию без ключей» копирует только безопасный текст.

Следующий sandbox-цикл описывает REST-интеграцию. Для полного теста счёт создаётся через ваше приложение, а оплату агент симулирует через `simulate-status`. Обычный технический тест webhook и HTTP 200 сами по себе не подтверждают изменение заказа. Исправление найденной ошибки сначала согласуется с владельцем.

## Коротко

| Параметр | Значение |
|---|---|
| Base URL API | `https://api.apipay.kz/api/v1` (это не сайт apipay.kz) |
| Авторизация | Заголовок `X-API-Key`, `Content-Type: application/json` |
| Тест без Kaspi | `POST /invoices/{id}/simulate-status` — только sandbox |
| Узнать об оплате | для старта — опрос `GET /invoices/{id}` с сервера; вебхук — по желанию |
| Проверка вебхука | `GET /webhook-logs?invoice_id=…`, пагинация `{current_page, data, total}` |
| Подпись вебхука | `X-Webhook-Signature: sha256=<hex>` — HMAC-SHA256 от сырого тела |
| Лимиты | 200 req/min на ключ; у отдельных эндпоинтов свои — [лимиты и квоты](/guides/limity-i-kvoty-apipay) |

## Машинная дорожка

Дайте ИИ-ассистенту любой из этих URL — по ним он поймёт весь API (помощнику с терминалом сначала нужен MCP, см. выше):

- `https://apipay.kz/llms.txt` — компактный контекст для LLM: методы, проверенные факты, чейнджлог.
- `https://apipay.kz/openapi.json` — полная OpenAPI 3.0 спецификация (для генерации типизированного клиента).
- `https://apipay.kz/apipay-api-docs.md` — полный Markdown с примерами на разных языках (для парсинга).
- `https://apipay.kz/docs` — документация для чтения в браузере.
- Пошаговый плейбук для ИИ — [apipay.kz/for-ai](/for-ai); готовые промпты — [apipay.kz/prompts](/prompts).

## Что такое ApiPay (контекст для ИИ)

ApiPay — приём платежей Kaspi Pay по номеру телефона в Казахстане через REST API. Мерчант создаёт счёт → покупатель платит в приложении Kaspi → сервер мерчанта узнаёт об оплате опросом статуса или вебхуком. Деньги идут напрямую на Kaspi-счёт мерчанта.

## Как узнавать об оплате: опрос или вебхук

**Для старта хватит опроса.** Сервер сохраняет `invoice.id` и запрашивает `GET /invoices/{id}` раз в 3–5 секунд, пока покупатель на экране оплаты и счёт ждёт оплаты; дальше — реже, как фоновая сверка. Запросы идут только с сервера: ключ `X-API-Key` в браузер не попадает. У `GET /invoices/{id}` отдельный лимит — 1000 запросов в минуту на ключ. Адрес уведомлений и секрет подписи для этого не нужны.

**Вебхук — когда нужен мгновенный отклик** или счетов много. Для него нужен публичный HTTPS-адрес; секрет подписи рекомендуем — без него запрос ничем не подтверждён, и перед выдачей товара статус сверяют через `GET /invoices/{id}`. Секрет выпускается в кабинете после сохранения адреса: карточка ключа → «Ещё» → «Создать секретный ключ подписи». Опрос при подключённом вебхуке оставьте как страховку. Подробно — в разборе [настройки вебхуков](/guides/nastroyka-webhookov-apipay).

## Тест-цикл в песочнице

Это ядро проверки: ИИ-агент прогоняет статусы счёта без Kaspi и без телефонов. Схема: создать sandbox-счёт → `simulate-status` → проверить статус и вебхук через `webhook-logs` → (при `paid`) возврат. Прямой вызов API из консоли проверяет только сторону ApiPay. Чтобы проверить интеграцию целиком, тестовый счёт создаёт само приложение через свой заказ, а изменение заказа и экран проверяются в приложении.

**Шаг 1. Создать sandbox-счёт.** Если организация в песочнице, счёт помечается `is_sandbox: true`. Для счёта по номеру `POST /invoices` отвечает `201 processing`: создание асинхронное, до симуляции дождитесь `pending` через вебхук или `GET /invoices/{id}`. Для QR `POST /invoices/qr` создаёт счёт синхронно и отвечает `201 pending`; отдельного вебхука перехода в `pending` нет, ждать его не нужно.

**Шаг 2. Симулировать статус — `POST /invoices/{invoice}/simulate-status`:**
- Работает **только для sandbox-счёта** (`is_sandbox: true`). Для не-sandbox счёта → `403 not_sandbox`.
- Тело: `{ "status": <enum> }`, где `status ∈ { paid, cancelled, expired, error, qr_scanned, pending }`; `pending` — из `error` или `cancelling`, `paid` — ещё и поздняя оплата из `cancelled` и `expired`.
- `paid` / `cancelled` / `expired` — счёт уходит в терминальный статус, отправляется вебхук `invoice.status_changed`. Опционально можно задать `kaspi_source_type` (`GOLD|RED|LOAN|BUSINESSACCOUNT|BANKINTEGRATIONACCOUNT`) и `kaspi_sale_type` (`Remote|QR|Static|Restaurant`); иначе при `paid` они выбираются случайно.
- `error` — счёт получает `error_code: sandbox_simulated_error` и `error_message` (свой текст можно передать в необязательном параметре `error_message`). Вебхук уходит как при реальной ошибке.
- `qr_scanned` — **только для QR-счёта**: статус остаётся `pending`, уходит вебхук `invoice.qr_scanned` с `qr_substate: "scanned"`. Повтор → `400 already_scanned`; для не-QR счёта → `400 not_qr_invoice`.
- Перехода нет в таблице переходов → `400 invalid_status_transition` (в ответе `current_status` и `allowed_from`).
- Успех — `200 { "message": "Invoice status simulated", "invoice": {…} }`.

**Шаг 3. Проверить результат.** Без подключённых уведомлений достаточно `GET /invoices/{id}`: статус счёта должен стать симулированным. Если уведомления подключены — проверьте и доставку вебхука через `GET /webhook-logs`:
- Read-only логи доставок вашей организации. Пишутся доставки по счетам, возвратам, QR-возвратам, подпискам (`subscription.*`), чекам (`receipt.*`) и кассе; событие счёта, возврата или QR-возврата, не отправленное из-за паузы отправки ключа, лежит строкой `status: skipped` и не повторяется (подписки и чеки паузу не соблюдают). События каталога живут в отдельном журнале `GET /api/v1/catalog/webhook-logs`. Фильтры: `invoice_id`, `event` (`invoice.status_changed`, `invoice.qr_scanned`, `invoice.refunded`), `status` (`success|failed|skipped`), `date_from`/`date_to`.
- Пагинация плоская: `{ current_page, data, total }`.
- `GET /webhook-logs/{id}` — одна доставка с полными `request_body`/`response_body`; чужой лог → `404` (защита от перебора).
- Логи хранятся 14 дней; в рабочем режиме повтор доставки — только из кабинета, в песочнице неудачную доставку повторяет `POST /webhook-logs/{id}/retry`.
- **Критерий успеха цикла:** по каждому симулированному статусу `GET /invoices/{id}` показывает ожидаемый статус, а при подключённых уведомлениях в `/webhook-logs` появляется запись `status: success` с ожидаемым `event`.

**Шаг 4 (опционально). Проверить возврат.** При `paid` — `POST /invoices/{id}/refund` (полный или частичный `amount`), затем `GET /invoices/{id}/refunds`.

Полный воспроизводимый цикл (ключ — в переменной окружения `APIPAY_API_KEY`; номер — маска или sandbox-константа, не реальный):

```bash
BASE="https://api.apipay.kz/api/v1"
KEY="$APIPAY_API_KEY"   # ключ — из переменной окружения, значение в команду не вписывайте

# 1) sandbox-счёт
ID=$(curl -s -X POST "$BASE/invoices" -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":10000,"phone_number":"87770000001","description":"Sandbox test"}' \
  | jq -r '.id')

# 2) дождаться pending (сразу после создания счёт в processing; симуляция раньше даст
#    400 invalid_status_transition), выход по error и по таймауту
for i in $(seq 1 30); do
  STATUS=$(curl -s "$BASE/invoices/$ID" -H "X-API-Key: $KEY" | jq -r '.status')
  [ "$STATUS" = "pending" ] && break
  [ "$STATUS" = "error" ] && { echo "Счёт в error — смотрите error_code"; exit 1; }
  sleep 2
done
[ "$STATUS" = "pending" ] || { echo "Счёт не перешёл в pending за минуту"; exit 1; }

# 2а) симулировать оплату (только sandbox)
curl -s -X POST "$BASE/invoices/$ID/simulate-status" -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" -d '{"status":"paid"}'

# 3) проверить статус счёта
curl -s "$BASE/invoices/$ID" -H "X-API-Key: $KEY" | jq -r '.status'

# 3а) если подключены уведомления — проверить, что вебхук ушёл
curl -s "$BASE/webhook-logs?invoice_id=$ID&event=invoice.status_changed" \
  -H "X-API-Key: $KEY" | jq '.data[] | {event, status, response_status}'
```

## Готовые промпты для вашего ИИ

Скопируйте нужный промпт своему ассистенту. Каждый дан на русском и английском.

**1. Сгенерировать клиент по OpenAPI.**
> RU: «Открой `https://apipay.kz/openapi.json` и сгенерируй типизированный клиент для ApiPay: base URL `https://api.apipay.kz/api/v1`, заголовок авторизации `X-API-Key`. Реализуй `POST /invoices` (счёт по номеру), `GET /invoices/{id}` (статус), `POST /invoices/{id}/refund` (возврат). Ключ бери из переменной окружения, не хардкодь.»
> EN: “Open `https://apipay.kz/openapi.json` and generate a typed client for ApiPay: base URL `https://api.apipay.kz/api/v1`, auth header `X-API-Key`. Implement `POST /invoices` (invoice by phone), `GET /invoices/{id}` (status), `POST /invoices/{id}/refund`. Read the key from an environment variable, never hardcode it.”

**2. Проверка оплаты опросом — для быстрого старта.**
> RU: «Проверяй оплату ApiPay опросом `GET /invoices/{id}` только с сервера: ключ `X-API-Key` бери из переменной окружения, в код браузера не передавай. Пока покупатель на экране оплаты — раз в 3–5 секунд, пока счёт в `processing` или `pending`; у QR-счёта — до `qr_expires_at`. Затем сверяй в фоне раз в 1–2 минуты все заказы без `paid`: счёт в `pending` — пока он не сменит статус, а закрытые по `cancelled`, `expired` или `error` — ещё 24 часа после этого: эти статусы ещё могут смениться на `paid` или `pending`. Заказ отмечай оплаченным только по `paid`.»
> EN: “Check ApiPay payment by polling `GET /invoices/{id}` from the server only: read `X-API-Key` from an environment variable, never pass it to browser code. While the buyer is on the payment screen, poll every 3–5 seconds while the invoice is `processing` or `pending`; for a QR invoice, until `qr_expires_at`. Then re-check in the background every 1–2 minutes every order that is not `paid`: a `pending` invoice until its status changes, and one closed as `cancelled`, `expired` or `error` for 24 more hours — these statuses can still change to `paid` or `pending`. Mark the order paid only on `paid`.”

**3. Вебхук-приёмник с проверкой HMAC — если подключаете уведомления.**
> RU: «Построй HTTP-эндпоинт-приёмник вебхуков ApiPay. Проверяй подпись `X-Webhook-Signature: sha256=<hex>` = `hash_hmac('sha256', <сырое тело>, webhook_secret)` по сырому телу запроса (до парсинга JSON). Отвечай HTTP 2xx в пределах 5 секунд. Дедуплицируй по `(invoice.id, invoice.status)`, но `pending` после `error` и `error` после такого `pending` не отбрасывай: это новые переходы, даже если этот статус по счёту уже приходил. Обработай события `invoice.status_changed`, `invoice.qr_scanned`, `invoice.refunded`.»
> EN: “Build an ApiPay webhook receiver. Verify the `X-Webhook-Signature: sha256=<hex>` header = `hash_hmac('sha256', <raw body>, webhook_secret)` against the raw request body (before JSON parsing). Reply HTTP 2xx within 5 seconds. Deduplicate by `(invoice.id, invoice.status)`, but do not drop `pending` after `error` or `error` after such a `pending`: they are new transitions even if that status already arrived for this invoice. Handle `invoice.status_changed`, `invoice.qr_scanned`, `invoice.refunded`.”

**4. Полный sandbox-цикл с проверкой.**
> RU: «В песочнице: создай счёт через `POST /invoices`, дождись `pending`, затем прогони `POST /invoices/{id}/simulate-status` для `paid`, `error` и (для QR-счёта) `qr_scanned`; после каждого убедись через `GET /invoices/{id}`, что статус изменился, а если подключены уведомления — через `GET /webhook-logs?invoice_id=…`, что доставка `status: success` с ожидаемым `event`. Учти: `simulate-status` работает только для sandbox-счетов.»
> EN: “In sandbox: create an invoice via `POST /invoices`, wait for `pending`, then run `POST /invoices/{id}/simulate-status` for `paid`, `error` and (for a QR invoice) `qr_scanned`; after each, confirm via `GET /invoices/{id}` that the status changed and, if notifications are set up, via `GET /webhook-logs?invoice_id=…` that delivery is `status: success` with the expected `event`. Note: `simulate-status` works only for sandbox invoices.”

**5. Обработка ошибок по `error_code`.**
> RU: «Реализуй ветвление по полю `error_code`/`error` (каталог — `/errors`): для асинхронной ошибки счёта (вебхук `invoice.status_changed`, `status=error`) читай `error_code`/`error_message`; на `429` разбирай код ограничения и соблюдай `Retry-After`, если он есть. У `qr_rate_limit` времени повтора нет — подожди примерно минуту; KYC-ограничение снимается одобрением анкеты, не ожиданием. На `422` разбирай `errors`. „Повтор“ при `status=error` означает создать новую операцию, а не повторять ту же.»
> EN: “Branch on the `error_code`/`error` field (catalog at `/errors`): for an async invoice error (webhook `invoice.status_changed`, `status=error`) read `error_code`/`error_message`; on `429` inspect the restriction and respect `Retry-After` when present. `qr_rate_limit` has no retry time — wait about one minute; a KYC restriction requires approval, not waiting. On `422` parse `errors`. A ‘retry’ on `status=error` means creating a new operation, not retrying the same one.”

## Проверка вебхуков и HMAC

Этот раздел нужен, если подключены уведомления.

- Заголовок подписи: `X-Webhook-Signature: sha256=<hex>` = `hash_hmac('sha256', <тело запроса>, webhook_secret)` — верифицируйте по **сырому телу** (raw body), а не по перепарсенному JSON. Заголовок присылается, только если у ключа задан `webhook_secret`.
- Успех доставки — любой HTTP 2xx; приёмник должен ответить **в пределах 5 секунд**, тяжёлую работу выносите в фон. Эндпоинт не должен отвечать редиректом — в настройках указывайте конечный URL.
- **Дедуп обязателен** (ретрай после частичной доставки уходит всем приёмникам). Ключи дедупа: `(invoice.id, invoice.status)`, `(refund.id, refund.status)`, `(event, subscription.id, invoice_id)` (`invoice_id` есть только в `subscription.payment_succeeded`, `subscription.payment_failed` и `subscription.cancelled` с `reason` `payer_refused` или `payer_error`), у `subscription.period_skipped` — `(event, subscription.id, billing_period_start)`. После `error` по счёту может снова прийти `pending`, а затем снова `error`, даже если этот статус по нему уже приходил: `pending` после `error` и `error` после такого `pending` — новые переходы, а не дубли.
- Ретраи, circuit breaker, список событий и код проверки подписи — в разборе [настройки вебхуков](/guides/nastroyka-webhookov-apipay).

## Обработка ошибок

- Определяйте тип ошибки по стабильному полю `error_code` (snake_case), а не по тексту; `message`/`error` оставлены для обратной совместимости. Каталог кодов — на странице [apipay.kz/errors](/errors): у каждого кода постоянный якорь `/errors#код`, поля со ссылкой в ответе API нет.
- **Асинхронные ошибки Kaspi.** `POST /invoices` отвечает `201 processing`. Если Kaspi не смог создать счёт, статус станет `error`, причина — в `error_message`, код — в `error_code` (например `client_not_found`, `network_unavailable`, `kaspi_throttled`). Забирайте результат через `GET /invoices/{id}` или из вебхука `invoice.status_changed`. Не пересоздавайте счёт, пока он в `processing` — получите два живых счёта. QR создаётся синхронно: `POST /invoices/qr` при успехе отвечает `201 pending`, без отдельного `pending`-вебхука; отказ создания разбирайте по HTTP-ответу.
- **HTTP-статусы:** `401` (ключ отсутствует/невалиден/деактивирован), `403` (`tariff_inactive`, `kyc_rejected`, организация не верифицирована), `404`, `409` (`duplicate_idempotency_key` — в теле `invoice_id` и `status` уже существующего счёта), `422` (валидация — детали в `errors`), `429` (смотрите `error_code`/`error` и `Retry-After`, если он есть; `qr_rate_limit` приходит без времени ожидания — пауза примерно минуту, `kyc_daily_limit_reached` требует одобрения анкеты), `502` (сторона Kaspi), `503` (`kaspi_session_invalid` на `POST /invoices/qr` — QR-счёт не создан, помогает только переавторизация кассира; `invoices_disabled` — счёт НЕ создан, повтор позже безопасен).

## Sandbox vs Production и предупреждения

- При регистрации создаётся sandbox-организация; тестовые счета и подписки помечены `is_sandbox: true`. Переключение в рабочий режим — переключатель в личном кабинете. Что именно меняется — в разборе [песочница и рабочий режим](/guides/pesochnitsa-i-rabochiy-rezhim).
- **Гигиена ключа:** `X-API-Key` не коммитьте в репозиторий, храните в переменных окружения или секретах. В примерах — только `YOUR_API_KEY`. Разница ключа и секрета подписи — в разборе [API-ключ и вебхук-секрет](/guides/api-klyuch-i-webhook-secret).
- **Запрет массового перебора `POST /clients/check`:** проверять можно номера своих покупателей, а не базу целиком. При злоупотреблении ключ деактивируется без предупреждения. Sandbox-режим: `87770000001` → `has_kaspi: true`, `"Иван И."`; `87770000002` → `has_kaspi: false`; любой другой → `false`.
- Отмена в проде асинхронна: `POST /invoices/{id}/cancel` → `202` + статус `cancelling`, реальный итог придёт вебхуком.

## Краткий справочник

- **Статусы счёта:** `processing`, `pending`, `cancelling`, `paid`, `cancelled`, `expired`, `error`, `partially_refunded` — что означает каждый, в разборе [жизненного цикла счёта](/guides/zhiznennyy-tsikl-scheta).
- **Ключевые эндпоинты цикла:** `POST /invoices`, `POST /invoices/qr`, `GET /invoices/{id}`, `POST /invoices/{id}/simulate-status` (sandbox), `GET /webhook-logs`, `GET /webhook-logs/{id}`, `POST /invoices/{id}/refund`.
- **Partner API** (`X-Partner-Key`, `/api/partner`) — отдельная тема для CRM и платформ, которые онбордят чужих мерчантов: см. разбор [как партнёру подключить организацию мерчанта](/guides/partner-connect-organization).
- Как ставится приём Kaspi целиком (регистрация, кассир, первый счёт) — в разборе [настройки за 15 минут](/guides/nastroyka-apipay-za-15-minut).

## In English

ApiPay accepts Kaspi Pay payments through the merchant's own Kaspi Pay account: create an invoice, the buyer pays in the Kaspi app, the merchant's server learns about it by polling the invoice status or from a webhook. Money goes straight to the merchant's Kaspi account.

Give your AI assistant one of the machine files and it can build the integration: `https://apipay.kz/llms.txt`, `https://apipay.kz/openapi.json`, or `https://apipay.kz/apipay-api-docs.md`. Base URL: `https://api.apipay.kz/api/v1`; auth header `X-API-Key`; `Content-Type: application/json`; 200 req/min per key. An assistant working in your project with a terminal will first ask you to connect the ApiPay MCP at apipay.kz/setup/ai.

**Autonomous sandbox test loop (no Kaspi, no phone numbers):** create a sandbox invoice with `POST /invoices` (wait for `pending`), drive its status with `POST /invoices/{id}/simulate-status` (`paid|cancelled|expired|error|qr_scanned`, sandbox only — `403 not_sandbox` otherwise; `400 invalid_status_transition` if not `pending`), then check `GET /invoices/{id}`; if notifications are set up, also verify webhook delivery via `GET /webhook-logs?invoice_id=…` (flat pagination `{current_page, data, total}`), where success = a `status: success` row with the expected `event`. Optionally refund with `POST /invoices/{id}/refund`.

**Payment status:** to get started, server-side polling of `GET /invoices/{id}` is enough — every 3–5 seconds while the buyer is on the payment screen, then less often as a background check (separate limit: 1000/min per key). Add webhooks when you need an instant reaction or handle many invoices; keep polling as a fallback. **Webhooks:** signature `X-Webhook-Signature: sha256=<hex>` = `hash_hmac('sha256', <raw body>, webhook_secret)` — verify against the raw body, reply 2xx within 5 seconds, deduplicate by `(invoice.id, invoice.status)`. Your endpoint must not redirect. **Errors:** branch on `error_code`/`error` (catalog at `/errors`); `POST /invoices` is async (`201 processing`), while `POST /invoices/qr` is synchronous (`201 pending`, no separate pending webhook). For `429`, inspect the restriction and respect `Retry-After` when present; `qr_rate_limit` has no retry time — wait about one minute; KYC requires approval. Never hardcode `X-API-Key`; don't bulk-probe `POST /clients/check` — check your own customers' numbers only, abuse deactivates the key. The ready-made prompts above are provided in English too.

## Частые вопросы

**Работает ли `simulate-status` в рабочем режиме?**
Нет. `simulate-status` доступен только для sandbox-счетов (`is_sandbox: true`); в проде вызов вернёт `403 not_sandbox`.

**Почему `POST /invoices` вернул `201`, но статус `processing`?**
Это не ошибка: создание счёта асинхронное. Счёт перейдёт в `pending` вебхуком; при сбое Kaspi станет `error` с `error_code`/`error_message`. Не пересоздавайте счёт в `processing` — иначе получите два живых счёта.

**Как отличить `X-API-Key` от `X-Partner-Key`?**
`X-API-Key` — обычный мерчантский ключ для `/api/v1` (счета, вебхуки, возвраты). `X-Partner-Key` — для Partner API (`/api/partner`), которым платформы онбордят чужих мерчантов; это отдельная тема.

---

ApiPay — независимый сервис и не аффилирован с АО «Kaspi Bank». Kaspi и Kaspi Pay — товарные знаки их правообладателя.
База знаний: https://apipay.kz/guides
