Выплаты

Подписанные запросы

Эндпоинты выплат требуют усиленную авторизацию: помимо X-Api-Key каждый запрос подписывается секретом по HMAC-SHA256.

В отличие от приёма платежей (где достаточно X-Api-Key), вывод средств — операция повышенного риска. Поэтому запросы POST /integration/payouts и GET /integration/payouts/{uuid} нужно подписывать.

Заголовки

ПолеТипОписание
X-Api-Keyобяз.stringAPI-ключ мерчанта (pk_…).
X-Timestampобяз.stringUnix-время в секундах на момент запроса.
X-Signatureобяз.stringHMAC-SHA256 в hex от строки подписи (см. ниже).

Строка подписи

Соедините четыре части символом перевода строки \n:

{timestamp}\n
{METHOD}\n
{path}\n
{sha256_hex(raw_body)}
  • timestamp — то же значение, что в заголовке X-Timestamp.
  • METHOD — HTTP-метод в верхнем регистре (POST или GET).
  • path — полный путь запроса включая префикс /api/v1, например /api/v1/integration/payouts. Без хоста и query-строки.
  • sha256_hex(raw_body) — SHA-256 в hex от сырого тела. Для GET тело пустое — это sha256("").

Подпись: HMAC-SHA256(строка, api_secret) в hex, где api_secret — секрет мерчанта (sk_…).

Окно по времени

X-Timestamp должен отличаться от серверного времени не более чем на 300 секунд (±5 минут). Синхронизируйте часы сервера (NTP), иначе запросы будут отклоняться с 401.

Формирование заголовков

import crypto from "node:crypto";
function signedHeaders(method, path, rawBody, apiKey, apiSecret) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const body = method === "GET" || method === "HEAD" ? "" : rawBody;
const bodyHash = crypto.createHash("sha256").update(body).digest("hex");
const payload = [timestamp, method, path, bodyHash].join("\n");
const signature = crypto
.createHmac("sha256", apiSecret)
.update(payload)
.digest("hex");
return {
"X-Api-Key": apiKey,
"X-Timestamp": timestamp,
"X-Signature": signature,
"Content-Type": "application/json",
};
}
const path = "/api/v1/integration/payouts";
const body = JSON.stringify({ amount: 25_000000, currency: "USDT",
external_id: "withdraw-001" });
await fetch("https://api.cashera.cash" + path, {
method: "POST",
headers: signedHeaders("POST", path, body, PK, SK),
body,
});

Белый список IP

Дополнительно мерчант может ограничить, с каких IP-адресов принимаются подписанные запросы. Если allowlist настроен в кабинете, запросы с других адресов отклоняются с 403. Запросы с разрешённых адресов проходят как обычно.

Ошибки подписи

ПолеТипОписание
401опц.UnauthorizedОтсутствует X-Timestamp/X-Signature, подпись неверна или время вне окна.
403опц.ForbiddenНе настроен секрет мерчанта или IP не в белом списке.