API для разработчиков
Обзор API
Quantum Payouts предоставляет REST API для интеграции с внешними системами. API позволяет создавать выплаты, отслеживать их статус и получать информацию о возможностях системы.
Основные возможности
- Создание выплат - регистрация выплаты с получением ссылки на страницу указания реквизитов
- Отслеживание статуса - получение актуальной информации о состоянии выплаты
- Информация о системе - получение доступных функций и ограничений
- Безопасная авторизация - использование Bearer токенов для аутентификации
Базовый URL
https://payouts-dev.quantumlabs.ru/api/v1/
Формат данных
- Запросы: JSON (Content-Type: application/json; charset=UTF-8)
- Ответы: JSON (Accept: application/json; version=1.0)
- Кодировка: UTF-8
- Суммы: в копейках (например, 150000 = 1500.00 рублей)
Авторизация
Все API запросы требуют авторизации с использованием Bearer токена.
Получение API токена
- Войдите в личный кабинет
- Перейдите в Настройки → API
- Нажмите "Создать API токен"
- Скопируйте сгенерированный токен
- Сохраните токен в безопасном месте
Использование токена
Authorization: Bearer YOUR_API_TOKEN
⚠️ Безопасность: Никогда не передавайте API токен в URL параметрах или в незащищенном виде. Используйте только HTTPS соединения.
Создание выплаты
Эндпоинт для регистрации новой выплаты и получения ссылки на страницу указания реквизитов.
Параметры запроса
Требуемые заголовки:Authorization: Bearer YOUR_API_TOKEN
,Accept: application/json; version=1.0
,Content-Type: application/json; charset=UTF-8
.
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
orderNumber |
String | Да | Уникальный идентификатор выплаты (до 36 символов) |
amount |
Integer | Да | Сумма в копейках (до 12 цифр) |
urls |
Object | Да | Контейнер ссылок для редиректов |
urls.returnUrl |
String | Да | URL для перенаправления при успехе |
urls.failUrl |
String | Нет | URL для перенаправления при ошибке |
description |
String | Нет | Описание выплаты |
sessionTimeoutSecs |
Integer | Нет | Время жизни сессии в секундах (по умолчанию 600) |
type |
String | Нет | Тип выплаты: "card" или "sbp" или не отправлять его. |
Пример запроса
curl -X POST 'https://payouts-dev.quantumlabs.ru/api/v1/createPayout' \
-H 'Content-Type: application/json; charset=UTF-8' \
-H 'Accept: application/json; version=1.0' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-d '{
"orderNumber": "ORDER_12345",
"amount": 150000,
"description": "Выплата по заказу #12345",
"sessionTimeoutSecs": 1800,
"type": "card",
"urls": {
"returnUrl": "https://your-site.com/success",
"failUrl": "https://your-site.com/fail"
}
}'
Параметры ответа
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
result.error |
String | Да | Код ошибки ("0" = успех) |
result.message |
String | Да | Сообщение об ошибке (null при успехе) |
payoutUrl |
String | Да | Ссылка на страницу указания реквизитов |
orderId |
String | Да | Внутренний идентификатор заказа |
orderNumber |
String | Да | Номер заказа из запроса |
Пример успешного ответа
{
"result": {
"error": "0",
"message": null
},
"payoutUrl": "https://payouts-dev.quantumlabs.ru/static/payout.php?payout_id=123&token=abc123",
"orderId": "PAY_2024_12_19_abc123",
"orderNumber": "ORDER_12345"
}
Пример ошибочного ответа
{
"result": {
"error": "VALIDATION_ERROR",
"message": "urls.returnUrl is required; amount must be positive"
}
}
Выполнение выплаты
Эндпоинт для немедленного выполнения одиночной выплаты на карту. Заявка создается и отправляется в банк в рамках одного запроса.
Параметры запроса
Требуемые заголовки:Authorization: Bearer YOUR_API_TOKEN
,Accept: application/json; version=1.0
,Content-Type: application/json; charset=UTF-8
.
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
orderNumber |
String | Да | Уникальный идентификатор выплаты (до 32 символов). Идемпотентность по связке (user, orderNumber). |
amount |
Integer | Да | Сумма в копейках (до 12 цифр). Пример: 150000 = 1500.00 ₽ |
description |
String | Да | Описание операции (до ~600 символов) |
target |
Object | Да | Контейнер реквизитов получателя |
target.pan |
String | Да | Номер карты получателя (13–19 цифр) |
Пример запроса
curl -X POST 'https://payouts-dev.quantumlabs.ru/api/v1/performPayout' \
-H 'Content-Type: application/json; charset=UTF-8' \
-H 'Accept: application/json; version=1.0' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-d '{
"orderNumber": "ORDER_12345",
"amount": 150000,
"description": "Разовая выплата",
"target": {
"pan": "4111111111111111"
}
}'
Параметры ответа
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
result |
Object | Да | Блок статуса выполнения запроса |
result.error |
String | Да | Код ошибки ("0" = успех) |
result.message |
String | Да | Сообщение об ошибке (null при успехе) |
target |
Object | Нет | Информация о реквизитах (при наличии) |
target.maskedPan |
String | Да | Маскированный номер карты |
orderNumber |
String | Да | Идентификатор заказа |
orderStatus |
String | Да | Статус заказа (created, processing, completed, failed) |
amount |
Integer | Да | Сумма в копейках |
creationDate |
Integer | Да | Unix timestamp создания |
orderId |
String | Да | Банковский код заказа (если есть) |
Пример успешного ответа
{
"result": { "error": "0", "message": null },
"orderNumber": "ORDER_12345",
"orderStatus": "processing",
"amount": 150000,
"creationDate": 1737097200,
"orderId": "BANK_ORDER_CODE_OPTIONAL",
"target": { "maskedPan": "411111******1111" }
}
Пример ошибочного ответа
{
"result": {
"error": "VALIDATION_ERROR",
"message": "orderNumber is required; amount must be greater than 0"
}
}
Получение статуса выплаты
Эндпоинт для получения актуальной информации о состоянии выплаты.
Параметры запроса
Требуемые заголовки:Authorization: Bearer YOUR_API_TOKEN
,Accept: application/json; version=1.0
,Content-Type: application/json; charset=UTF-8
.
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
orderNumber |
String | Да | Идентификатор выплаты (до 32 символов) |
Пример запроса
curl -X POST 'https://payouts-dev.quantumlabs.ru/api/v1/getPayoutStatus' \
-H 'Content-Type: application/json; charset=UTF-8' \
-H 'Accept: application/json; version=1.0' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-d '{
"orderNumber": "ORDER_12345"
}'
Параметры ответа
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
result |
Object | Да | Блок статуса выполнения запроса |
result.error |
String | Да | Код ошибки ("0" = успех) |
result.message |
String | Да | Сообщение об ошибке (null при успехе) |
target |
Object | Нет | Информация о реквизитах (при наличии) |
target.maskedPan |
String | Да | Маскированный номер карты (для карточных выплат) |
target.maskedPhone |
String | Нет | Маскированный номер телефона (для СБП выплат) |
orderNumber |
String | Да | Идентификатор заказа |
orderStatus |
String | Да | Статус заказа (created, processing, completed, failed) |
amount |
Integer | Да | Сумма в копейках |
creationDate |
Integer | Да | Unix timestamp создания |
orderId |
String | Да | Банковский код заказа (если есть) |
Пример успешного ответа
{
"result": {
"error": "0",
"message": null
},
"orderStatus": "success",
"orderNumber": "ORDER_12345",
"amount": 150000,
"currency": "RUB"
}
Пример ошибочного ответа
{
"result": {
"error": "PAYOUT_NOT_FOUND",
"message": "Payout with this orderNumber not found"
}
}
Webhook
Статический webhook для уведомлений о событиях (например, об изменении статуса выплаты). Настройка выполняется в ЛК → Настройки → Webhook.
Формат события
{
"event": "payout.status_changed",
"eventId": "2f4b1b0a0c2a4d32b2b0c9d311e7e59b",
"occurredAt": "2025-09-15T19:40:21+03:00",
"payout": {
"id": 123456,
"externalId": "INV-2025-0001",
"status": "SUCCESS",
"amount": 12345,
"currency": "RUB"
}
}
- amount — сумма в копейках (минимальные единицы валюты)
- occurredAt — ISO8601 (Europe/Moscow)
Заголовки
Content-Type: application/json
X-Payouts-Event
X-Payouts-Event-Id
X-Payouts-Timestamp
X-Payouts-Signature
(опционально):sha256=<hex>
Проверка подписи (опционально)
Алгоритм расчёта подписи
Подпись рассчитывается по алгоритму HMAC-SHA256 следующим образом:
- Исходные данные: берём сырое тело HTTP-запроса (raw body) в том виде, как оно было отправлено
- Нормализация JSON: применяем JSON minify к телу запроса (удаляем пробелы, переносы строк, табуляции)
- Секретный ключ: используем секрет, сгенерированный в настройках webhook
- Алгоритм хеширования: применяем HMAC-SHA256 к нормализованному JSON с использованием секрета
- Формат результата: получаем шестнадцатеричную строку и добавляем префикс
sha256=
- Сравнение: сравниваем полученную подпись с заголовком
X-Payouts-Signature
с использованием безопасного сравнения строк
Пошаговый пример расчёта подписи
Рассмотрим пример с тестовым webhook'ом:
1. Исходное тело запроса (как отправлено):
{
"event": "payout.status_changed",
"eventId": "2f4b1b0a0c2a4d32b2b0c9d311e7e59b",
"occurredAt": "2025-09-15T19:40:21+03:00",
"payout": {
"id": 123456,
"externalId": "INV-2025-0001",
"status": "SUCCESS",
"amount": 12345,
"currency": "RUB"
}
}
2. Нормализованный JSON (после minify):
{"event":"payout.status_changed","eventId":"2f4b1b0a0c2a4d32b2b0c9d311e7e59b","occurredAt":"2025-09-15T19:40:21+03:00","payout":{"id":123456,"externalId":"INV-2025-0001","status":"SUCCESS","amount":12345,"currency":"RUB"}}
3. Секретный ключ (пример):
sk_test_1234567890abcdef1234567890abcdef12345678
4. HMAC-SHA256 расчёт:
HMAC-SHA256(
"sk_test_1234567890abcdef1234567890abcdef12345678",
"{\"event\":\"payout.status_changed\",\"eventId\":\"2f4b1b0a0c2a4d32b2b0c9d311e7e59b\",\"occurredAt\":\"2025-09-15T19:40:21+03:00\",\"payout\":{\"id\":123456,\"externalId\":\"INV-2025-0001\",\"status\":\"SUCCESS\",\"amount\":12345,\"currency\":\"RUB\"}}"
) = "d923ed84eac76c985b045b003649c60ca6884bd1d415fcca16f9f83d1ef127a2"
5. Итоговая подпись:
sha256=d923ed84eac76c985b045b003649c60ca6884bd1d415fcca16f9f83d1ef127a2
Примеры кода для проверки подписи
PHP:
$raw = file_get_contents('php://input');
$normalized = json_encode(json_decode($raw), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$sig = $_SERVER['HTTP_X_PAYOUTS_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $normalized, $yourSecret);
if (!hash_equals($expected, $sig)) { http_response_code(401); exit; }
Node.js:
const crypto = require('crypto');
const rawBody = req.rawBody; // unmodified body
const normalized = JSON.stringify(JSON.parse(rawBody));
const signature = req.get('X-Payouts-Signature') || '';
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(normalized).digest('hex');
if (!timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.status(401).end();
}
Повторы доставки
0s → 15s → 30s → 60s → 5m → 15m → 30m → 60m → 120m → 180m до первого HTTP 2xx. Тестовая отправка — 1 попытка.
Требования к обработчику
- Возвращать HTTP 2xx при успехе
- Долгие операции выносить в очередь и отвечать 200 сразу
- Таймаут ожидания ответа ~10 секунд
Идемпотентность и безопасность
- Используйте
eventId
для защиты от повторной обработки - Требуется HTTPS; рекомендуем включить подпись
Возможности системы
Эндпоинт для получения информации о доступных функциях и ограничениях системы.
Параметры запроса
Требуемые заголовки:Authorization: Bearer YOUR_API_TOKEN
,Accept: application/json; version=1.0
.
Пример запроса
curl -X GET 'https://payouts-dev.quantumlabs.ru/api/v1/features' \
-H 'Accept: application/json; version=1.0' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
Параметры ответа
Параметр | Тип | Обязательный | Описание |
---|---|---|---|
system |
String | Да | Название системы ("payouts") |
environment |
String | Да | Окружение (development, uat, production) |
version |
String | Да | Версия API ("v1") |
timestamp |
Integer | Да | Unix timestamp ответа |
features |
Object | Да | Набор флагов доступности функционала (см. детальное описание ниже) |
result.error |
String | Да | Код ошибки ("0" = успех) |
result.message |
String | Да | Сообщение об ошибке (null при успехе) |
Детальное описание объекта features
Поле | Тип | Обязательный | Описание |
---|---|---|---|
single_payout |
Boolean | Да | Доступность API для одиночных выплат (всегда true для пользователей с валидным токеном) |
batch_processing |
Boolean | Да | Доступность пакетной обработки выплат через файлы (всегда true) |
bearer_auth |
Boolean | Да | Поддержка авторизации по Bearer токену (всегда true) |
card_payouts |
Boolean | Да | Доступность выплат на банковские карты (зависит от настроек клиента и наличия client_id/client_secret) |
sbp_payouts |
Boolean | Да | Доступность выплат через СБП (зависит от настроек клиента и наличия sbp_client_id/sbp_client_secret) |
file_download |
Boolean | Да | Доступность скачивания файлов с результатами выплат (зависит от прав пользователя) |
Пример успешного ответа
{
"system": "payouts",
"environment": "production",
"version": "v1",
"timestamp": 1737097200,
"features": {
"single_payout": true,
"batch_processing": true,
"bearer_auth": true,
"card_payouts": false,
"sbp_payouts": false,
"file_download": false
},
"result": { "error": "0", "message": null }
}
Пример ошибочного ответа
{
"result": {
"error": "UNAUTHORIZED",
"message": "Invalid or missing Bearer token"
}
}
Примеры интеграции
Python
import requests
class PayoutsAPI:
def __init__(self, api_token, base_url='https://payouts-dev.quantumlabs.ru/api/v1'):
self.api_token = api_token
self.base_url = base_url
self.headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Accept': 'application/json; version=1.0',
'Authorization': f'Bearer {api_token}'
}
def create_payout(self, order_number, amount, return_url, description=None, payout_type='card'):
data = {
'orderNumber': order_number,
'amount': amount,
'urls': {'returnUrl': return_url},
'type': payout_type
}
if description:
data['description'] = description
response = requests.post(f'{self.base_url}/createPayout', json=data, headers=self.headers)
return response.json()
def get_payout_status(self, order_number):
params = {'orderNumber': order_number}
response = requests.get(f'{self.base_url}/getPayoutStatus', params=params, headers=self.headers)
return response.json()
# Использование
api = PayoutsAPI('your_token_here')
result = api.create_payout('ORDER_001', 100000, 'https://example.com/success')
print(result)
PHP
class PayoutsAPI {
private $apiToken;
private $baseUrl;
public function __construct($apiToken, $baseUrl = 'https://payouts-dev.quantumlabs.ru/api/v1') {
$this->apiToken = $apiToken;
$this->baseUrl = $baseUrl;
}
public function createPayout($orderNumber, $amount, $returnUrl, $description = null, $type = 'card') {
$data = [
'orderNumber' => $orderNumber,
'amount' => $amount,
'urls' => ['returnUrl' => $returnUrl],
'type' => $type
];
if ($description) {
$data['description'] = $description;
}
return $this->makeRequest('POST', '/createPayout', $data);
}
private function makeRequest($method, $endpoint, $data = null) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $this->baseUrl . $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json; charset=UTF-8',
'Accept: application/json; version=1.0',
'Authorization: Bearer ' . $this->apiToken
]
]);
if ($data && $method !== 'GET') {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
}
// Использование
$api = new PayoutsAPI('your_token_here');
$result = $api->createPayout('ORDER_001', 100000, 'https://example.com/success');
var_dump($result);
JavaScript/Node.js
const axios = require('axios');
class PayoutsAPI {
constructor(apiToken, baseUrl = 'https://payouts-dev.quantumlabs.ru/api/v1') {
this.apiToken = apiToken;
this.baseUrl = baseUrl;
this.headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Accept': 'application/json; version=1.0',
'Authorization': `Bearer ${apiToken}`
};
}
async createPayout(orderNumber, amount, returnUrl, description = null, type = 'card') {
const data = {
orderNumber,
amount,
urls: { returnUrl },
type
};
if (description) {
data.description = description;
}
try {
const response = await axios.post(`${this.baseUrl}/createPayout`, data, { headers: this.headers });
return response.data;
} catch (error) {
throw new Error(`API Error: ${error.response?.data || error.message}`);
}
}
}
// Использование
const api = new PayoutsAPI('your_token_here');
api.createPayout('ORDER_001', 100000, 'https://example.com/success')
.then(result => console.log(result))
.catch(error => console.error(error));
Обработка ошибок
API использует стандартные HTTP коды статуса для индикации успеха или ошибки запроса.
Коды ошибок
HTTP код | Код ошибки | Описание |
---|---|---|
400 | VALIDATION_ERROR | Ошибка валидации входных данных |
401 | UNAUTHORIZED | Неверный или отсутствующий Bearer токен |
403 | PERMISSION_DENIED | Недостаточно прав для выполнения операции |
500 | INTERNAL_ERROR | Внутренняя ошибка сервера |
Лучшие практики
Безопасность
- Используйте HTTPS - никогда не отправляйте API токены по незащищенному соединению
- Храните токены безопасно - используйте переменные окружения
- Ротация токенов - регулярно обновляйте API токены
Производительность
- Соблюдайте лимиты - не превышайте 30 запросов в секунду
- Используйте таймауты - устанавливайте разумные таймауты для HTTP запросов
- Повторные попытки - реализуйте exponential backoff для повторов
Надежность
- Обработка ошибок - всегда проверяйте коды ответов
- Идемпотентность - используйте уникальные orderNumber
- Логирование - логируйте все API запросы и ответы