> Источник: 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-счёт клиента — ApiPay независимый сервис поверх его Kaspi Pay. Весь пайплайн сначала прогоняется в **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** |

## Что означает «полностью автоматически»

Полностью автоматически — это когда клиент партнёра пользуется **вашим** продуктом (CRM, платформа, SaaS, 1С), а приём Kaspi «просто работает» под вашим брендом. У клиента **нет отдельного аккаунта 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` в это окно.
- Неверный код — это тоже **HTTP 200** с `{ "success": false, "error": "invalid_otp" }`, сессия не сбрасывается: просто попросите код заново и повторите `verify-otp`.
- Слетела сессия позже — переавторизация тем же флоу с `init` + `"force": true`.

Пошаговый онбординг с разбором каждой ошибки `send-phone` — в статье «[Как партнёру подключить организацию](/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` (TTL минуты).
- Возврат — `POST /api/v1/invoices/{id}/refund` (полный или частичный).

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

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

Партнёр **сам платит ApiPay за подписку** клиента (`start` 10 000 ₸/мес до 30 счетов/день, `business` 25 000 ₸ до 100, `pro` 60 000 ₸ 100–300; больше 300 — договорная). Это подписочная плата клиент→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, webhook_secret)`; проверяйте по **сырому телу**, до JSON-парсинга. Доставка `tariff.activated` ретраится автоматически (до 11 попыток); при окончательном сбое активацию видно поллингом `GET .../tariff/payments` (`pending → completed`). Готовые приёмники и проверка HMAC — «[Настройка вебхуков ApiPay](/guides/nastroyka-webhookov-apipay)».

## Сначала — sandbox

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

## Частые ошибки

- **Просить клиента зайти в кабинет ApiPay.** Не нужно: у клиента нет аккаунта, всё делает партнёр. Единственное действие клиента — продиктовать код из SMS.
- **Путать ключи и хосты.** `X-Partner-Key` → `.../api/partner`; per-org `X-API-Key` → `.../api/v1`. Перепутать — типовая причина `401`.
- **Путать телефоны.** Кассир — `7XXXXXXXXXX` (авторизация Kaspi), плательщик — `8XXXXXXXXXX` (кому выставляете счёт).
- **Ждать активации тарифа по счёту автоматически.** У `tariff/invoice` автоактивации нет — тариф выдаёт владелец ApiPay вручную после банковского перевода; ловите `tariff.activated` или поллинг `tariff/payments`.
- **Проверять HMAC по перепарсенному JSON.** Только по сырому телу — пересериализация ломает подпись.
- **Не сохранить one-time `key`/`webhook_secret`.** Показываются один раз; иначе только перевыпуск.

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

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

**Чем `tariff/invoice` отличается от `tariff/pay`?**
`tariff/pay` — push-счёт через Kaspi на телефон плательщика, активация асинхронная после оплаты. `tariff/invoice` — PDF-«Счёт на оплату» для юрлица, оплата банковским переводом, тариф активируется вручную владельцем ApiPay. Это два независимых способа оплатить один тариф.

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

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

**Можно ли всё протестировать без реального Kaspi?**
Да. Песочница партнёра детерминированно эмулирует онбординг, авторизацию кассира, счета и вебхуки без реального Kaspi и SMS (магические номера, OTP `0000`). Тот же код затем работает в production.

Смотрите также: [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
