В отличие от приёма платежей (где достаточно X-Api-Key), вывод средств — операция повышенного риска. Поэтому запросы POST /integration/payouts и GET /integration/payouts/{uuid} нужно подписывать.
Заголовки
| Поле | Тип | Описание |
|---|---|---|
X-Api-Keyобяз. | string | API-ключ мерчанта (pk_…). |
X-Timestampобяз. | string | Unix-время в секундах на момент запроса. |
X-Signatureобяз. | string | HMAC-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 не в белом списке. |