Outgoing Webhooks
Events, payload format, HMAC-SHA256 signature
What it is
Outgoing webhooks notify your external systems when events occur in WHMDC: invoice created, invoice paid, service provisioned, etc. Your endpoint receives the event data and can react (e.g. sync to CRM, send to Slack, trigger provisioning elsewhere).
How it works
When an event occurs, WHMDC sends an HTTP POST to each configured webhook URL. The payload is JSON. The X-Webhook-Signature header contains an HMAC-SHA256 signature so you can verify the request came from your WHMDC.
Delivery behaviour
| Behaviour | Details |
|---|---|
| Retries | Single attempt per event. Failed deliveries are logged in webhook_deliveries but not automatically retried. Use Admin webhook logs to identify failures; implement a manual resend or replay process if needed. |
| Timeout | 10 seconds total, 5 seconds connect. Your endpoint must respond within 10 seconds. Process heavy work asynchronously (queue a job, return 200 immediately). |
| Ordering | No guaranteed ordering. Events may arrive out of order. Use timestamp in the payload to order if needed. |
| Deduplication | No built-in event_id. Generate a dedupe key: hash('sha256', $event . '|' . ($data['invoice_id'] ?? $data['service_id'] ?? '') . '|' . $timestamp). Store processed keys and skip duplicates. |
Best practices
- Idempotency: Design your handler to be idempotent. The same event could theoretically be re-sent (e.g. manual replay). Check if you have already processed this invoice_id/event before applying side effects.
- Fast response: Return HTTP 200 quickly. Do not block on external API calls. Queue work for background processing.
- Replay: If Admin provides a "resend" or "replay" action for failed deliveries, use it to retry. Otherwise, re-trigger the event from your side if possible.
Payload format
{
"event": "invoice.paid",
"data": {
"invoice_id": 123,
"invoice_number": "INV-2024-001",
"client_id": 45,
"amount": 29.99,
"currency": "GBP"
},
"timestamp": "2024-01-15T10:30:00Z"
}
Example events
invoice.createdinvoice.paidpayment.failedservice.provisionedservice.suspendedclient.created
Verifying the signature
// PHP example
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$secret = 'your_webhook_secret';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (hash_equals($expected, $signature)) {
// Valid - process the event
}
How to set up
Create webhooks via the Public API (POST /api/v1/webhooks) or admin UI if available. Configure the URL, select events, and store the secret for signature verification.
Was this helpful?