Webhooks and automation
Subscribe to events, verify signatures, chain distro into your stack.
Webhooks let you react to distro events in your own systems. Common uses: piping shipped posts into an internal dashboard, triggering a CI build when an idea moves to Drafting, posting to a team Slack when a peer review arrives.
Creating a webhook
Settings → API → Webhooks → New. You provide:
- An endpoint URL (HTTPS required)
- A subset of events to subscribe to (or "all events")
- Optionally, specific apps to scope to (default: all your apps)
On save, we generate a signing secret (whsec_...) shown once. Verify incoming requests against it — we never send payloads that aren't signed.
Signature verification
// Node
import crypto from 'crypto';
function verify(rawBody, signatureHeader, secret) {
const [t, v1] = signatureHeader.split(',').map(p => p.split('=')[1]);
const signed = `${t}.${rawBody}`;
const expected = crypto
.createHmac('sha256', secret)
.update(signed)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(v1)
);
}Header is distro-signature. Reject on mismatch. Reject if the timestamp is more than 5 minutes old (replay protection).
Event payload shape
{
"id": "evt_01HRXZ...",
"type": "idea.evaluated",
"created": 1713456789,
"livemode": true,
"data": {
"idea": { "id": "...", "title": "...", "composite": 78, ... }
}
}Retries
We retry non-2xx responses with exponential backoff: 10s, 30s, 2m, 15m, 1h. Give up after 5 attempts. Each attempt has a 10-second timeout.
Test and replay
The webhook detail page shows the last 100 deliveries with status, response body, latency. Click any failed delivery to Resend. Useful when your handler had a bug and you want to re-run after deploying a fix.