Payment Docs
Payouts

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:

  1. callbackUrl passed in the body of POST /v1/payouts — applies to this payout only;
  2. callbackUrl specified in the merchant settings;
  3. 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

RequirementValue
Schemehttp or https
Lengthno more than 2048 characters
Validationinvalid 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 format

Request 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

FieldTypeDescription
idstringPayout UUID
statusstringCurrent payout status
amountstringPayout amount
feestringFee charged for the payout
currencystringPayout currency
typestringPayment type
notestring / nullPayout note
externalIdstring / nullIdentifier in your system
merchantIdstringYour merchant UUID
settlementCurrencystring / nullSettlement currency
settlementAmountstring / nullAmount in the settlement currency
createdAtstringCreation time
completedAtstring / nullCompletion 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

ParameterValue
Number of attemptsup to 30
Interval30s × 2^n, but no more than 30 min
Success criterionresponse 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-Signature header 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

See Also

On this page