/accountПроверить ключ и получить бизнес
Любой ключБыстрый старт
Подключите свой сайт к платежам FastPay. Начните с тестового ключа — без реальных оплат.
В разделе «Интеграции» выберите тестовый режим и права payments:read и payments:write.
Задайте FASTPAY_API_KEY в переменных окружения. Для FASTPAY_BASE_URL используйте адрес FastPay, например https://fastpay.ink.
Запрос ниже вернёт бизнес и эффективный режим этого ключа. Он не создаёт платежей.
curl "$FASTPAY_BASE_URL/api/v1/account" \
-H "Authorization: Bearer $FASTPAY_API_KEY"Примеры только копируются. Эта страница не отправляет API-запросы.
Доступ
Передавайте ключ в заголовке Authorization: Bearer …. Ключ привязан к бизнесу и режиму, выбранному при создании.
Эффективный режим будет тестовым, если тестовый режим выбран у ключа или у кабинета. Реальный запрос в Kaspi возможен только тогда, когда и ключ, и кабинет работают в боевом режиме. Поля keyEnvironment, workspaceMode и effectiveMode возвращаются методом GET /api/v1/account.
Полный ключ показывается один раз. Если потеряли его — замените в кабинете и обновите на сервере. Старый ключ перестанет работать.
Создание
Отправьте POST /api/v1/payments с правом payments:write. Сумма передаётся в тенге, не в тиынах.
curl -X POST "$FASTPAY_BASE_URL/api/v1/payments" \
-H "Authorization: Bearer $FASTPAY_API_KEY" \
-H "Idempotency-Key: order-42-attempt-1" \
-H "Content-Type: application/json" \
-d '{
"method": "qr",
"amount": 100,
"currency": "KZT",
"externalOrderId": "ORDER-42"
}'methodОбязательно. qr — QR-код; invoice — счёт на телефон.
amountОбязательно. Число больше 0, максимум 999 999 999.
customerPhoneДля invoice — номер без пробелов и «+», например 77001234567.
externalOrderIdВаш номер заказа, до 200 символов. Не заменяет заголовок идемпотентности.
Ответ содержит data.id и data.status. При создании QR также возвращается data.qrCodeDataUrl.
Для создания платежа и возврата обязателен Idempotency-Key длиной 8–200 символов. При повторе того же запроса передавайте тот же ключ. Срок хранения — 24 часа.
Тестовый режим
Тестовый QR открывает безопасную страницу FastPay и сам не меняет статус. Задайте результат через API или в деталях платежа в кабинете. Ни один из этих шагов не обращается в Kaspi.
Выполните запрос из раздела выше и сохраните data.id как PAYMENT_ID.
Передайте один из результатов: paid, failed, expired или cancelled.
Получите платёж через API и убедитесь, что вебхук принял соответствующее событие.
После результата paid верните тестовую сумму без подключения Kaspi.
curl -X POST "$FASTPAY_BASE_URL/api/v1/payments/PAYMENT_ID/simulate-status" \
-H "Authorization: Bearer $FASTPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"paid"}'curl -X POST "$FASTPAY_BASE_URL/api/v1/payments/PAYMENT_ID/refunds" \
-H "Authorization: Bearer $FASTPAY_API_KEY" \
-H "Idempotency-Key: refund-order-42-attempt-1" \
-H "Content-Type: application/json" \
-d '{"amount":100}'Тестовый ключ не может вернуть реальный платёж. Уже созданный тестовый платёж остаётся тестовым, даже если позже переключить кабинет в боевой режим.
Результат
Замените PAYMENT_ID на data.id созданного платежа.
curl "$FASTPAY_BASE_URL/api/v1/payments/PAYMENT_ID" \
-H "Authorization: Bearer $FASTPAY_API_KEY"created, requires_customer_action, pending
paid
failed, expired, cancelled
unknown не подтверждает оплату — дождитесь уточнения. Возвраты: partially_refunded или refunded.
Полный сценарий имитации оплаты и возврата приведён в разделе «Тестовый цикл».
Уведомления
Добавьте webhook URL в настройках ключа. FastPay отправляет на него POST с событием и данными платежа. Сохраните отдельный секрет подписи webhook на сервере.
X-Webhook-Timestamp и подпись X-Webhook-Signature по исходному телу запроса.X-Webhook-Id для защиты от повторов.2xx.import { createHmac, timingSafeEqual } from 'node:crypto';
// rawBody is the original body Buffer, before JSON.parse.
export function verifyWebhook(headers, rawBody, secret) {
const timestamp = headers['x-webhook-timestamp'];
const signature = headers['x-webhook-signature'];
if (typeof timestamp !== 'string' ||
typeof signature !== 'string' ||
!/^\d+$/.test(timestamp) ||
!/^sha256=[a-f0-9]{64}$/.test(signature)) return false;
// A five-minute window is the receiver policy.
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300)
return false;
const expected = 'sha256=' + createHmac('sha256', secret)
.update(timestamp + '.').update(rawBody).digest('hex');
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Подпись: sha256= + hex HMAC-SHA256 от timestamp + "." + rawBody. Не вычисляйте подпись по повторно сериализованному JSON. X-Webhook-Delivery обозначает доставку, а не уникальное событие.
Отладка
400Проверьте обязательные поля и формат значений.
401 / 403Проверьте ключ, его режим и разрешения.
404Объект не найден в бизнесе, которому принадлежит ключ.
409Конфликт состояния или тот же Idempotency-Key с другим содержимым запроса.
502Операция не завершилась у провайдера. Проверьте статус платежа перед повтором.
Ответ ошибки содержит error и может содержать requestId. Сохраните requestId для разбора ошибки; API-ключ в логи не записывайте.
API v1
Общий префикс — /api/v1. Полные схемы запросов и ответов — в OpenAPI.
/accountПроверить ключ и получить бизнес
Любой ключ/paymentsСоздать QR или счёт на телефон
payments:write/paymentsСписок платежей
payments:read/payments/{id}Статус платежа
payments:read/payments/{id}Изменить внутреннюю заметку
payments:write/payments/{id}/cancelОтменить ожидающий счёт на телефон
payments:write/payments/{id}/refundsОформить возврат
payments:write/payments/{id}/simulate-statusИзменить статус в тестовом режиме
payments:write/subscriptionsСписок расписаний
payments:read/subscriptionsСоздать расписание счетов
payments:write/subscriptions/{id}Получить расписание
payments:read/subscriptions/{id}Изменить расписание
payments:write/subscriptions/{id}/pauseПриостановить расписание
payments:write/subscriptions/{id}/resumeВозобновить расписание
payments:write/subscriptions/{id}/cancelОтменить расписание
payments:write/subscriptions/{id}/invoicesСчета по расписанию
payments:readМетоды не найдены. Попробуйте другой запрос.