Платёжная ссылка — это готовая страница оплаты Kaspi Pay, которую вы создаёте одним запросом POST /v2/payment-links и отправляете плательщику в мессенджере, письме или счёте. В ответ приходит короткий публичный URL вида https://paybot.kz/checkout/{token} и картинка QR-кода — покупатель открывает ссылку, платит в Kaspi, а вы получаете вебхук об оплате. Ни своей страницы оплаты, ни интеграции с QR вручную не требуется.
Платёжные ссылки работают поверх Hosted Checkout — публичной страницы PayBot, которая сама выдаёт свежий Kaspi QR при каждом открытии. Это делает ссылку пригодной и для онлайн-оплаты (кнопка в интернет-магазине), и для офлайна (напечатанный QR на кассе).
Как создать платёжную ссылку
Отправьте POST /v2/payment-links с суммой в тенге и описанием заказа. Эндпоинт принимает и API-ключ (X-API-Key), и JWT-токен кабинета (Authorization: Bearer) — используйте тот способ авторизации, что уже есть под рукой.
Обязательные поля тела — только amount (целое число тенге) и description (1–500 символов). Остальное опционально и имеет разумные значения по умолчанию.
curl -X POST https://api.paybot.kz/v2/payment-links \
-H "X-API-Key: kp_live_00112233445566778899aabbccddeeff" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5f9c1e2a-7b3d-4c8e-9a1f-2d6b8c0e4a11" \
-d '{
"amount": 5000,
"description": "Заказ #1234",
"success_url": "https://shop.example/success",
"cancel_url": "https://shop.example/cancel",
"expires_in_minutes": 1440,
"allow_repeat": false,
"email_required": false,
"metadata": {"order_id": "1234"}
}'import requests, uuid
resp = requests.post(
"https://api.paybot.kz/v2/payment-links",
headers={
"X-API-Key": "kp_live_00112233445566778899aabbccddeeff",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"amount": 5000,
"description": "Заказ #1234",
"success_url": "https://shop.example/success",
"cancel_url": "https://shop.example/cancel",
"metadata": {"order_id": "1234"},
},
)
link = resp.json()
print(link["url"]) # https://paybot.kz/checkout/pl_abc123
print(link["qr_image_url"]) # PNG для печатиПример ответа 200 OK:
{
"id": 1024,
"token": "pl_abc123",
"url": "https://paybot.kz/checkout/pl_abc123",
"qr_image_url": "https://api.qrserver.com/v1/create-qr-code/?size=600x600&data=https://paybot.kz/checkout/pl_abc123",
"kaspi_qr_image_url": "https://api.qrserver.com/v1/create-qr-code/?size=600x600&data=3010...",
"deep_link": "https://qr.kaspi.kz/pay/abc123",
"amount": 5000,
"description": "Заказ #1234",
"status": "active",
"success_url": "https://shop.example/success",
"cancel_url": "https://shop.example/cancel",
"expires_at": "2026-07-17T10:00:00Z",
"qr_expires_at": "2026-07-16T10:05:00Z",
"allow_repeat": false,
"email_required": false,
"metadata": {"order_id": "1234"},
"created_at": "2026-07-16T10:00:00Z"
}Какие поля принимает запрос
| Поле | Тип | Обязательно | Назначение |
|---|---|---|---|
amount | integer | да | Сумма в тенге (₸), целое число. |
description | string (1–500) | да | Описание заказа, видно плательщику. |
success_url | string (≤2048) | нет | Куда вернуть покупателя после оплаты. |
cancel_url | string (≤2048) | нет | Куда вернуть при отмене или истечении. |
expires_in_minutes | integer (5–43200) | нет | Срок жизни ссылки, по умолчанию 1440 (24 часа), максимум 30 дней. |
allow_repeat | boolean | нет | Разрешить несколько успешных оплат по одной ссылке (по умолчанию false). |
email_required | boolean | нет | Спросить email плательщика перед оплатой. |
metadata | object | нет | Произвольный JSON — вернётся в вебхуке об оплате. |
Все суммы — целые тенге; тиынов на входе и выходе нет. Поле metadata удобно для связки платежа с заказом в вашей системе: то, что вы положили сюда, придёт обратно в теле вебхука payment.completed.
Что означает поле status
Статус ссылки описывает её жизненный цикл и приходит в поле status.
| Статус | Значение |
|---|---|
active | Ссылка активна, оплата возможна. |
paid | Ссылка оплачена (для allow_repeat: false — финальный статус). |
expired | Истёк expires_at, оплата больше невозможна. |
cancelled | Ссылка отменена вами вручную. |
Не опрашивайте статус ссылки в цикле сами — для отслеживания оплаты используйте вебхуки payment.completed, а для страницы оплаты покупателя статус уже опрашивает Hosted Checkout.
Короткая публичная ссылка и QR для печати
Поле url в ответе — это и есть короткая ссылка на страницу оплаты: https://paybot.kz/checkout/{token}. Её можно слать в WhatsApp, Telegram, SMS или вставлять кнопкой на сайт — открыв её, покупатель попадает на брендированную страницу оплаты.
Поле qr_image_url возвращает PNG QR-кода, который кодирует ту же постоянную ссылку paybot.kz/checkout/{token}. Этот QR статичен: его можно один раз напечатать и наклеить на кассу или витрину, а страница внутри при каждом открытии выдаёт свежий одноразовый Kaspi QR. Поле kaspi_qr_image_url — это, наоборот, текущий динамический Kaspi QR (одноразовый), а deep_link открывает приложение Kaspi напрямую на телефоне.
qr_image_url (постоянный), а не kaspi_qr_image_url (протухнет через ~5 минут).Как разрешить несколько оплат по одной ссылке
Установите allow_repeat: true, чтобы одну ссылку можно было оплатить много раз — это сценарий «ссылка-донат» или «оплата на витрине», когда по одному URL платят разные люди. При этом ссылка не переходит в финальный paid после первой оплаты, а остаётся active до истечения expires_at.
Для таких ссылок на странице оплаты важно передавать идентификатор конкретного цикла оплаты — подробнее в разделе Hosted Checkout, где описан параметр op.
Как изменить или продлить ссылку
PATCH /v2/payment-links/{token} меняет description, success_url, cancel_url, expires_at и allow_repeat. Продление expires_at из состояния expired снова делает ссылку active.
curl -X PATCH https://api.paybot.kz/v2/payment-links/pl_abc123 \
-H "X-API-Key: kp_live_00112233445566778899aabbccddeeff" \
-H "Content-Type: application/json" \
-d '{"expires_at": "2026-07-20T10:00:00Z", "description": "Заказ #1234 (продлён)"}'Редактирование запрещено, если ссылка уже в статусе paid или cancelled и при этом allow_repeat: false — в ответ придёт 409 payment_link_immutable. Заранее блокируйте кнопку редактирования по текущему status, чтобы не ловить эту ошибку.
Чтобы выдать свежий Kaspi QR, не меняя саму ссылку, используйте POST /v2/payment-links/{token}/refresh-qr — он работает только при status == "active", иначе вернёт 409 payment_link_not_active.
Как отменить платёжную ссылку
POST /v2/payment-links/{token}/cancel переводит ссылку в статус cancelled — после этого оплатить её нельзя.
curl -X POST https://api.paybot.kz/v2/payment-links/pl_abc123/cancel \
-H "X-API-Key: kp_live_00112233445566778899aabbccddeeff"Попытка отменить уже оплаченную ссылку вернёт 409 payment_link_already_paid. Как и с редактированием, дизейблите действие по status заранее.
Как получить список ссылок
GET /v2/payment-links возвращает ссылки с курсорной пагинацией. Параметры запроса: cursor, limit (1–100, по умолчанию 25) и status. Ответ — конверт {data, next_cursor, has_more}; признак «есть ещё страница» — это has_more, а cursor передавайте как непрозрачную строку, не разбирая её.
curl "https://api.paybot.kz/v2/payment-links?limit=25&status=active" \
-H "X-API-Key: kp_live_00112233445566778899aabbccddeeff"Элементы списка намеренно не содержат metadata и данных QR — чтобы получить qr_image_url и metadata конкретной ссылки, запрашивайте её отдельно через GET /v2/payment-links/{token}.
FAQ
Нужен ли договор эквайринга, чтобы принимать оплату по ссылке?
Нет. PayBot работает поверх вашего личного или бизнес-аккаунта Kaspi Pay через Kaspi API — отдельный договор эквайринга с банком не требуется. Достаточно подключить Kaspi-аккаунт в кабинете; деньги приходят на ваш счёт Kaspi.
Чем платёжная ссылка отличается от QR через API?
Платёжная ссылка — это готовая брендированная страница оплаты с постоянным URL, которую не нужно программировать: вы просто отдаёте ссылку покупателю. Прямой вызов QR или счёта через API даёт вам сырой qr_token и deep_link, которые вы сами рисуете и показываете в своём интерфейсе. Ссылка удобнее для ручной отправки и печати, прямой API — для встраивания в собственный POS или чекаут.
Идемпотентен ли повторный запрос на создание ссылки?
Да. Для POST /v2/payment-links заголовок Idempotency-Key опционален — если вы его не передадите, сервер сам подставит ключ вида pl_auto_. Но чтобы двойной клик по кнопке не создал две ссылки, передавайте свой ключ (обычно UUID v4) — один на одно намерение пользователя. Подробнее в разделе Идемпотентность.
Сколько живёт ссылка?
По умолчанию 24 часа (expires_in_minutes: 1440). Минимум — 5 минут, максимум — 30 дней (43200 минут). Точное время истечения приходит в поле expires_at (UTC) — ориентируйтесь на него, а не на константу.