Webhooks
Webhooks
Webhooks · SeleQueue · SeleMail · Email Routing · Push · Bot protection · API and keys
Register an HTTPS endpoint and choose the events you want. We POST each event as JSON, signed with your endpoint secret. The secret is shown once when you create the endpoint; rotate it any time.
Create an endpoint
POST /v1/webhooks/endpoints
{ "url": "https://example.com/hooks/seleid", "events": ["user.created"] }
-> { "id": "we_1", "secret": "whsec_..." }
Verify the signature
Each request carries SeleID-Signature: t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of <t>.<raw body> with your secret. Compare in constant time and reject timestamps older than 5 minutes.
Node
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(secret, rawBody, header, nowSec = Date.now() / 1000) {
const p = Object.fromEntries(header.split(',').map((x) => x.split('=')));
if (Math.abs(nowSec - Number(p.t)) > 300) return false;
const want = createHmac('sha256', secret).update(p.t + '.' + rawBody).digest('hex');
return want.length === p.v1.length && timingSafeEqual(Buffer.from(want), Buffer.from(p.v1));
}
Retries, log and replay
Any non-2xx answer, timeout (10 seconds) or network error is retried with exponential backoff (30 s, 1 min, 2 min, 4 min, 8 min), six attempts in all; after that the delivery is marked failed and kept in the dead-letter list. Every attempt is recorded in the delivery log. Replay re-sends the same event body as a new delivery. Respond quickly with 2xx and process in the background; the same event may arrive more than once, so de-duplicate on SeleID-Event-Id.
Endpoint URLs must be HTTPS on a public hostname (no IP addresses, localhost or internal names).