Webhooks
Webhooks push events to your backend the moment they happen — a message was delivered, a link was clicked, a contact unsubscribed. Every payload is signed so you can trust it, and failed deliveries are retried with backoff so a brief outage never loses an event.
What you'll need
- A public HTTPS endpoint to receive POSTs
- An API key or admin access to register the webhook
Register an endpoint
- 1
Open Settings → Webhooks
Or call POST /v1/workspaces/{workspace_id}/webhooks. Provide your HTTPS URL and pick the events you want.
- 2
Store the signing secret
Each webhook has a secret, shown on creation. You'll use it to verify every incoming request.
- 3
Add custom headers (optional)
Attach headers (e.g. an auth token) that Climails will send with each delivery to your endpoint.
Events you can subscribe to
- Email — email.delivered, email.bounce, email.complaint, email.unsubscribe, email.opened, email.clicked.
- SMS — sms.delivered, sms.failed.
- Contacts — contact.subscribed, contact.unsubscribed, contact.changed.
- Campaigns — campaign.finished.
Verify the signature
Each request carries X-Senderbox-Timestamp and X-Senderbox-Sig. Recompute the HMAC and compare — reject anything that doesn't match, and reject old timestamps to stop replays.
// signature = HMAC_SHA256(secret, timestamp + "." + rawBody)
import crypto from "node:crypto";
function verify(rawBody, headers, secret) {
const ts = headers["x-senderbox-timestamp"];
const sig = headers["x-senderbox-sig"]; // "sha256=<hex>"
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(ts + "." + rawBody)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}Retries and failures
Return a 2xx quickly to acknowledge. If your endpoint errors or times out, Climails retries with increasing backoff: 30s, 2m, 10m, 1h, 6h, 24h.
- After 6 failed attempts the delivery is dropped.
- A 4xx (except 408 and 429) is treated as terminal and not retried — fix the endpoint and it'll resume on the next event.
- Endpoints are SSRF-protected: internal/private addresses are refused.
Frequently asked questions
How do I verify a webhook is really from Climails?
Recompute HMAC-SHA256 over timestamp + "." + raw body with the webhook's secret and compare to X-Senderbox-Sig. Use a constant-time compare.
What happens if my server is down?
Deliveries retry with backoff (30s → 24h) across up to 6 attempts, so a short outage won't lose events.
Why was my webhook stopped retrying immediately?
A 4xx response (other than 408/429) is treated as a permanent error. Fix the handler; new events resume delivery.
Start sending in minutes
Create a free account, connect your domain and reach your audience across every channel — no credit card needed.
Free plan forever · No credit card required · Set up in minutes