Webhooks

Basics

Merchant systems can receive real-time notifications from the xMoney platform via webhooks. Currently, the available events are:

  • Order payment confirmation
  • Order cancellation

The webhook URL is specified using the callback_url field when creating an order.

Response Handling & Retries

Webhook requests must respond with an HTTP 2xx status to indicate success. Any other response or a lack of response is considered a failure, triggering a retry mechanism. xMoney retries up to 15 times using an exponential backoff following a Fibonacci sequence:

  1. First retry: 1 minute after failure
  2. Second retry: 2 minutes after the first retry
  3. Third retry: 3 minutes after the second retry
  4. ... up to 987 minutes (~16 hours 27 minutes) after the last failure

If all retries fail, an email notification with error details is sent.

Security & Authentication

All webhook requests from xMoney are signed using a Webhooks Secret for validation.

  • Webhooks are automatically set up and validated in our integrations.
  • For custom integrations, we provide libraries for request validation.
  • Each webhook request is signed to prevent unauthorized access.

Events

Events notify merchants of order-related activities in real time. Webhooks deliver these events to the specified callback_url.

Supported Events

Event NameDescription
ORDER.PAYMENT.DETECTEDPayment detected on blockchain (not confirmed).
ORDER.PAYMENT.RECEIVEDPayment successfully confirmed.
ORDER.PAYMENT.CANCELLEDPayment was canceled.

Verifying Events

To ensure authenticity, webhook events are signed using HMAC SHA256 with the Webhooks Secret as the key. The payload is sorted alphabetically before signing.

Example Payload

{
  "event_type": "ORDER.PAYMENT.RECEIVED",
  "resource": {
    "reference": "1400012634",
    "amount": "10.8200",
    "currency": "EUR"
  },
  "signature": "5ef8a5994e917c14479b31f690d4d2a023dfcc6059081504e3087977b21580ab",
  "state": "completed"
}

Ordered Payload for Signing

{
  "event_type": "ORDER.PAYMENT.RECEIVED",
  "resource": {
    "amount": "10.8200",
    "currency": "EUR",
    "reference": "1400012634"
  },
  "state": "completed"
}

Signing Process

joined_payload="event_typeORDER.PAYMENT.RECEIVEDresourceamount10.8200resourcecurrencyEURresourcereference1400012634statecompleted"
signed_payload=$(echo -n "$joined_payload" | openssl dgst -sha256 -hmac "$secret")

The resulting signature should match the one in the webhook request.

For a PHP validation example, see this reference.

Response & Retries

Webhook responses must follow these rules:

  • Success (200 OK){ "success": true } (optional JSON response)
  • Invalid signature or malformed request (400 Bad Request)
  • Internal processing errors (500 Internal Server Error)

If the webhook fails, retries occur as per the Fibonacci backoff schedule, up to 15 times. After that, an email notification is sent with failure details.