Skip to main content
Instead of polling, let PulseSend call your server when something happens to an email: delivered, bounced, marked as spam.

Add an endpoint

In the dashboard, open Webhooks and click Add endpoint. Enter a public HTTPS URL and pick the events to receive, or all of them. Each endpoint gets its own signing secret, shown on its page, where you can also rotate it. Use Send test to check your endpoint: PulseSend sends a webhook.test event, whatever the endpoint subscribes to. Every attempt shows up under Deliveries with the response code, and any delivery can be resent with the same event id. Endpoints must use https:// and resolve to a public address: localhost, private networks and cloud metadata addresses are refused.

Events

Payload

Each call is a POST with a JSON body:
email.failed adds a reason to data. Use id to drop duplicates: the same event can arrive more than once.

Verify the signature

Every call carries an X-PulseSend-Signature header:
v1 is an HMAC-SHA256 of {t}.{raw body} with your endpoint’s secret. Check it before trusting the payload, and reject timestamps older than five minutes to block replays.
Sign the raw request body, byte for byte. Parsing and re-serializing the JSON changes it and the signature won’t match.
In Laravel, exclude the route from CSRF protection.

Responding and retries

Answer with any 2xx status within 10 seconds. Do the heavy work in a queue after answering. A timeout, a network error or any other status counts as a failure. PulseSend then retries 6 times over about a day: after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 15 hours. Redirects aren’t followed.