EN RU

API Интеграции Мерчанта

Обзор

Данный документ описывает API для интеграции мерчантов с платежной платформой Kotleta. API позволяет создавать платежные заявки (pay-in), получать обновления статусов через вебхуки, проверять статусы платежей и управлять аккаунтом.

Продуктивный сервер: https://kotleta.best Тестовый сервер (Sandbox): https://deora2.tech


Авторизация

Получение доступов

Для начала интеграции необходимо:

  1. Запросить доступ к панели мерчанта у вашего менеджера.
  2. Создать магазин (если он не был создан для вас заранее).
  3. Получить API-ключ и Секретный ключ в настройках магазина.

Заголовки аутентификации

Все запросы к Merchant API должны содержать следующие заголовки:

Заголовок Описание
X-API-Key Ваш API-ключ мерчанта (формат: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
X-Signature Подпись запроса HMAC-SHA256 (см. ниже)
Content-Type application/json для JSON-запросов

Генерация подписи

Заголовок X-Signature представляет собой HMAC-SHA256 подпись, закодированную в Base64, вычисленную из конкатенации:

  1. HTTP-метод (GET, POST и т.д.)
  2. Полный URL запроса (включая query-параметры)
  3. Тело запроса (только для application/json запросов; пустая строка для GET-запросов)

Формула подписи:

X-Signature = Base64(HMAC-SHA256(secret_key, METHOD + URL + BODY))

Примеры кода

PHP:

<?php
$method = 'POST';
$url = 'https://kotleta.best/api/v1/payments';
$body = json_encode(['currency' => 'RUB', 'amount' => 5000]);
$secretKey = 'your_secret_key';

$stringToSign = $method . $url . $body;
$signature = base64_encode(hash_hmac('sha256', $stringToSign, $secretKey, true));

// Установите заголовок: X-Signature: $signature

JavaScript (Node.js):

const crypto = require('crypto');

const method = 'POST';
const url = 'https://kotleta.best/api/v1/payments';
const body = JSON.stringify({ currency: 'RUB', amount: 5000 });
const secretKey = 'your_secret_key';

const stringToSign = method + url + body;
const signature = crypto
  .createHmac('sha256', secretKey)
  .update(stringToSign)
  .digest('base64');

// Установите заголовок: X-Signature: <signature>

Python:

import hmac
import hashlib
import base64
import json

method = 'POST'
url = 'https://kotleta.best/api/v1/payments'
body = json.dumps({'currency': 'RUB', 'amount': 5000})
secret_key = 'your_secret_key'

string_to_sign = method + url + body
signature = base64.b64encode(
    hmac.new(
        secret_key.encode(),
        string_to_sign.encode(),
        hashlib.sha256
    ).digest()
).decode()

# Установите заголовок: X-Signature: <signature>

Host-to-Host интеграция

Host-to-Host интеграция обеспечивает прямой межсерверный обмен данными между бэкендом мерчанта и API платежной платформы, позволяя полностью автоматизировать обработку платежей.

Создание заявки на приём (Pay-In)

Процесс pay-in позволяет мерчантам принимать платежи от своих клиентов.

Общая схема

1. Сервер мерчанта  -> POST /api/v1/payments       -> Создание платежа, получение реквизитов
2. Мерчант          -> Показывает реквизиты клиенту -> Клиент переводит средства
3. Платформа        -> Обнаруживает перевод         -> Подтверждает платеж
4. Платформа        -> POST на callback мерчанта    -> Уведомление о смене статуса
5. Мерчант          -> GET /api/v1/payments/{id}    -> (Опционально) Проверка финального статуса

Шаг 1: Создание платежа

Мерчант отправляет запрос на создание платежа. Система маршрутизирует платеж к доступному трейдеру, выбирает подходящие реквизиты (номер карты или телефон СБП) и возвращает их в ответе.

Запрос:

POST /api/v1/payments
Content-Type: application/json
X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-Signature: <вычисленная_подпись>
{
  "currency": "RUB",
  "amount": 5000.00
}

Ответ (201 Created):

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "waiting_sms",
    "currency": "RUB",
    "amount": 5000.00,
    "amount_usdt": 52.63,
    "external_id": "ext-unique-id",
    "requisite": {
      "type": "card",
      "card_number": "2200 1234 5678 9012",
      "card_holder": "IVAN IVANOV",
      "bank_name": "Sberbank",
      "bank_code": "sberbank",
      "timer_seconds": 900
    },
    "expires_at": "2026-02-15T15:15:00Z",
    "created_at": "2026-02-15T15:00:00Z"
  }
}

