Webhooks
Webhooks send your server an HTTPS POST whenever something happens to an email you sent: it was delivered, it bounced, it was deferred, and so on. You don't need to poll; events usually arrive within a few seconds.
Set up an endpoint
- In the dashboard, open Webhooks and click Add endpoint.
- Enter your endpoint URL. It must use
https://with a valid certificate. - Choose the events to receive, or All events (this also includes event types added later).
- Optionally limit it to some of your sending domains.
- Optionally add an auth header (see Securing your endpoint).
- Save, then click Test to send a sample event and see your server's reply.
An endpoint only receives events that happen after it was created.
| Limit | Value |
|---|---|
| Endpoints per workspace | 10 |
| The same URL twice in one workspace | not allowed |
| Who can manage webhooks | Owner, Admin, Developer (Viewers can't see them) |
What your server receives
Every request is a POST with a JSON list of 1 to 100 events. Events are sent as soon as they are ready; SendMero doesn't wait to fill a list, so under light traffic most requests carry one event.
POST /your/webhook/path HTTP/1.1
Content-Type: application/json
User-Agent: SendMero-Webhooks/1.0
webhook-id: req_28df66049b47aafafc19a609
webhook-timestamp: 1790354239
[
{
"id": "evt_062c48c47998041a138ebf6bf53cec95",
"type": "bounced",
"created_at": "2026-09-25T18:01:22.470Z",
"data": {
"message_id": "msg_0c2a7e323ab3471881a1db9f077540a1",
"recipient": "someone@example.com",
"domain": "mail.yourdomain.com",
"occurred_at": "2026-09-25T18:01:20.006Z",
"attempt": 0,
"metadata": { "order_id": "88231" },
"details": {
"smtp": { "code": 550, "enhanced_code": "5.7.1", "response": "…", "remote_ip": "74.125.197.27" },
"bounce": { "type": "hard", "classification": null }
}
}
}
]
| Header | Meaning |
|---|---|
webhook-id | ID of this request. A retry of the same events is a new request with a new ID. |
webhook-timestamp | When the request was sent, in Unix seconds. |
| Your auth header | Only if you set one on the endpoint. |
See Event reference for every event type and field.
Responding
- Reply with any
2xxstatus to confirm. The reply body is ignored. - Reply within 10 seconds (5 seconds to connect). Slower replies count as failures.
- Redirects are not followed; a
3xxcounts as a failure. - Do the slow work (database writes, other API calls) after you reply, for example by putting the events on your own queue.
Handle duplicates
Delivery is at least once: after a timeout or a network error, an event you already processed can arrive again. Use each event's id to ignore ones you have already handled. The order of events is not guaranteed, especially across retries; use occurred_at if order matters.
Failures and retries
If a request fails (no 2xx, a timeout, or a connection error), its events are retried 5 times after about 1 minute, 5 minutes, 30 minutes, 1 hour and 4 hours. Other events keep flowing while one is being retried.
If your endpoint keeps failing:
| After | What happens |
|---|---|
| 20 failures in a row | The endpoint is paused. New events wait, and one event is tried every 5 minutes. |
| The first successful try | The endpoint is active again and everything that waited is sent. |
| 24 hours of failing | The endpoint is switched off. Owners, Admins and Developers get an email and a dashboard notification. |
To switch an endpoint back on, fix your server, then click Enable on the endpoint. Events that waited up to 24 hours are sent; anything older is not sent (it's noted in the delivery log, and the emails' events are still shown in Activity).
If you delete a sending domain, it is removed from every endpoint's domain filter. An endpoint left with no domains is switched off with the reason "domain removed".
Download events as a file
To get the same events as a CSV or JSON Lines file instead of receiving them at an endpoint, use Export → Events on Activity.
Delivery log, graphs and replay
Open an endpoint to see:
- Delivery log: every request from the last 30 days, successful or not, with the status code, error, events, attempt number, the first 1 KB of your server's reply, and a timing breakdown (DNS, connect, TLS, waiting for your server).
- Graphs: requests, events, failures and response time per minute, hour or day.
- Replay: resend the events of one request, or all failed events in a time range up to 7 days back. Replays are sent at up to 5 requests per second and don't change what is sent next.
Securing your endpoint
Each endpoint can have one auth header, a header name and value that SendMero adds to every request, for example Authorization: Bearer <a long random secret>. Check it on your server and reject requests without it.
- The value is encrypted when stored and never shown again after saving (the dashboard shows only its last 4 characters). To change it, enter a new value.
- The value is never written to the delivery log.
- You can't use
Content-Type,Content-Length,User-Agent,Host,webhook-idorwebhook-timestampas the header name.
Requests aren't signed yet. If your firewall only allows known addresses, contact support for the list of addresses webhooks are sent from (IPv4 and IPv6).