Payout Webhooks
How to receive payout status notifications
There are two ways to get the payout status: automatic webhook notifications (recommended) and manual polling of GET /v1/payouts/{payoutId}.
Notification Address
The address is resolved in the following order of priority:
callbackUrlpassed in the body ofPOST /v1/payouts— applies to this payout only;callbackUrlspecified in the merchant settings;- if neither value is set, no notifications are sent for the payout.
The address is fixed at the moment the payout is created. Subsequent changes to the merchant settings do not move the notifications of an already created payout to the new address, and vice versa.
The signature is always generated using the merchant apiToken, regardless of which address is used.
Request Example
{
"amount": 1000.5,
"currency": "RUB",
"paymentType": "C2C",
"externalId": "payout-123",
"callbackUrl": "https://merchant.example/payouts/webhook",
"account": {
"name": "Ivan Ivanov",
"requisites": "4111111111111111",
"userId": "u-42"
}
}callbackUrl Requirements
| Requirement | Value |
|---|---|
| Scheme | http or https |
| Length | no more than 2048 characters |
| Validation | invalid URL → 400 Validation failed |
The field is returned in the payout object (GET /v1/payouts/{payoutId}). A value of null means the merchant settings are used.
Delivery Conditions
A notification is generated on every payout status change, with two exceptions:
CREATED— no notification is sent;COMPLETED— the notification is queued separately, within the payout completion transaction, once the final fee amount is known.
Manual sending of a notification from the administration panel is also supported.
Duplicate records are excluded by the combination of (address, payout id, status) among unsent notifications.
Notification Format
POST {callbackUrl}
Content-Type: application/json
X-Type: PAYOUT_UPDATE
X-Signature: HMAC-SHA512(request body, apiToken) in hex formatRequest Body Example
{
"id": "0198c3f1-2a4b-7c3d-9e0f-1a2b3c4d5e6f",
"status": "COMPLETED",
"amount": "1000.5",
"fee": "60",
"currency": "RUB",
"type": "C2C",
"note": null,
"externalId": "payout-123",
"merchantId": "0198c3f1-1111-7222-8333-444455556666",
"settlementCurrency": "USD",
"settlementAmount": "11.28",
"createdAt": "2026-07-29T10:00:00.000Z",
"completedAt": "2026-07-29T10:04:12.317Z"
}Request Body Fields
| Field | Type | Description |
|---|---|---|
| id | string | Payout UUID |
| status | string | Current payout status |
| amount | string | Payout amount |
| fee | string | Fee charged for the payout |
| currency | string | Payout currency |
| type | string | Payment type |
| note | string / null | Payout note |
| externalId | string / null | Identifier in your system |
| merchantId | string | Your merchant UUID |
| settlementCurrency | string / null | Settlement currency |
| settlementAmount | string / null | Amount in the settlement currency |
| createdAt | string | Creation time |
| completedAt | string / null | Completion time |
The callbackUrl field is not included in the notification body: it defines
the delivery address and is not part of the payout state.
Signature Verification (X-Signature)
Each notification includes the X-Signature header — this is the HMAC SHA512 hash in HEX format of the request body. The signature is generated using your API token as the secret key.
Example of Signature Verification
import crypto from "crypto";
const apiToken = "your_API_token";
app.post("/payouts/webhook", (req, res) => {
const signature = req.headers["x-signature"];
const body = JSON.stringify(req.body);
// Verify the signature
const hmac = crypto.createHmac("sha512", apiToken);
hmac.update(body);
const calculatedSignature = hmac.digest("hex");
if (calculatedSignature !== signature) {
console.error("❌ Invalid webhook signature!");
return res.status(403).send("Invalid signature");
}
console.log("✅ Signature is valid");
// Process the notification
const data = req.body;
if (data.status === "COMPLETED") {
console.log(`✅ Payout ${data.externalId} has been sent!`);
}
res.status(200).send("OK");
});If the same address receives notifications for both orders and payouts, additionally check the X-Type: PAYOUT_UPDATE header.
Retry Policy
| Parameter | Value |
|---|---|
| Number of attempts | up to 30 |
| Interval | 30s × 2^n, but no more than 30 min |
| Success criterion | response with HTTP code 200–399 |
A circuit breaker mechanism is also applied: an address that consistently returns errors is temporarily excluded from delivery.
Webhook Recommendations
- Always respond with HTTP 200–399 to confirm receipt
- Verify the
X-Signatureheader before processing the request body - Process notifications idempotently — the same notification may be delivered more than once
- Verify the payout data matches your records using
externalId - Handle all possible status values in your integration