Webhooks
Subscribe to delivery lifecycle events. Every payload is signed so you can verify authenticity.
Events
email.queued— Accepted by the APIemail.sent— Handed to the MTAemail.delivered— Accepted by the recipient MXemail.opened— Open pixel firedemail.clicked— Tracked link clickedemail.bounced— Hard or soft bounceemail.complained— Spam complaintemail.unsubscribed— Recipient opted out (link or one-click)
Payload example
{
"type": "email.delivered",
"created_at": "2026-10-20T10:01:12Z",
"data": {
"email_id": "em_01HX...",
"to": "[email protected]",
"from": "[email protected]"
}
}Signatures
PSend signs every webhook with HMAC-SHA256. Verify using the Svix-compatible headers or the dedicated PSend header:
svix-id,svix-timestamp,svix-signatureX-PSend-Signature—t=timestamp,v1=hex_hmac
// Node verification sketch
const payload = `${t}.${rawBody}`;
const expected = crypto
.createHmac('sha256', signingSecret)
.update(payload)
.digest('hex');
timingSafeEqual(expected, v1);Retry policy
- Timeout: 10 seconds per delivery attempt
- Retries on non-2xx with exponential backoff over ~24 hours
- Disable an endpoint after sustained failures; re-enable in the dashboard
Tip: use the RN/Expo and Flutter harnesses locally, then point a tunnel (ngrok, Cloudflare Tunnel) at your webhook listener while testing.