Мерчант должен отобразить полученные реквизиты клиенту и указать точную сумму для перевода. Платеж истекает по прошествии timer_seconds (по умолчанию 15 минут).

Возможные типы реквизитов:

Шаг 2: Подтверждение платежа

После того как клиент выполнит перевод, платформа автоматически обнаруживает входящий платеж. Ручное подтверждение со стороны мерчанта не требуется — система обрабатывает обнаружение автоматически через свою внутреннюю сеть.

Шаг 3: Уведомление через вебхук

При подтверждении платежа платформа отправляет вебхук на настроенный callback_url мерчанта. Подробности в разделе Обратные вызовы (Вебхуки).

Создание заявки на выплату (Pay-Out)

Примечание: Функциональность выплат находится в разработке. Обратитесь к вашему менеджеру для уточнения сроков и раннего доступа.

Процесс pay-out позволит мерчантам отправлять средства на банковские счета или карты клиентов.


Обратные вызовы (Вебхуки)

Обзор

Платформа отправляет HTTP POST-уведомления на callback_url мерчанта при каждом изменении статуса платежа. URL для обратных вызовов настраивается в профиле мерчанта (не для каждого запроса отдельно).

Аутентификация

Каждый запрос вебхука содержит заголовок X-Signature, вычисленный с использованием секретного ключа мерчанта:

X-Signature = Base64(HMAC-SHA256(secret_key, "POST" + webhook_url + body))

Мерчант обязан проверять эту подпись, чтобы убедиться в подлинности вебхука и отсутствии подмены данных.

Формат данных вебхука

{
  "payment_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "external_id": "ext-unique-id",
  "status": "confirmed",
  "currency": "RUB",
  "amount": 5000.00,
  "amount_usdt": 52.63,
  "tx_id": "",
  "confirmed_at": "2026-02-15T15:05:30Z",
  "timestamp": "2026-02-15T15:05:31Z"
}

Описание полей вебхука

Поле Тип Описание
payment_id string (UUID) Уникальный идентификатор платежа в системе
external_id string Внешний идентификатор
status string Новый статус платежа (см. PaymentStatus)
currency string Валюта платежа (например, RUB)
amount number Сумма платежа в исходной валюте
amount_usdt number Сумма платежа в пересчёте на USDT
tx_id string ID транзакции в блокчейне (при завершении)
confirmed_at string (ISO 8601) Временная метка подтверждения
timestamp string (ISO 8601) Временная метка генерации вебхука

Ожидаемый ответ

Мерчант должен ответить HTTP-кодом 200 OK. Любой другой код считается ошибкой, и вебхук будет повторно отправлен.

Политика повторных попыток

Если сервер мерчанта не ответил кодом 200, платформа повторяет отправку с экспоненциальной задержкой:

Попытка Задержка
1 5 минут
2 15 минут
3 1 час
4 6 часов
5-10 24 часа

Максимум 10 попыток. После исчерпания лимита вебхук помечается как неудачный и может быть повторно отправлен вручную через панель управления или API.

Пример проверки подписи

PHP:

<?php
$secretKey = 'your_secret_key';
$webhookUrl = 'https://yoursite.com/webhook';
$body = file_get_contents('php://input');
$receivedSignature = $_SERVER['HTTP_X_SIGNATURE'];

$stringToSign = 'POST' . $webhookUrl . $body;
$expectedSignature = base64_encode(
    hash_hmac('sha256', $stringToSign, $secretKey, true)
);

