> Источник: https://apipay.kz/guides/kak-sozdat-schet-kaspi-po-nomeru · Обновлено: 2026-07-06 · apipay.kz
> ApiPay — независимый сервис приёма платежей поверх вашего Kaspi Pay.

# Как создать счёт Kaspi по номеру телефона через API?

**TL;DR.** Один запрос `POST /invoices` с заголовком `X-API-Key`: передаёте номер покупателя в формате `8XXXXXXXXXX` и сумму — покупатель получает push-уведомление в приложении Kaspi и оплачивает в одно касание. Счёт живёт **24 часа**. API отвечает мгновенно со статусом `processing` — это нормально: фактическое выставление в Kaspi асинхронное, итог принесёт вебхук. После оплаты статус `paid` обычно виден за **10–20 секунд**.

## Коротко

| Вопрос | Ответ |
|---|---|
| Эндпоинт | `POST https://api.apipay.kz/api/v1/invoices` |
| Авторизация | Заголовок `X-API-Key` (ключ — в кабинете, показывается один раз) |
| Обязательные поля | `phone_number` (формат `8XXXXXXXXXX`) + `amount` (или `cart_items` вместо суммы) |
| Описание счёта | `description` до 500 символов |
| Ответ | `201` со статусом `processing` — Kaspi ещё не вызван, это не ошибка |
| Сколько живёт счёт | 24 часа |
| Как узнать об оплате | Вебхук `invoice.status_changed` со статусом `paid`; обычно за 10–20 секунд |
| Защита от дублей | `external_order_id_idempotency` → повтор даёт `409` |
| Лимит запросов | 200 запросов в минуту на API-ключ |

## Три шага: запрос → ответ → покупатель платит

### Шаг 1. Отправьте запрос

```bash
curl -X POST https://api.apipay.kz/api/v1/invoices \
  -H "X-API-Key: ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "87001234567",
    "amount": 5000,
    "description": "Оплата заказа №123",
    "external_order_id": "order-123",
    "external_order_id_idempotency": "order-123"
  }'
```

Номер — 11 цифр, начинается с 8: `8XXXXXXXXXX`. API-ключ берётся в кабинете apipay.kz (Настройки → API-ключи); полный ключ показывается только один раз при создании — подробнее в статье «[API-ключ и вебхук-секрет](/guides/api-klyuch-i-webhook-secret)».

### Шаг 2. Получите ответ 201 со статусом processing

```json
{
  "id": 1,
  "amount": "5000.00",
  "status": "processing",
  "phone": "77001234567",
  "created_at": "2026-07-02T10:25:00+06:00"
}
```

`processing` означает «принято в работу»: выставление счёта в Kaspi происходит асинхронно, в фоне. Ничего опрашивать в цикле не нужно — итоговый статус придёт вебхуком (настройка — «[Как настроить вебхуки ApiPay](/guides/nastroyka-webhookov-apipay)»). Для отладки текущее состояние можно посмотреть запросом `GET /invoices/{id}` — там же видны поля `last_kaspi_error_code` и `last_kaspi_error_message`, если Kaspi отвечал ошибкой между повторами.

### Шаг 3. Что видит покупатель

Покупателю приходит push-уведомление в приложении Kaspi: счёт с вашим описанием и суммой, кнопка «Оплатить» — оплата в одно касание, деньги идут напрямую на ваш Kaspi-счёт. Счёт доступен к оплате **24 часа**. После оплаты вам приходит вебхук `invoice.status_changed` со статусом `paid` — обычно в течение 10–20 секунд.

## Какие статусы проходит счёт?

| Статус | Что значит |
|---|---|
| `processing` | Принят, выставляется в Kaspi (асинхронно, с автоповторами) |
| `pending` | Выставлен, ждёт оплаты (до 24 часов) |
| `paid` | Оплачен — финальный «хороший» статус |
| `cancelled` | Отменён (вами через API или покупателем) |
| `expired` | Истекли 24 часа без оплаты |
| `error` | Выставить не удалось; в вебхуке будет `error_code` с причиной |
| `cancelling` | Отмена в процессе (прод: `202` на запрос отмены); вебхука на этот статус нет |
| `partially_refunded` | Был частичный возврат |

Вебхуки приходят на переходы в `pending`, `paid`, `cancelled`, `expired`, `error`, `partially_refunded`. На технические статусы `processing` и `cancelling` вебхуков не бывает.

## «Странные» переходы статусов, которые НЕ баг

Это самый важный раздел — он экономит обращения в поддержку. Все переходы ниже легитимны, закладывайте их в код:

- **`processing` дольше 60 минут — не зависание.** Если Kaspi временно ограничил частоту запросов (троттлинг), система выдерживает паузы и повторяет выставление — до 200 попыток. Легитимная очередь кассира может держать счёт в `processing` больше часа. Не пересоздавайте счёт в `processing` — получите **два живых счёта** и двойную оплату.
- **`cancelled` → `paid` и `expired` → `paid`.** Покупатель оплатил в последний момент, и оплата «выиграла гонку» у отмены/истечения. Придёт корректирующий вебхук `paid` — засчитайте оплату.
- **`error` → `pending`.** Система сверилась с Kaspi и обнаружила, что счёт всё-таки выставлен, — придёт корректирующий вебхук.
- **`error` → `paid` невозможен.** Если счёт в `error`, без промежуточного `pending` оплаты не будет.
- **Детект оплаты у «спящей» организации — до ~10 минут.** Частота сверки адаптивная: у активно продающих организаций оплата видна за 10–30 секунд, у организации после долгой паузы первая оплата может подтянуться в пределах 10 минут.

