Webhooks
After a payment or payout status changes, Cobrex sends an HTTP request to the URL configured for the merchant or the callback provided when the operation was created.
Request body
| Operation | Body |
|---|---|
| Payment | JSON payment object (see model). |
| Payout | JSON payout object (see model). |
Confirm HTTP method and headers with the latest spec; use the checks below for security.
Your server response
When the webhook is accepted and processed (or safely queued internally so processing is guaranteed), your endpoint must return HTTP 200. Cobrex treats this as successful delivery.
Any other outcome (5xx, 4xx, timeouts, connection drops) is treated as failure — retries follow the schedule below.
Retries after failure
On unsuccessful delivery, Cobrex schedules another attempt with increasing delay:
- The attempt counter increments while it stays below 9.
- At 9 or more attempts in this cycle, no further retries are scheduled (
next_attempt_atis cleared). - The delay until the next attempt depends on the current
attemptsvalue when the next run is scheduled.
Delay until the next attempt:
attempts when scheduling | Delay until next delivery |
|---|---|
1 | 10 seconds |
2 | 30 seconds |
3 | 1 minute |
4 | 5 minutes |
5 | 15 minutes |
6 | 1 hour |
7 | 4 hours |
8 | 16 hours |
| Other handled values (implementation fallback) | 15 minutes |
You may therefore receive up to nine unsuccessful rounds before retries stop under this scheme; confirm production behaviour with Cobrex support if retry policy changes.
Check 1 — IP address
Allow only trusted IPs. At documentation time:
46.166.162.83
Lists can change after infra moves — confirm the production list with support.
Check 2 — x-signature header
- Keep the raw body as string/buffer before
JSON.parse. - HMAC-SHA256 with your secret (same as API, or a dedicated webhook secret — confirm with Cobrex).
Expected pattern (integration panel):
signature_hex = HMAC-SHA256( key = api_secret, message = JSON.stringify(data) ).toString('hex')
where data is the parsed object. In practice, verifying HMAC over the raw body string is often more stable:
const crypto = require('crypto');
function verifyWebhookSignature(rawBodyString, receivedHex, apiSecret) {
const expected = crypto.createHmac('sha256', apiSecret).update(rawBodyString).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(receivedHex, 'hex'));
}
Confirm with Cobrex whether production matches JSON.stringify(data) exactly or raw bytes — use the confirmed variant.
Recommendations
- Return
HTTP 200quickly after validation and enqueueing; run heavy work asynchronously. - Make handlers idempotent by
payment_id/payout_id. - Log headers and bodies in debug (never log secrets).
See also: Authentication & signing.