PSend

Webhooks

Subscribe to delivery lifecycle events. Every payload is signed so you can verify authenticity.

Events

  • email.queued — Accepted by the API
  • email.sent — Handed to the MTA
  • email.delivered — Accepted by the recipient MX
  • email.opened — Open pixel fired
  • email.clicked — Tracked link clicked
  • email.bounced — Hard or soft bounce
  • email.complained — Spam complaint
  • email.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-signature
  • X-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.