Email Provider Webhooks: SendGrid, Mailgun & SES
Email Provider Webhooks: SendGrid, Mailgun & SES
If you are implementing email provider event webhooks for delivery tracking, bounce handling, complaints, and engagement analytics, the hard part is not receiving HTTP POST requests. The hard part is building one pipeline that is secure, idempotent, and consistent across providers with very different payload and signature models.
This guide is the pillar page for SendGrid, Mailgun, and AWS SES/SNS webhook handling in Laravel/PHP teams using SendPromptly. It gives you the architecture, normalization pattern, and security baseline, then routes you to provider-specific implementation guides.
Supporting guides in this cluster
- SendGrid Event Webhook in Laravel
- Verify SendGrid Signed Event Webhook
- Mailgun Webhooks in Laravel
- Verify Mailgun Webhook Signatures
- AWS SES Event Notifications via SNS
- Verify AWS SNS Message Signatures in PHP
What “good” looks like for provider webhooks
A production-safe email provider webhook integration should:
- Verify authenticity before business processing.
- Return
2xxquickly to control retries. - Persist enough raw context for replay/debug.
- Process asynchronously with dedupe and idempotency.
- Normalize provider-specific events into one canonical event model.
- Forward canonical events into SendPromptly with an
Idempotency-Key.
If any one of those six is missing, you usually get one of these incidents: duplicate side effects, spoofed notifications, hidden drops, or “we got a 2xx but nothing actually processed.”
Provider comparison at a glance
| Provider | Delivery shape | Auth/signature model | Key implementation guide |
|---|---|---|---|
| SendGrid Event Webhook | JSON array (batched events) | Signed Event Webhook using ECDSA over timestamp + raw bytes | Receive + normalize and verify signature |
| Mailgun Webhooks | Often form-encoded (can vary) | HMAC-SHA256 over timestamp+token, plus replay protections | Receive + normalize and verify signature |
| AWS SES via SNS | SNS envelope, nested SES payload in Message | SNS certificate-based signature validation + TopicArn controls | SES/SNS flow and verify SNS signature |
Canonical architecture for email provider event webhooks
1) Receive provider webhook on a dedicated endpoint
Keep provider endpoints explicit, for example:
/webhooks/sendgrid/events/webhooks/mailgun/events/webhooks/aws/sns/ses
Dedicated routes make auth, rate controls, and observability cleaner.
2) Verify signatures in middleware (fail closed)
Run verification before parsing/mutating body content. Reject unauthorized or stale requests with 401 and no side effects.
- SendGrid: validate signed webhook headers and raw-body signature.
- Mailgun: validate
timestamp,token, and HMAC signature with replay defense. - SNS: validate message signature and pin expected topic where possible.
3) ACK fast (200/204), queue heavy work
Provider webhooks are at-least-once delivery systems. If you block in request threads, you amplify retries and duplicates. Accept quickly, then enqueue processing.
4) Dedupe and idempotency before state changes
Use deterministic dedupe keys and store them before applying downstream side effects.
Recommended key ingredients:
- SendGrid:
sg_event_id + event + timestamp - Mailgun: provider message identity + event + timestamp/token context
- SNS/SES: SNS
MessageId+ SES notification type + message identity
5) Normalize to one internal schema
Normalize all providers into one canonical event payload so analytics, alerting, and workflows are provider-agnostic.
| |
6) Forward to SendPromptly ingestion with idempotency
Use one canonical event key (for example email.provider_event) and always send an Idempotency-Key header so retries do not create duplicate runs.
Reference: Event Ingestion and Authentication.
Event taxonomy mapping (provider -> canonical)
| Canonical type | SendGrid examples | Mailgun examples | SES/SNS examples |
|---|---|---|---|
delivered | delivered | delivered | Delivery notification |
bounce | bounce, dropped | bounced | Bounce notification |
complaint | spamreport | complained | Complaint notification |
deferred | deferred | delayed/temporary failure equivalents | transient delivery delays (provider-specific context) |
open | open | opened | typically not SES core feedback via SNS |
click | click | clicked | typically not SES core feedback via SNS |
The goal is stable downstream behavior regardless of provider naming differences.
Security baseline checklist
- Verify before queueing or persistence side effects.
- Use raw body where provider algorithms require it.
- Enforce timestamp drift windows and replay controls.
- Pin trusted origins (topic ARN/cert domains where applicable).
- Never log secrets, full tokens, or sensitive payload fields.
- Rotate secrets/keys with staged rollout and test vectors.
Deep dive references:
- Webhook Signature Verification Cookbook
- Webhook Security Checklist
- Webhook Signature Verification Pitfalls
Observability and debugging workflow
For email provider event webhooks, debugging should follow one order every time:
- Confirm provider attempted delivery.
- Confirm your endpoint received and verified the request.
- Confirm dedupe/idempotency decision.
- Confirm normalized event forwarding to SendPromptly.
- Confirm resulting run state and retries in logs.
Use these guides for deterministic troubleshooting:
- Debug Webhooks with Delivery Logs
- Delivery Log Replay Workflow
- Test Webhooks Locally (Tunnels + Signed Requests)
Recommended rollout order
- Implement provider endpoint + fast ACK pattern.
- Add signature verification and replay controls.
- Add dedupe store and idempotent worker behavior.
- Normalize events and forward into SendPromptly.
- Add alerting for signature failures, timeout spikes, and retry storms.
This sequence reduces integration risk and gives you production visibility early.
Conclusion
Email provider event webhooks are most reliable when you treat them as a security and reliability pipeline, not just an HTTP controller. Build once with verification, fast acknowledgment, idempotent async processing, and canonical normalization, then plug in each provider-specific adapter.
Start with the provider you use today, then follow the linked implementation + verification guides above to reach a consistent multi-provider model in SendPromptly.