Webhooks
Speend отправляет POST на url_callback при изменении статуса. Правила того, при каких именно сменах статуса шлётся webhook, различаются для платежей и выплат — см. ниже.
Откуда берётся адрес доставки
Приоритет между адресом из личного кабинета и адресом из тела запроса различается по методам:
| Метод | Приоритет |
|---|---|
| Статический кошелёк (createStaticWallet) | Адрес из личного кабинета — значение url_callback из запроса игнорируется |
| Инвойс (createPayment) | Адрес из запроса имеет больший приоритета по сравнению с адресом из личного кабинета |
| Выплата (payout/create) | Адрес из личного кабинета — аналогично статическому кошельку |
Webhook — инвойс и статический кошелёк
Отправляется на многих значимых переходах, включая промежуточные статусы (не только финальные) — например, при переходе в check, при частичной недоплате, при разблокировке AML и т.д.
{
"type": 2,
"uuid": "019f69ef-f130-7064-b822-09b39a40b99c",
"amount": "2",
"paid_amount": "6.170554",
"paid_amount_usd": "2.00210147",
"merchant_amount": "6.07799569",
"commission_percent": "1.5",
"commission_fixed": "0",
"commission": "0.09255431",
"is_final": true,
"status": "paid",
"network": "TRON",
"currency": "TRX",
"txid": "36540b5842d27b23da70415439281e2...",
"from": "TQn9Y2*****LVLTiPKX",
"to": "TCEUYh*****bNhPMK6W",
"order_id": "1002",
"additional_data": null,
"sign": "91be60615455288c41ee177ab8b02b19"
}
Для статического кошелька дополнительно присутствуют поля wallet_address_uuid и wallet_id. Если у мерчанта включена автоконвертация — присутствует объект convert (структура как в payment/info, см. раздел «Информация о платеже»).
type — что породило уведомление (платежи и статический кошелёк)
| type | Источник |
| 1 | Статический кошелёк |
| 2 | Invoice (createPayment) |
Webhook — выплаты (Payout)
В отличие от платежей, вебхук по выплате отправляется не при каждой смене статуса, а только для ограниченного набора статусов — см. таблицу ниже. Промежуточные технические статусы наружу не идут.
{
"uuid": "019f89aa-bfe9-7308-8e40-fb5b1345a5a4",
"type": 1,
"status": "success",
"is_final": true,
"amount": "7",
"commission": "0",
"network": "SOL",
"currency": "USDT",
"address": "8Q3zsm*****tVUzasKQ",
"txid": "DgR9Tg*****AFe5nA9j6zJ6",
"order_id": "13",
"description": null,
"comment": null,
"created_at": "2026-07-22T11:51:36+00:00",
"updated_at": "2026-07-22T11:52:04+00:00",
"sign": "c8980a53111b04abea70c2371ff2fca7"
}
type — способ создания выплаты (только Payout)
| type | Способ создания выплаты |
| 1 | Через публичное API (payout/create) |
| 2 | Вручную в личном кабинете мерчанта |
| 3 | Администратором Speend |
Статусы, по которым шлётся webhook (Payout)
| Статус в API (getStatus) | Статус в вебхуке |
|---|---|
| ON_QUEUE | process |
| SUCCESS | success |
| CANCELED | cancel |
| FAILED | fail |
| AML_FAILED | aml_fail |
Вебхук приходит только по этим 5 статусам, вне зависимости от того, как создана выплата. Статусы REQUESTED, AWAITING_CONFIRMATION и внутренние стадии (ON_QUEUE_CONVERSION, ON_NETWORK_QUEUE) наружу не отправляются.
Подпись sign
Каждый webhook содержит поле sign.
Подпись позволяет убедиться, что webhook действительно отправлен Speend, а не подделан третьей стороной. Проверка обязательна перед тем, как доверять статусу из webhook.
type — что породило уведомление (платежи и статический кошелёк)
// webhook_password опционален
signKey = api_key + webhook_password
// тело — без поля sign, порядок ключей как в исходном JSON
sign = MD5(
base64( json_encode(тело, JSON_UNESCAPED_UNICODE) ) . signKey
)
Какой ключ использовать
Ключ для формулы зависит от события, а не напрямую от поля type. У Payout и Статического кошелька значение type одинаковое (1), но ключи разные:
| Событие | Ключ (api_key в формуле) |
|---|---|
| Payout (вывод средств) | Ключ выводов (api_key_withdraw) |
| Статический кошелёк (пополнение) | Основной ключ (api_key_main) |
| Invoice (createPayment) | Основной ключ (api_key_main) |