> Источник: https://apipay.kz/guides/besshovnyy-priyom-kaspi-dlya-klientov-partnyora · Обновлено: 2026-07-10 · apipay.kz
> ApiPay — независимый сервис приёма платежей поверх вашего Kaspi Pay.

# Как настроить полностью автоматический приём Kaspi для клиентов?

**TL;DR.** Клиент партнёра делает ровно **1 действие** — диктует **один код из Kaspi-SMS** при авторизации кассира, и **0 раз** заходит в кабинет ApiPay. Всё остальное партнёр делает через server-to-server Partner API (`X-Partner-Key`, хост `https://api.apipay.kz/api/partner`): создаёт организацию, выдаёт per-org `X-API-Key` + `webhook_url`, выставляет счета и возвраты, платит тариф ApiPay (по телефону `tariff/pay` **или** счётом на юрлицо `tariff/invoice`). Петлю закрывают **2 вебхука** — `invoice.status_changed` (клиент оплатил) и `tariff.activated` (тариф выдан), так что поллинг не нужен. Деньги идут напрямую на Kaspi-счёт клиента. Весь пайплайн сначала прогоняется в **sandbox** без реального Kaspi и SMS.

## Коротко

| Шаг пайплайна | Кто делает | API / событие |
|---|---|---|
| 1. Создать организацию клиента | Партнёр (авто) | `POST /organizations` (идемпотентно по `external_id`) |
| 2. Авторизовать кассира | Клиент диктует код из SMS | `kaspi-auth/init → send-phone → verify-otp` |
| 3. Выдать ключ и вебхук | Партнёр (авто) | `POST /organizations/{id}/api-key` → `X-API-Key` + `webhook_secret` |
| 4. Счета / каталог / возвраты | Партнёр (авто) | `X-API-Key` против `/api/v1` |
| 5. Оплата тарифа ApiPay | Партнёр (авто) | `tariff/pay` (телефон) **или** `tariff/invoice` (счёт юрлицу) |
| 6. Замкнуть петлю без поллинга | Вебхуки | `invoice.status_changed`, `tariff.activated` |
| Заходов клиента в кабинет ApiPay | — | **0** |

## Два ключа

У клиента **нет отдельного аккаунта ApiPay**: организацию, ключи и вебхук держит партнёр. Единственное действие клиента — подтвердить код из Kaspi-SMS при авторизации кассира (код приходит на номер кассира клиента, а не партнёру).

Ключей два, не путайте их — это главный источник ошибок:

- `X-Partner-Key` — партнёрский, server-to-server: онбординг, авторизация кассира, выдача ключей, тариф, health. Хост `.../api/partner`.
- per-org `X-API-Key` — ключ конкретного клиента: счета, статусы, возвраты, каталог, lookup. Хост `.../api/v1`.

Разбор пары ключей — в статье «[Partner API white-label](/guides/partner-api-white-label)».

## Шаг 1. Создать организацию клиента (авто)

`POST /organizations` с телом `{ "external_id": "crm-client-42", "name": "ТОО Клиент", "has_catalog": false }`. `external_id` — ваш референс клиента в CRM и **ключ идемпотентности**: повторный вызов с тем же `external_id` вернёт ту же организацию (`200`), дубля не будет. В ответе — `organization.id`, `status: "pending"`, `sandbox_mode`. Никакого участия клиента.

## Шаг 2. Авторизация кассира — единственный ручной штрих

Три вызова подряд: `POST /organizations/{id}/kaspi-auth/init` → `send-phone` → `verify-otp`. На `send-phone` вы передаёте телефон **кассира** клиента в формате `7XXXXXXXXXX`; Kaspi шлёт SMS-код на этот номер. Клиент диктует код — вы отправляете его в `verify-otp` (`{ "otp": "1234" }`). Всё, организация становится `verified`.

- `process_id` живёт ~10 минут — уложите `send-phone` + `verify-otp` в это окно.
- Слетела сессия позже — переавторизация тем же флоу с `init` + `"force": true`.

Ветки отказа `send-phone` и `verify-otp` (в том числе `409 cashier_unavailable`, суточный `429 rate_limited` и терминальные исходы, после которых нужен новый `init`) разобраны в статье «[Как партнёру подключить организацию](/guides/partner-connect-organization)» — заложите их обработку до запуска.

## Шаг 3. Выдать клиенту ключ и вебхук (авто)

`POST /organizations/{id}/api-key` с обязательным `webhook_url` (проходит SSRF-валидацию — приватный адрес `422`); указывайте постоянный домен своего сервиса, не шортенер и не временный адрес-перехватчик. В ответе `key` (это `X-API-Key`) и `webhook_secret` приходят в открытом виде **ровно один раз** — сохраните оба сразу в своё секрет-хранилище, привязав к записи клиента. Клиент этих ключей не видит и не хранит — они живут у партнёра. Как ключ соотносится с секретом подписи — «[API-ключ и вебхук-секрет](/guides/api-klyuch-i-webhook-secret)».

## Шаг 4. Счета, каталог, статусы, возвраты (авто)

Дальше работаете **выданным `X-API-Key`** против `https://api.apipay.kz/api/v1` — от имени клиента, но без его участия:

- Счёт по номеру — `POST /api/v1/invoices` (`201`, обработка асинхронная).
- QR-счёт на экране кассы — `POST /api/v1/invoices/qr`. Срок жизни берите из `qr_expires_at`, а не из константы: окно и лимиты — в статье «[QR-счёт: окно и лимиты](/guides/qr-schet-ttl-i-limity)».
- Возврат — `POST /api/v1/invoices/{id}/refund` (полный или частичный).

Полный платёжный API — в мерчантской документации [`/docs`](/docs); создание счетов по номеру — «[Счёт Kaspi по номеру](/guides/kak-sozdat-schet-kaspi-po-nomeru)».

## Шаг 5. Оплата тарифа ApiPay — два способа

Партнёр **сам платит ApiPay за подписку** клиента (`start`/`business`/`pro`/`pro_max` — сетка в статье «[Тарифы и комиссия](/guides/tarify-i-komissiya-apipay)»). Это подписочная плата клиент→ApiPay, **не** оборот клиента. Два независимых способа оплатить один тариф:

- **По телефону** — `POST /organizations/{id}/tariff/pay` с `{ "tier_id", "period_months", "phone": "8XXXXXXXXXX" }`. Push-счёт через Kaspi на телефон плательщика; активация асинхронная после оплаты.
- **Счётом на юрлицо** — `POST /organizations/{id}/tariff/invoice` с реквизитами покупателя (`buyer_bin` 12 цифр, `buyer_name`, опц. `buyer_address`/`contract`). Синхронно возвращает `download_url` — публичную ссылку на **PDF-счёт**, который оплачивается **банковским переводом**. Тариф активируется **вручную** владельцем ApiPay после поступления средств — автоактивации у счёта **нет**.

Неоплаченный счёт (`payment_method=invoice`) **не блокирует** `tariff/pay`, и наоборот — способы независимы. Точную сумму за выбранный период возвращает сервер (`GET /tariff-plans`), не считайте её сами.

## Шаг 6. Вебхуки закрывают петлю без поллинга

Два события снимают необходимость постоянно опрашивать статусы:

- **`invoice.status_changed`** — приходит на per-org `webhook_url` клиента, когда счёт меняет статус (в т.ч. `paid` — клиент оплатил). Реагируйте на **последний** статус: легитимны и `cancelled → paid`, и `expired → paid`.
- **`tariff.activated`** — приходит на `webhook_url` **партнёра**, когда владелец ApiPay вручную активировал тариф по выписанному счёту. Плоский payload с `payment_id`, `invoice_number`, `tier`, `amount`, `expires_at`.

Обе подписи — `X-Webhook-Signature: sha256=HMAC-SHA256(raw body, secret)`, проверяйте по **сырому телу**, до JSON-парсинга (готовые приёмники — «[Настройка вебхуков ApiPay](/guides/nastroyka-webhookov-apipay)»). Секреты **разные**: `invoice.status_changed` подписан per-org `webhook_secret` организации клиента, а `tariff.activated` — **партнёрским** `webhook_secret`, который выдан вместе с `X-Partner-Key`. Доставка `tariff.activated` повторяется автоматически (до 11 попыток); при окончательном сбое активацию видно поллингом `GET .../tariff/payments` (`pending → completed`).

## Сначала — sandbox

Весь пайплайн прогоняется в песочнице партнёра **без реального Kaspi и SMS**, детерминированно (магические номера кассира, OTP `0000`) — можно покрыть автотестами. Пока партнёр в sandbox, боевые вызовы отбиваются `403 production_access_required`; production открывается после ручного одобрения.

Не путайте телефоны: кассир — `7XXXXXXXXXX` (авторизация Kaspi), плательщик — `8XXXXXXXXXX` (кому выставляете счёт).

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

**Заходит ли клиент в кабинет ApiPay?**
Нет, ни разу. У клиента нет отдельного аккаунта ApiPay: организацию, `X-API-Key` и вебхук держит партнёр. Единственное действие клиента — продиктовать код из Kaspi-SMS при авторизации кассира.

**Как узнать, что тариф по счёту активирован?**
Придёт вебхук `tariff.activated` на `webhook_url` партнёра. Если он не дошёл (после ретраев), тот же факт виден поллингом `GET .../tariff/payments`: статус платежа `payment_method=invoice` переходит `pending → completed`. Автоактивации у `tariff/invoice` нет.

**Куда приходят вебхуки об оплате счетов клиента?**
На per-org `webhook_url` клиента (ключа, создавшего счёт). Партнёрский `webhook_url` в доставке `invoice`/`refund` не участвует — на него идёт только `tariff.activated`.

Смотрите также: [Partner API white-label](/guides/partner-api-white-label) · [Подключить организацию клиента](/guides/partner-connect-organization) · [ApiPay для платформ и SaaS](/guides/apipay-dlya-platform-i-saas) · [Настройка вебхуков](/guides/nastroyka-webhookov-apipay) · [Интеграция с помощью ИИ](/guides/integratsiya-apipay-s-pomoshchyu-ii) · страница [Partner API](/partners) · мерчантская дока [`/docs`](/docs).

---

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