if (!hash_equals($expectedSignature, $receivedSignature)) {
    http_response_code(403);
    exit('Invalid signature');
}

// Обработка вебхука...
http_response_code(200);

Python:

import hmac
import hashlib
import base64

secret_key = 'your_secret_key'
webhook_url = 'https://yoursite.com/webhook'
body = request.get_data(as_text=True)
received_signature = request.headers.get('X-Signature')

string_to_sign = 'POST' + webhook_url + body
expected_signature = base64.b64encode(
    hmac.new(
        secret_key.encode(),
        string_to_sign.encode(),
        hashlib.sha256
    ).digest()
).decode()

if not hmac.compare_digest(expected_signature, received_signature):
    return 'Invalid signature', 403

# Обработка вебхука...
return 'OK', 200

Справочник API

Создание платежа

Создает новую заявку на приём платежа и возвращает реквизиты для перевода.

Эндпоинт: POST /api/v1/payments

Аутентификация: API-ключ + Подпись

Заголовки запроса:

Заголовок Обязательный Описание
X-API-Key Да API-ключ мерчанта
X-Signature Да Подпись запроса
Content-Type Да application/json

Тело запроса:

Параметр Тип Обязательный Описание
currency string Да Код валюты, 3 символа (например, RUB, USD, EUR, THB)
amount number Да Сумма платежа (минимум: 100)

Пример запроса:

{
  "currency": "RUB",
  "amount": 5000.00
}

Ответ (201 Created):

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "waiting_sms",
    "currency": "RUB",
    "amount": 5000.00,
    "amount_usdt": 52.63,
    "external_id": "generated-uuid",
    "requisite": {
      "type": "card",
      "card_number": "2200 1234 5678 9012",
      "card_holder": "IVAN IVANOV",
      "bank_name": "Sberbank",
      "bank_code": "sberbank",
      "timer_seconds": 900
    },
    "expires_at": "2026-02-15T15:15:00Z",
    "created_at": "2026-02-15T15:00:00Z"
  }
}

Ответы с ошибками:

Код Описание
400 Некорректное тело запроса, отсутствуют обязательные поля или не настроен callback URL
401 Неверный или отсутствующий API-ключ, или неверная подпись
500 Внутренняя ошибка сервера (нет доступных трейдеров/реквизитов)

Получение платежа по ID

Возвращает текущий статус и детали платежа.

Эндпоинт: GET /api/v1/payments/{id}

Аутентификация: API-ключ + Подпись

Параметры URL:

Параметр Тип Описание
id string (UUID) Идентификатор платежа

Ответ (200 OK):

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "confirmed",
    "currency": "RUB",
    "amount": 5000.00,
    "amount_usdt": 52.63,
    "external_id": "generated-uuid",
    "created_at": "2026-02-15T15:00:00Z",
    "updated_at": "2026-02-15T15:05:30Z"
  }
}

Ответы с ошибками:

Код Описание
400 Некорректный формат ID платежа
404 Платеж не найден

Получение платежей мерчанта

Возвращает постраничный список платежей мерчанта.

Эндпоинт: GET /api/v1/merchants/{merchant_id}/payments

Аутентификация: JWT Bearer Token

Параметры URL:

Параметр Тип Описание
merchant_id string (UUID) Идентификатор мерчанта

Query-параметры:

Параметр Тип По умолчанию Описание
page integer 1 Номер страницы
page_size integer 20 Элементов на странице (максимум: 100)

Ответ (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": "confirmed",
      "currency": "RUB",
      "amount": 5000.00,
      "amount_usdt": 52.63,
      "external_id": "generated-uuid",
      "created_at": "2026-02-15T15:00:00Z"
    }
  ],
  "pagination": {
    "total": 150,
    "page": 1,
    "page_size": 20,
    "total_pages": 8
  }
}

Управление вебхуками

Эндпоинты для мониторинга и управления доставкой вебхуков.

Аутентификация: JWT Bearer Token

Статистика вебхуков

Эндпоинт: GET /api/v1/merchant/webhooks/stats

Ответ:

{
  "success": true,
  "data": {
    "pending": 2,
    "processing": 0,
    "completed": 145,
    "failed": 3
  }
}

Список неудачных вебхуков

Эндпоинт: GET /api/v1/merchant/webhooks/failed

Повторная отправка вебхука

Эндпоинт: POST /api/v1/merchant/webhooks/{id}/retry

Детали вебхука

Эндпоинт: GET /api/v1/merchant/webhooks/{id}


Описание объектов API

PaymentStatus

Статус Описание
created Платеж создан, идёт назначение трейдера
waiting_sms Реквизиты назначены, ожидание перевода от клиента
confirmed Платеж подтверждён — средства получены и проверены
completed Платеж полностью завершён — расчёт произведён
failed Платеж не удался на любом этапе обработки
expired Платеж не завершён в установленный срок (по умолчанию: 15 мин)

PaymentResponse

Поле Тип Описание
id string (UUID) Уникальный идентификатор платежа
status PaymentStatus Текущий статус платежа
currency string Код валюты платежа (например, RUB)
amount number Сумма платежа в исходной валюте
amount_usdt number Сумма платежа в пересчёте на USDT
external_id string Внешний идентификатор
requisite RequisiteDTO Реквизиты для перевода (при статусе waiting_sms)
expires_at string (ISO 8601) Время истечения платежа
created_at string (ISO 8601) Время создания платежа

RequisiteDTO

Поле Тип Описание
type string Тип реквизитов: card или sbp
phone_number string Номер телефона СБП (для типа sbp)
card_number string Номер банковской карты (для типа card)
card_holder string Имя держателя карты (для типа card)
bank_name string Название банка
bank_code string Код банка
timer_seconds integer Время в секундах до истечения платежа

WebhookPayload

Поле Тип Описание
payment_id string (UUID) Идентификатор платежа
external_id string Внешний идентификатор
status PaymentStatus Обновлённый статус платежа
currency string Валюта платежа
amount number Сумма в исходной валюте
amount_usdt number Сумма в USDT
tx_id string Хеш транзакции в блокчейне (при завершении)
confirmed_at string (ISO 8601) Время подтверждения
timestamp string (ISO 8601) Время генерации вебхука

Обработка ошибок

Формат ответа

Все ответы с ошибками имеют единый формат:

{
  "success": false,
  "error": "Описание ошибки"
}

HTTP-коды статуса

Код Описание
200 Успех
201 Успешно создано
400 Некорректный запрос — неверные параметры или нарушение бизнес-логики
401 Не авторизован — неверный или отсутствующий API-ключ / подпись
404 Не найдено — запрошенный ресурс не существует
409 Конфликт — дублирующий запрос (идемпотентность)
500 Внутренняя ошибка сервера

Типичные сообщения об ошибках

Ошибка Причина
Invalid request body Некорректный JSON или отсутствуют обязательные поля
currency must be 3 characters Код валюты не в формате ISO 4217
Merchant not authenticated Отсутствующий или неверный заголовок X-API-Key
Invalid signature X-Signature не совпадает с вычисленным значением
Merchant has no callback URL configured В профиле мерчанта не указан callback_url
Payment not found or already processed Платеж не найден или находится в терминальном статусе
Payment is not waiting for SMS confirmation Платеж в неожиданном статусе

Поддерживаемые валюты

Код Валюта
RUB Российский рубль
USD Доллар США
EUR Евро
THB Тайский бат

Примечание: Доступные валюты зависят от конфигурации трафик-группы мерчанта. Обратитесь к вашему менеджеру для активации.


Лимиты запросов

API-запросы ограничены по частоте для каждого мерчанта. Лимиты по умолчанию:

Эндпоинт Лимит
POST /payments 60 запросов/минута
GET /payments/* 120 запросов/минута

При превышении лимитов возвращается HTTP 429 (Too Many Requests).


Тестирование и Sandbox

Для тестирования интеграции используйте sandbox-окружение по адресу https://deora2.tech. Тестовые API-ключи имеют префикс sk_test_.

Все процессы работают идентично продуктивной среде, но реальное движение средств не происходит.