/
Docs home / Developers

Webhooks

Webhooks send an HTTP POST to your server when something happens to your email, so your own systems stay in sync.

Last updated: 2026-10-13

Events

Event Sent when
unsub A contact unsubscribes
complaint A contact marks an email as spam
bounce An email hard-bounces
open A contact opens an email
click A contact clicks a link
open_click A contact opens or clicks
unsub_complaint A contact unsubscribes or complains

Create a webhook

In the portal, open Integrations → Webhooks and add the URL that should receive events, then choose the event. Use the Test Webhook dialog to see example data for each event type.

With the API:

curl -s -X POST https://mailhoor.com/api/webhooks \
  -H "X-Auth-APIKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Unsubscribes to CRM", "target_url": "https://yourapp.com/hooks/mailhoor", "event": "unsub"}'

The response is 201 with the new webhook. A 409 means the same webhook already exists.

Receiving events

  • Your endpoint must use HTTPS and answer with HTTP 200 quickly. Do slow work after you respond.
  • The same event can arrive more than once. Make your handler safe to run twice.
  • Treat the data as untrusted input: validate it before you write to your database.

Verify the signature

Every webhook carries two headers: X-MailHoor-Timestamp (Unix seconds) and X-MailHoor-Signature (sha256= + HMAC-SHA256 of the timestamp, a dot and the raw request body). Find your signing secret under Integrations → Webhooks → Signing secret.

import hashlib, hmac, time

def verify(secret: str, timestamp: str, signature: str, raw_body: bytes) -> bool:
    if abs(time.time() - int(timestamp)) > 300:
        return False
    expected = "sha256=" + hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

Use the raw body exactly as received, before parsing JSON. Reject requests older than 5 minutes. If you replace the secret, update your server right away.

Common uses

  • Mark unsubscribed contacts in your CRM (unsub, complaint).
  • Clean bounced addresses from your own database (bounce).
  • Score leads by engagement (open_click).
Still need help? Email support@mailhoor.com or call +20 101 072 9258. We answer in Arabic and English.