Email Delivery Webhooks (SendGrid / SES / Mailgun / Mailjet)
When your email provider (SendGrid, Amazon SES, Mailgun, Mailjet) wants to tell XSender "the message you sent has been delivered / opened / clicked / bounced / spam-complained", it does so by POSTing a webhook to one of these endpoints.
XSender then writes the event into the corresponding Campaign Dispatch row, so your analytics dashboards, drip-campaign branches, and bounce-suppression lists all stay accurate.
Endpoints
| Provider | Webhook URL |
| SendGrid | POST /api/webhook/email/sendgrid |
| Amazon SES (via SNS) | POST /api/webhook/email/ses |
| Mailgun | POST /api/webhook/email/mailgun |
| Mailjet | POST /api/webhook/email/mailjet |
All endpoints are exempt from rate-limiting and accept the JSON shape that each provider natively sends — no transformation required on your side.
Setup — one URL per provider
SendGrid
- SendGrid → Settings → Mail Settings → Event Webhook.
- HTTP Post URL:
https://YOUR-XSENDER-DOMAIN/api/webhook/email/sendgrid
- Tick the events you want recorded (Delivered, Opened, Clicked, Bounced, Spam Report, Unsubscribe).
- Enable Signature Verification and paste the signing key in
XSender → Settings → Email Settings → SendGrid Signing Secret.
Amazon SES
- SES → Configuration Sets → create or pick one.
- Add an SNS destination pointing to a topic.
- Subscribe HTTPS endpoint
https://YOUR-XSENDER-DOMAIN/api/webhook/email/ses to the topic.
- XSender auto-confirms the SNS subscription on first call.
Mailgun
- Mailgun → Sending → Webhooks → Add webhook.
- URL:
https://YOUR-XSENDER-DOMAIN/api/webhook/email/mailgun
- Pick events: Delivered, Opened, Clicked, Permanent Failure, Complained, Unsubscribed.
- Mailgun signs each request; XSender verifies using your account's HTTP webhook signing key.
Mailjet
- Mailjet → Account → Event tracking (Triggers).
- For every event type, set URL to
https://YOUR-XSENDER-DOMAIN/api/webhook/email/mailjet
- Mailjet ships a per-account API key in the payload — XSender uses that to attribute the event to the right tenant.
How events become dispatch updates
| Provider event | XSender field updated |
delivered | delivered_at, status → Delivered |
open | opened_at, increment opens |
click | clicked_at, increment clicks, store URL |
bounce (hard) | status → Bounced, contact added to suppression list |
spam complaint | status → Complained, contact suppressed |
unsubscribe | contact marked unsubscribed = true |
Verifying events flow
- Send a test campaign to a controlled mailbox.
- Open
Campaigns → History → {your campaign} → Recipients.
- Each row's status, opens, and clicks should update within seconds of the action being taken in the inbox.
- If updates do not arrive: check the provider's webhook log for the response code XSender returned. A 2xx means it was accepted; 4xx/5xx means we rejected — read the body for the reason (usually signature mismatch or unknown account).
Other ESPs (Postmark, SparkPost, Resend, …)
Native webhook support is currently limited to the four providers listed above. For other ESPs you have two options:
- Translate via Zapier / Make: their webhook step receives the ESP event, reshapes it into the SendGrid format, and re-POSTs to XSender.
- Use the Automation Trigger Webhook with the ESP's outgoing webhook to enrol contacts into a "bounced" / "opened" workflow that simply updates the contact tag.
Native support for additional ESPs is on the v4.6 roadmap.