Webhooks notify your application in real-time when email events occur — deliveries, bounces, opens, clicks, and more. Instead of polling the API, your server receives HTTP POST requests instantly.
Supported Events
| Event | Description | When It Fires |
|---|---|---|
delivered |
Email delivered to recipient | Recipient’s mail server accepted the email |
bounced |
Email bounced | Recipient address invalid (hard) or mailbox full (soft) |
opened |
Email opened | Recipient opened the email (tracking pixel loaded) |
clicked |
Link clicked | Recipient clicked a tracked link |
complained |
Spam complaint | Recipient marked the email as spam |
failed |
Delivery failed | Email could not be sent after all retry attempts |
Setting Up Webhooks
- Go to https://platform.cyberpersons.com/email/webhooks/
- Click Create Webhook
- Enter your endpoint URL (must be HTTPS in production)
- Select which events to subscribe to
- Click Create — note the signing secret for verification
Webhook Payload
Each webhook sends a JSON POST request to your endpoint:
{
"event": "delivered",
"timestamp": "2026-02-23T10:30:02Z",
"data": {
"message_id": "[email protected]",
"from": "[email protected]",
"to": "[email protected]",
"subject": "Order Confirmation",
"tags": ["order"],
"metadata": {"order_id": "12345"}
}
}
For bounce events, additional fields are included:
{
"event": "bounced",
"data": {
"message_id": "...",
"bounce_type": "hard", // "hard", "soft", or "complaint"
"error_message": "550 User not found"
}
}
Security: Verifying Webhook Signatures
Every webhook request includes an X-Webhook-Signature header with an HMAC-SHA256 signature. Always verify this to confirm the request came from CyberPanel.
Python
import hmac, hashlib def verify_signature(payload_body, signature, secret): expected = hmac.new( secret.encode(), payload_body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature)
Node.js
const crypto = require('crypto'); function verifySignature(body, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) ); }
PHP
function verifySignature($body, $signature, $secret) { $expected = hash_hmac('sha256', $body, $secret); return hash_equals($expected, $signature); }
Retry Policy
- If your endpoint returns a non-2xx status, we retry with exponential backoff
- After 10 consecutive failures, the webhook is automatically disabled
- You can re-enable disabled webhooks from the dashboard
- Use the Test button in the dashboard to send a test event to your endpoint