## Как не выставить два счёта за один заказ?

Передавайте `external_order_id_idempotency` (до 191 символа, уникален в пределах организации — удобно класть туда ID заказа). Повторный запрос с тем же значением вернёт **`409 duplicate_idempotency_key`** с `invoice_id` и `status` уже существующего счёта — дубль не создастся, даже при гонке двух параллельных запросов.

Исключение по смыслу: если прежний счёт уже мёртв (`expired`, `cancelled`, `error`), повторный запрос с тем же ключом **создаст новый счёт** — это осознанное поведение для перевыставления неоплаченного заказа. Для живых статусов (`processing`, `pending`, `paid`, `partially_refunded`) всегда будет `409`.

## Почему счёт ушёл в error?

В вебхуке и в `GET /invoices/{id}` будет машиночитаемый `error_code`. Самые частые:

| error_code | Причина | Что делать |
|---|---|---|
| `client_not_found` | Номер не зарегистрирован в Kaspi | Уточнить номер у покупателя; счёт на этот номер невозможен |
| Ошибка авторизации кассира | Привязка кассира разорвалась | Переподключить за 1 минуту: Настройки → «Авторизация Kaspi» |
| `kaspi_throttled` | Kaspi ограничил частоту | Подождать 2–3 минуты; система замедлится сама |
| `network_unavailable` | Kaspi временно недоступен | Повторить через 1–2 минуты |
| `unknown_error` | Попытки исчерпаны без диагноза | Написать в поддержку с `id` счёта |

Важно: если статус уже `error` — система свои повторы исчерпала, счёт финален. «Повторить» = создать новый счёт.

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

- **Поллить `GET /invoices/{id}` в цикле вместо вебхука.** Работает, но это лишняя нагрузка и задержка; рекомендуемый канал — вебхук. Лимит API — 200 запросов/мин на ключ.
- **Пересоздавать счёт, пока он в `processing`.** Получите два живых счёта. Ждите терминального статуса или используйте идемпотентность.
- **Передавать номер с `+7` или 10 цифр.** Формат строго `8XXXXXXXXXX` (11 цифр, первая — 8). В ответах API номер возвращается нормализованным (`77001234567`) — это нормально.
- **Считать `processing` в ответе ошибкой.** Это штатный ответ: выставление асинхронное.
- **Не передавать `external_order_id_idempotency`.** При сетевом таймауте ваш повторный запрос создаст второй счёт — покупатель получит два push.
- **Ждать оплату в песочнице.** В тестовом режиме счета в Kaspi не уходят — push не приходит. Переключите «Рабочий режим» в Настройках.

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

**Сколько живёт счёт по номеру телефона?**
24 часа с момента выставления. Не оплачен за 24 часа — перейдёт в `expired` (придёт вебхук). QR-счёт — отдельный формат со временем жизни 5 минут: «[QR-счёт: TTL и лимиты](/guides/qr-schet-ttl-i-limity)».

**Через сколько после оплаты я узнаю о ней?**
Обычно за 10–20 секунд приходит вебхук `paid`. У организации, которая долго не выставляла счета, первая сверка может занять до ~10 минут.

**Что будет, если у покупателя нет Kaspi?**
Счёт уйдёт в `error` с кодом `client_not_found`. Заранее проверить номер можно запросом `POST /clients/check` (лимит 60/мин на ключ).

**Можно ли отменить выставленный счёт?**
Да: `POST /invoices/{id}/cancel` — только для `pending`/`processing`. В рабочем режиме ответ `202`, отмена асинхронная; если покупатель успел оплатить, придёт `error` с `invoice_already_paid` или счёт останется оплаченным.

**Обязательно ли указывать amount?**
Либо `amount`, либо корзина `cart_items` (тогда сумма считается по позициям каталога): «[Счета с корзиной (cart_items)](/guides/scheta-s-korzinoy-cart-items-ofd)».

**Счёт висит в processing уже час — это зависание?**
Чаще всего нет: при троттлинге со стороны Kaspi система замедляется и повторяет — хвост очереди легитимно живёт больше 60 минут. «Зависшие» счета контролируются автоматикой: мёртвый процесс финализируется в `error` с осмысленным кодом и вебхуком.

Смотрите также: [Счета с корзиной (cart_items)](/guides/scheta-s-korzinoy-cart-items-ofd) · [QR-счёт: TTL и лимиты](/guides/qr-schet-ttl-i-limity) · [Вебхуки ApiPay](/guides/nastroyka-webhookov-apipay) · пиллар «[Как принимать оплату Kaspi через API](/kaspi-api)» · страница «[Счёт по номеру телефона](/invoice-by-phone)».

---

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