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:
- First retry: 1 minute after failure
- Second retry: 2 minutes after the first retry
- Third retry: 3 minutes after the second retry
- ... 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 Name | Description |
---|---|
ORDER.PAYMENT.DETECTED | Payment detected on blockchain (not confirmed). |
ORDER.PAYMENT.RECEIVED | Payment successfully confirmed. |
ORDER.PAYMENT.CANCELLED | Payment 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.