2.3 Webhook delivery
Overview
When a payout status changes, the platform can notify your system by sending an HTTP request to a URL you provide. This allows you to keep your records in sync without polling Get payout status.
When webhooks are sent
A webhook is sent when the transaction status changes. One request is sent per status change.
Webhook URL
The platform uses the first available URL in this order:
- Per-request
callback_url— if you passedcallback_urlin the Create payout request body, that URL is used for that transaction. - Shop default webhook URL — if the shop has
webhook_urlconfigured and webhooks enabled, that URL is used when the transaction has nocallback_url.
If neither is set, no webhook is sent for that transaction.
Request format
| Property | Value |
|---|---|
| Method | POST |
| URL | Your callback_url or the shop's webhook_url. |
| Headers | See below. |
| Body | JSON object (see payload). |
Headers
| Header | Description |
|---|---|
| Content-Type | application/json |
| X-Timestamp | ISO-8601 timestamp (UTC) of the request. |
| X-Signature | HMAC-SHA256 signature (see Verifying the signature). |
Payload (body)
The body is a JSON object with the following fields:
| Field | Type | Description |
|---|---|---|
| id | number | Internal transaction ID. |
| external_id | string | Your identifier from the create request (idempotency key). |
| shop_code | string | Shop code. |
| status | string | Current external payout status. Values are limited to pending, success, failed, canceled, refunded, or expired. |
| amount | string | Transaction amount. |
| currency | string | ISO currency code. |
| paymentData | object | Shop-schema output (same shape as in API responses). |
| updated_at | string | ISO-8601 timestamp of the status update. |
The webhook body does not include an event field. Delivery type is implied by the endpoint and the merchant flow (payout vs payin), while the platform still tracks the internal event name for delivery logs.
Example payload
{
"id": 12345,
"external_id": "PAY-001",
"shop_code": "shop-001",
"status": "success",
"amount": "1000.00",
"currency": "RUB",
"paymentData": {},
"updated_at": "2025-12-05T10:15:00.000000Z"
}
Verifying the signature
To ensure the request came from the platform and was not altered, verify the X-Signature header.
- Take the X-Timestamp header value (as sent).
- Take the raw request body (string, as received).
- Compute:
message = X-Timestamp + body. - Compute:
signature = HMAC_SHA256(webhook_secret, message). - Compare
signaturewith the X-Signature header (constant-time comparison).
The webhook_secret is the same secret used for API request signing (merchant/organization level). If no secret is configured, webhooks are not sent.
Your endpoint requirements
- Your endpoint must respond with HTTP 2xx (e.g. 200) for the delivery to be considered successful.
- Any other status (4xx, 5xx) or a timeout is treated as a failure; the platform will retry (see below).
- Respond quickly (e.g. within a few seconds). If you need to do long work, acknowledge with 200 and process asynchronously.
Retries
If the platform does not receive a successful (2xx) response or the request times out, it retries the webhook up to 5 attempts total (initial attempt plus retries) with delays of 1 minute, 5 minutes, 30 minutes, 60 minutes, and 120 minutes. Design your endpoint to be idempotent so that receiving the same status change more than once is safe.