Документация
1pay API
Принимайте платежи через Kaspi Pay по REST API. Все запросы — JSON, авторизация Bearer-ключом, единая модель платежа для счетов, QR-ссылок и кнопок.
Базовый URL
https://pay.1app.kzНет ключа? Зарегистрируйтесь, подключите устройство, создайте API-ключ — и делайте первый запрос.
Начало
Авторизация
Каждый запрос к /v1/* содержит заголовок с API-ключом. Ключ — секрет, держите только на сервере.
Authorization: Bearer 1pay_live_xxxxxxxxxxxx
Как принять платёж
Быстрый старт
- Подключите устройство (телефон кассира) и создайте API-ключ в дашборде.
- Создайте платёж:
POST /v1/payments(счёт на телефон) или/v1/payments/link(QR/ссылка). - Настройте вебхук в дашборде — на него придёт
payment.completed.
curl -X POST https://pay.1app.kz/v1/payments \-H "Authorization: Bearer 1pay_live_xxx" \-H "Content-Type: application/json" \-d '{"amount":1500,"payer_phone":"+77011234567","merchant_order_id":"order_1042"}'
Счёт на номер телефона
Знаете номер клиента — выставляете счёт. Клиенту приходит push в Kaspi, он подтверждает. Тип платежа: invoice.
const res = await fetch("https://pay.1app.kz/v1/payments", {method: "POST",headers: {"Authorization": `Bearer ${process.env.ONEPAY_API_KEY}`,"Content-Type": "application/json","Idempotency-Key": orderId,},body: JSON.stringify({amount: 1500,payer_phone: "+77011234567",merchant_order_id: orderId,comment: "Заказ №1042",}),});const payment = await res.json();// payment.id = "pay_..." payment.status = "PENDING"// Сохраните payment.id — ждите вебхук payment.completed
{"id": "pay_3kQ7v2","status": "PENDING","type": "invoice","amount": 1500,"currency": "KZT","payer_phone": "+77011234567","merchant_order_id": "order_1042","created_at": "..."}
Kaspi QR / платёжная ссылка
Нет номера клиента (онлайн-витрина, касса, email) — создаёте ссылку. В ответе payment_link (URL Kaspi) — покажите как QR или кнопку. Тип: link.
const res = await fetch("https://pay.1app.kz/v1/payments/link", {method: "POST",headers: {"Authorization": `Bearer ${process.env.ONEPAY_API_KEY}`,"Content-Type": "application/json","Idempotency-Key": orderId,},body: JSON.stringify({ amount: 4990, merchant_order_id: orderId }),});const payment = await res.json();// payment.payment_link = "https://pay.kaspi.kz/pay/..." → данные для QR
// Любая QR-библиотека по payment.payment_link:const qrImg = "https://api.qrserver.com/v1/create-qr-code/?size=240x240&data="+ encodeURIComponent(payment.payment_link);// <img src={qrImg} /> — клиент сканирует камерой приложения Kaspi
Вебхуки
Настройте вебхук в дашборде (URL + события). При создании выдаётся секрет(один раз). Каждый POST подписан: X-Webhook-Signature: sha256=<hmac> — HMAC-SHA256 от сырого тела вашим секретом.
import crypto from "crypto";app.post("/webhooks/1pay",express.raw({ type: "application/json" }), // ВАЖНО: сырой body(req, res) => {const sig = req.get("X-Webhook-Signature") || "";const expected = "sha256=" + crypto.createHmac("sha256", process.env.ONEPAY_WEBHOOK_SECRET).update(req.body).digest("hex");const ok = sig.length === expected.length &&crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));if (!ok) return res.status(401).end();const evt = JSON.parse(req.body.toString("utf8"));if (evt.event === "payment.completed") {// пометьте заказ оплаченным — ИДЕМПОТЕНТНО (ретраи возможны)markOrderPaid(evt.data.merchant_order_id);}res.json({ ok: true }); // отвечайте 2xx, иначе будут ретраи});
{"id": "wh_9aB3cD","event": "payment.completed","created_at": "2026-06-02T09:15:12Z","data": {"id": "pay_3kQ7v2","status": "COMPLETED","type": "invoice","amount": 1500,"currency": "KZT","payer_phone": "+77011234567","comment": "Заказ #1042","merchant_order_id": "order_1042","payment_link": null,"receipt_url": "https://kaspi.kz/receipt/...","created_at": "2026-06-02T09:14:00Z","updated_at": "2026-06-02T09:15:12Z"}}
data.id: один платёж может прислать несколько вебхуков, а статус иногда уточняется позже — например, при сверке с Kaspi ранее истёкший/неуспешный платёж может подтвердиться как payment.completed.Все типы событий — в справочнике событий.
Отмена платежа
Можно отменить платёж в статусе PENDING (до оплаты клиентом).
curl -X POST https://pay.1app.kz/v1/payments/pay_3kQ7v2/cancel \-H "Authorization: Bearer 1pay_live_xxx"
Возврат (полный и частичный)
Только по оплаченному платежу (COMPLETED). Укажите сумму — частями или всю. После полного возврата статус станет REFUNDED.
curl -X POST https://pay.1app.kz/v1/refunds \-H "Authorization: Bearer 1pay_live_xxx" \-H "Content-Type: application/json" \-d '{"payment_id":"pay_3kQ7v2","amount":500,"reason":"частичный возврат"}'
Проверка номера в Kaspi
Перед выставлением счёта можно проверить, зарегистрирован ли номер — меньше неуспешных оплат.
curl -X POST https://pay.1app.kz/v1/clients/check \-H "Authorization: Bearer 1pay_live_xxx" \-H "Content-Type: application/json" \-d '{"phone":"+77011234567"}'# → {"phone":"+77011234567","registered":true,"name":"И. Иванов"}
Идемпотентность
merchant_order_id— уникален в рамках мерчанта. Повтор с тем же id вернёт409 DUPLICATE.- Заголовок
Idempotency-Key— повтор с тем же ключом вернёт тот же платёж (200), не новый. Ставьте при ретраях запроса.
Полный пример — чекаут + вебхук (Node/Express)
import express from "express";import crypto from "crypto";const ONEPAY = "https://pay.1app.kz";const API_KEY = process.env.ONEPAY_API_KEY;const SECRET = process.env.ONEPAY_WEBHOOK_SECRET;const app = express();// 1) Создать платёж для заказаapp.post("/checkout", express.json(), async (req, res) => {const { orderId, phone, amount } = req.body;const r = await fetch(`${ONEPAY}/v1/payments`, {method: "POST",headers: {"Authorization": `Bearer ${API_KEY}`,"Content-Type": "application/json","Idempotency-Key": orderId,},body: JSON.stringify({ amount, payer_phone: phone, merchant_order_id: orderId }),});const payment = await r.json();if (!r.ok) return res.status(r.status).json(payment);res.json({ payment_id: payment.id });});// 2) Вебхук — узнаём об оплатеapp.post("/webhooks/1pay", express.raw({ type: "application/json" }), (req, res) => {const sig = req.get("X-Webhook-Signature") || "";const exp = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");if (sig.length !== exp.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(exp)))return res.status(401).end();const evt = JSON.parse(req.body.toString("utf8"));switch (evt.event) {case "payment.completed": markOrderPaid(evt.data.merchant_order_id); break;case "payment.refunded": recordRefund(evt.data.merchant_order_id); break;case "payment.cancelled":case "payment.expired": markOrderUnpaid(evt.data.merchant_order_id); break;}res.json({ ok: true });});app.listen(3000);
Платформа
Модель платформы
Для SaaS/маркетплейсов, которые подключают приём Kaspi своим клиентам так, что клиент не знает про 1pay. Платформа управляет суб-мерчантами, их кассирами и балансами через один серверный ключ.
- Платформа — ваш сервис с одним
platform-ключом. - Школа (суб-мерчант) — ваш клиент. Заводится по API, про 1pay не знает.
- Баланс комиссии — предоплата школы. Деньги учеников идут ей в Kaspi напрямую; вашу комиссию 1pay списывает с этого баланса. При нуле приём выключается.
Authorization: Bearer 1pay_platform_xxxxxxxxxxxx
Управление школами
Заводите школу с комиссией и опциональным начальным балансом. external_id — ваш id школы.
const res = await fetch("https://pay.1app.kz/platform/merchants", {method: "POST",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({name: "Школа Алмаз",external_id: "school_42",commission_rate: 3,initial_balance: 0,}),});const school = await res.json(); // school.id = "mer_..." — сохраните у себя
Ещё: GET /platform/merchants (список, ?external_id=), GET/PATCH /platform/merchants/:id (имя, ставка, active).
Онбординг кассира
Школа подключает Kaspi-кассир прямо в вашем UI — два шага:
const r = await fetch(`https://pay.1app.kz/platform/merchants/${schoolId}/devices`, {method: "POST",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({ name: "Касса", phone: "+7 7XX XXX XX XX" }),});const { device } = await r.json(); // device.id → кассиру пришёл SMS
await fetch(`https://pay.1app.kz/platform/merchants/${schoolId}/devices/${device.id}/otp`, {method: "POST",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({ otp: "1234" }),});// device.status = "ACTIVE" → школа готова принимать платежи
Баланс комиссии
Вы пополняете/корректируете баланс школы; 1pay автоматически списывает комиссию с каждого платежа.
// Пополнитьawait fetch(`https://pay.1app.kz/platform/merchants/${schoolId}/balance/topup`, {method: "POST",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({ amount: 5000, note: "апрель" }),});// Остатокconst b = await (await fetch(`https://pay.1app.kz/platform/merchants/${schoolId}/balance`,{ headers: { "Authorization": `Bearer ${PLATFORM_KEY}` } })).json();// { commission_rate: 3, commission_balance: 5000, accepting: true }
POST …/balance/adjust — ручная коррекция (+/−). GET …/balance/ledger — журнал (TOPUP / COMMISSION / ADJUST). При нуле баланса — 402 BALANCE_DEPLETED. Подпишитесь на merchant.depleted, чтобы авто-пополнять.
Платежи от имени школы
Деньги идут на Kaspi школы; комиссия списывается с её баланса.
// Счёт на телефонconst p = await (await fetch(`https://pay.1app.kz/platform/merchants/${schoolId}/payments`, {method: "POST",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({ amount: 4990, payer_phone: "+77011234567", merchant_order_id: "order_1" }),})).json();// p.id = "pay_..." p.status = "PENDING"// QR-ссылка (без номера телефона)const l = await (await fetch(`https://pay.1app.kz/platform/merchants/${schoolId}/payments/link`, {method: "POST",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({ amount: 4990, merchant_order_id: "order_2" }),})).json();// l.payment_link = "https://pay.kaspi.kz/pay/..."
Ещё: GET …/payments, GET …/payments/:id, POST …/payments/:id/cancel, POST …/refunds, POST …/clients/check.
Статистика
GET https://pay.1app.kz/platform/merchants/:id/stats # оборот, баланс, ставка, объём за сегодняGET https://pay.1app.kz/platform/stats # агрегат по всем школам платформы
Вебхук платформы
Один URL на всю платформу — события всех школ приходят сюда с merchant_id и merchant_external_id.
const { secret } = await (await fetch("https://pay.1app.kz/platform/webhook", {method: "PUT",headers: { "Authorization": `Bearer ${PLATFORM_KEY}`, "Content-Type": "application/json" },body: JSON.stringify({url: "https://api.example.com/webhooks/1pay",events: ["payment.completed", "payment.refunded", "merchant.depleted"],}),})).json(); // secret — сохраните для проверки подписи
{"id": "wh_...","event": "payment.completed","merchant_id": "mer_...","merchant_external_id": "school_42","data": { "id": "pay_...", "status": "COMPLETED", "amount": 4990, "merchant_order_id": "order_1" }}
Подпись — та же схема: X-Webhook-Signature: sha256=<hmac>. Код проверки — в разделе Вебхуки.
Полный пример Platform API (Node)
const API = "https://pay.1app.kz";const KEY = process.env.ONEPAY_PLATFORM_KEY;const h = { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" };// 1) Завести школуconst school = await (await fetch(`${API}/platform/merchants`,{ method: "POST", headers: h, body: JSON.stringify({ name: "Школа Алмаз", external_id: "school_42", commission_rate: 3 }) })).json();// 2) В UI школы: /devices → SMS → /devices/:id/otp → ACTIVE// 3) Пополнить балансawait fetch(`${API}/platform/merchants/${school.id}/balance/topup`,{ method: "POST", headers: h, body: JSON.stringify({ amount: 5000 }) });// 4) Платёж от имени школыconst pay = await (await fetch(`${API}/platform/merchants/${school.id}/payments`,{ method: "POST", headers: h, body: JSON.stringify({ amount: 4990, payer_phone: "+77011234567", merchant_order_id: "ord_1" }) })).json();// 5) На ваш платформенный вебхук прилетит payment.completed (merchant_external_id = "school_42")
Справочник
/v1/paymentsСоздать счёт на телефон
Выставляет счёт в Kaspi на указанный номер. Покупатель подтверждает оплату в приложении Kaspi. Тип платежа — invoice.
| Поле | Тип | Описание |
|---|---|---|
amount | number | Сумма в тенге (KZT). Укажите amount ИЛИ cart_items. |
cart_items | array | Позиции: [{ catalog_item_id|name, count, price?, nds_percentage? }]. Сумма считается из позиций. |
discount_percentage | number | Скидка на корзину, 1–99% (только с cart_items). |
payer_phoneобяз. | string | Телефон плательщика, формат +7XXXXXXXXXX. |
comment | string | Назначение платежа, видно покупателю. |
merchant_order_id | string | Ваш идентификатор заказа. Идемпотентность — повтор вернёт 409 DUPLICATE. |
metadata | object | Произвольные данные, вернутся в вебхуке. |
Запрос
curl -X POST https://pay.1app.kz/v1/payments \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \-H "Content-Type: application/json" \-d '{"amount": 1500,"payer_phone": "+77011234567","comment": "Заказ #1042","merchant_order_id": "order_1042"}'
Ответ · 201 Created
{"id": "pay_3kQ7v2","status": "PENDING","type": "invoice","amount": 1500,"currency": "KZT","payer_phone": "+77011234567","comment": "Заказ #1042","merchant_order_id": "order_1042","payment_link": null,"receipt_url": null,"created_at": "2026-06-02T09:14:00Z","updated_at": "2026-06-02T09:14:00Z"}
/v1/payments/linkСоздать платёжную ссылку (QR)
Создаёт платёжную ссылку / QR-токен Kaspi без привязки к номеру телефона. Тип платежа — link. Ссылка возвращается в поле payment_link.
| Поле | Тип | Описание |
|---|---|---|
amountобяз. | number | Сумма в тенге (KZT). |
comment | string | Назначение платежа. |
merchant_order_id | string | Ваш идентификатор заказа (идемпотентность). |
metadata | object | Произвольные данные. |
Запрос
curl -X POST https://pay.1app.kz/v1/payments/link \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \-H "Content-Type: application/json" \-d '{"amount": 4990,"comment": "Подписка Pro","merchant_order_id": "sub_771"}'
Ответ · 201 Created
{"id": "pay_8Lm2qX","status": "PENDING","type": "link","amount": 4990,"currency": "KZT","payer_phone": null,"comment": "Подписка Pro","merchant_order_id": "sub_771","payment_link": "https://pay.kaspi.kz/pay/abc123","receipt_url": null,"created_at": "2026-06-02T09:20:00Z","updated_at": "2026-06-02T09:20:00Z"}
/v1/payments/:idПолучить статус платежа
Возвращает текущее состояние платежа из базы 1pay. Статус обновляется поллером каждые 3 секунды.
Запрос
curl -X GET https://pay.1app.kz/v1/payments/pay_3kQ7v2 \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"id": "pay_3kQ7v2","status": "COMPLETED","type": "invoice","amount": 1500,"currency": "KZT","payer_phone": "+77011234567","comment": "Заказ #1042","merchant_order_id": "order_1042","payment_link": null,"receipt_url": "https://kaspi.kz/receipt/...","created_at": "2026-06-02T09:14:00Z","updated_at": "2026-06-02T09:15:12Z"}
/v1/payments/:id/cancelОтменить платёж
Отменяет платёж в статусе PENDING. Уже оплаченные платежи отменить нельзя — используйте возврат.
Запрос
curl -X POST https://pay.1app.kz/v1/payments/pay_3kQ7v2/cancel \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"id": "pay_3kQ7v2","status": "CANCELLED","type": "invoice","amount": 1500,"currency": "KZT","payer_phone": "+77011234567","merchant_order_id": "order_1042","created_at": "2026-06-02T09:14:00Z","updated_at": "2026-06-02T09:16:40Z"}
/v1/refundsСделать возврат
Возвращает средства по проведённому платежу. Поддерживается полный и частичный возврат: при полном возврате платёж переходит в REFUNDED, при частичном — в PARTIALLY_REFUNDED (возврат можно добрать позже, пока сумма возвратов меньше суммы платежа). Поле refunded_amount хранит суммарно возвращённое.
| Поле | Тип | Описание |
|---|---|---|
payment_idобяз. | string | ID платежа 1pay (pay_...). |
amountобяз. | number | Сумма возврата в тенге (целое), не больше остатка к возврату. |
Запрос
curl -X POST https://pay.1app.kz/v1/refunds \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \-H "Content-Type: application/json" \-d '{"payment_id": "pay_3kQ7v2","amount": 1500}'
Ответ · 200 OK
{"id": "pay_3kQ7v2","status": "REFUNDED","type": "invoice","amount": 1500,"currency": "KZT","payer_phone": "+77011234567","merchant_order_id": "order_1042","refunded_amount": 1500,"created_at": "2026-06-02T09:14:00Z","updated_at": "2026-06-02T10:02:00Z"}
/v1/paymentsСписок платежей
Возвращает платежи мерчанта с фильтром по статусу и пагинацией. Параметры query: status, merchant_order_id, page, limit (≤100).
Запрос
curl -X GET https://pay.1app.kz/v1/payments?status=COMPLETED&page=1&limit=20 \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"data": [ /* объекты платежей */ ],"page": 1,"page_size": 20,"total": 134,"total_pages": 7}
/v1/payments/:id/refundsВозвраты по платежу
Журнал возвратов (успешных и неуспешных) по конкретному платежу.
Запрос
curl -X GET https://pay.1app.kz/v1/payments/pay_3kQ7v2/refunds \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"data": [{"id": "ref_9aZ1","payment_id": "pay_3kQ7v2","amount": 500,"status": "COMPLETED","reason": "частичный возврат","error": null,"created_at": "2026-06-02T10:02:00Z"}]}
/v1/refundsЖурнал возвратов
Все возвраты мерчанта с пагинацией (query: page, limit ≤100).
Запрос
curl -X GET https://pay.1app.kz/v1/refunds?page=1&limit=20 \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"data": [ /* объекты возвратов */ ],"page": 1,"page_size": 20,"total": 12,"total_pages": 1}
/v1/clients/checkПроверить номер в Kaspi
Проверяет, зарегистрирован ли номер в Kaspi, до выставления счёта — снижает долю неуспешных платежей.
| Поле | Тип | Описание |
|---|---|---|
phoneобяз. | string | Телефон, формат +7XXXXXXXXXX. |
Запрос
curl -X POST https://pay.1app.kz/v1/clients/check \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \-H "Content-Type: application/json" \-d '{"phone": "+77011234567"}'
Ответ · 200 OK
{"phone": "+77011234567","registered": true,"name": "И. Иванов"}
/v1/subscriptionsСоздать подписку
Регулярное списание с номера клиента. Списания выполняются автоматически по расписанию; при неудаче — ретраи и льготный период (grace). События приходят в вебхуках subscription.*.
| Поле | Тип | Описание |
|---|---|---|
phone_numberобяз. | string | Номер клиента, +7XXXXXXXXXX. |
amountобяз. | number | Сумма каждого списания, ₸ (целое). |
billing_periodобяз. | string | DAILY | WEEKLY | BIWEEKLY | MONTHLY | QUARTERLY | YEARLY. |
billing_day | number | День списания 1–28 (для месячных периодов). |
bill_immediately | boolean | Списать первый платёж сразу. |
max_retry_attempts | number | Попыток до grace (1–10, по умолч. 3). |
retry_interval_hours | number | Интервал ретрая, ч (1–168, по умолч. 24). |
grace_period_days | number | Льготный период, дней (1–30, по умолч. 3). |
Запрос
curl -X POST https://pay.1app.kz/v1/subscriptions \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \-H "Content-Type: application/json" \-d '{"phone_number": "+77011234567","amount": 4990,"billing_period": "MONTHLY","billing_day": 5,"bill_immediately": true}'
Ответ · 201 Created
{"id": "sub_7Kp2","status": "ACTIVE","phone_number": "+77011234567","amount": 4990,"billing_period": "MONTHLY","billing_day": 5,"next_billing_at": "2026-06-02T10:30:00Z","failed_attempts": 0,"in_grace_period": false,"created_at": "2026-06-02T10:30:00Z"}
/v1/catalogКаталог товаров
Товары мерчанта для счетов с позициями (cart_items) и чеков. POST — создать товар (или пачку через {products:[...]}); также GET /v1/catalog (список, ?q= поиск), GET/PATCH/DELETE /v1/catalog/:id, GET /v1/catalog/units.
| Поле | Тип | Описание |
|---|---|---|
nameобяз. | string | Название товара. |
priceобяз. | number | Цена за единицу, ₸ (целое). |
unit | string | Единица измерения (шт, кг, услуга…). |
barcode | string | Штрихкод. |
ntin | string | Код маркировки. |
nds_percentage | number | НДС, %. |
Запрос
curl -X POST https://pay.1app.kz/v1/catalog \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx" \-H "Content-Type: application/json" \-d '{"name": "Кофе латте","price": 990,"unit": "шт","nds_percentage": 12}'
Ответ · 201 Created
{"id": "prod_4Xy","name": "Кофе латте","price": 990,"unit": "шт","nds_percentage": 12,"is_active": true,"created_at": "2026-06-02T12:00:00Z"}
/v1/payments/:id/receiptФискальный чек
Фискальный чек по оплаченному платежу (включите фискализацию в настройках). GET — получить чек; POST /v1/payments/:id/receipt — сформировать/дослать. Передача в Kaspi OFD — в процессе подключения; до этого чек в статусе PENDING.
Запрос
curl -X GET https://pay.1app.kz/v1/payments/pay_3kQ7v2/receipt \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"id": "rcpt_1a","payment_id": "pay_3kQ7v2","status": "PENDING","fiscal_id": null,"receipt_url": null,"payload": { "total": 1500, "items": [ /* позиции */ ] },"created_at": "2026-06-02T10:00:00Z","sent_at": null}
/v1/subscriptions/:id/pause | /resume | /cancelУправление подпиской
pause — приостановить, resume — возобновить (следующее списание планируется от момента возобновления), cancel — отменить навсегда. Также: GET /v1/subscriptions, GET /v1/subscriptions/:id, PUT /v1/subscriptions/:id, GET /v1/subscriptions/:id/invoices.
Запрос
curl -X POST https://pay.1app.kz/v1/subscriptions/sub_7Kp2/pause \-H "Authorization: Bearer 1pay_live_xxxxxxxxxxxx"
Ответ · 200 OK
{"id": "sub_7Kp2","status": "PAUSED","paused_at": "2026-06-02T11:00:00Z"}
Справочник
Коды ошибок
Ошибки возвращаются с HTTP-статусом и телом { "error": { "code", "message" } }.
| HTTP | Код | Описание |
|---|---|---|
| 400 | VALIDATION_ERROR | Некорректное тело запроса или параметры. |
| 401 | UNAUTHORIZED | Отсутствует или недействителен API-ключ. |
| 402 | SESSION_EXPIRED | Сессия устройства истекла — переавторизуйте устройство. |
| 403 | FORBIDDEN | Действие недоступно (например, не подтверждён email). |
| 404 | NOT_FOUND | Платёж или ресурс не найден. |
| 409 | DUPLICATE | merchant_order_id уже использован. |
| 422 | KASPI_ERROR | Kaspi отклонил операцию. |
| 429 | RATE_LIMITED | Слишком много запросов — повторите позже (см. заголовок Retry-After). |
| 500 | INTERNAL_ERROR | Внутренняя ошибка сервиса. |
Статусы платежей
PENDING | Создан, ждёт оплаты клиентом. |
COMPLETED | Оплачен. |
FAILED | Отклонён / ошибка оплаты. |
CANCELLED | Отменён мерчантом. |
EXPIRED | Истёк срок действия. |
PARTIALLY_REFUNDED | Возвращена часть суммы. |
REFUNDED | Возвращена вся сумма. |
События вебхуков
payment.completed | Оплачен (терминальный). |
payment.failed | Не прошёл. |
payment.cancelled | Отменён. |
payment.expired | Истёк срок. |
payment.refunded | Возврат выполнен. |
payment.refund_failed | Возврат не удался. |
subscription.payment_succeeded | Подписка: списание прошло. |
subscription.payment_failed | Подписка: списание не прошло (будет ретрай). |
subscription.grace_period_started | Подписка: исчерпаны попытки — начался grace. |
subscription.expired | Подписка: grace закончился без оплаты — остановлена. |
merchant.balance_low | Баланс комиссии ниже порога. |
merchant.depleted | Баланс комиссии исчерпан. |
Маппинг статусов Kaspi → 1pay
Поллер опрашивает Kaspi каждые ~3 с и нормализует статусы.
| Processed | COMPLETED |
| CancelledByUser, NotConfirmedByUser, Rejected, Error, Insufficient*, Iris* | FAILED |
| QrTokenDiscarded, Expired | EXPIRED |
| QrTokenCreated, Wait | PENDING |
| Processed | COMPLETED |
| RemotePaymentCanceled, RemotePaymentRejected | FAILED |
| Expired | EXPIRED |
| RemotePaymentCreated | PENDING |