eSMS AfricaeSMS Africa
eSMS Mail

Webhooks

Receive real-time notifications for email delivery events.

Webhooks send HTTP POST requests to your server when email events occur - delivery, bounce, open, click, etc.

Create a webhook

Via dashboard

Go to Settings → Webhooks and click Create. Enter your endpoint URL and select which events to receive.

Via API

curl -X POST https://send.esmsafrica.io/v1/webhooks/ \
  -H "Authorization: Bearer esms_k_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/email",
    "events": ["delivered", "bounced", "open", "click"]
  }'

Response includes a secret for verifying webhook signatures:

{
  "id": "wh_123",
  "url": "https://yourapp.com/webhooks/email",
  "events": ["delivered", "bounced", "open", "click"],
  "secret": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
  "is_active": true
}

Webhook payload

{
  "event_type": "delivered",
  "email_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-07-31T10:30:00Z",
  "data": { "recipient": "[email protected]" }
}

Each request also carries these headers: X-ESMS-Signature (HMAC-SHA256 of the raw body), X-ESMS-Event (the event type), and X-ESMS-Delivery-ID. Non-2xx responses are retried with backoff (1m, 5m, 30m, 2h, 8h). Endpoints that resolve to private/internal addresses are rejected.

Verifying signatures

Each webhook request includes an X-ESMS-Signature header containing an HMAC-SHA256 signature. Verify it using the webhook secret:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from('sha256=' + expected)
  );
}
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest('sha256=' + expected, signature)

Available events

EventDescription
sentEmail accepted by the gateway and handed to the recipient's server
deliveredEmail accepted by recipient's server
bouncedEmail rejected by recipient's server
complainedRecipient marked the email as spam (feedback loop)
openRecipient opened the email
clickRecipient clicked a link
failedEmail could not be sent

Managing webhooks

Update a webhook

curl -X PATCH https://send.esmsafrica.io/v1/webhooks/{webhook_id} \
  -H "Authorization: Bearer esms_k_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"events": ["delivered", "bounced"], "is_active": true}'

Delete a webhook

curl -X DELETE https://send.esmsafrica.io/v1/webhooks/{webhook_id} \
  -H "Authorization: Bearer esms_k_your_api_key"

Retry policy

If your endpoint returns a non-2xx status code, eSMS Mail will retry the delivery. Failed webhooks are logged and can be inspected in the dashboard.

On this page