Webhook (DNS / domain events)
Webhooks that fire when DNS or domain state changes (verified, cert issued, expired). The plumbing for keeping your app in sync with the domain platform.
Webhooks for DNS and domain events are HTTP callbacks fired by a domain platform (or DNS provider) when something happens to a domain you've registered with it. They let your app react to state changes without polling.
The common events:
domain.verified— your customer added the DNS records you asked for and they propagated.domain.cert.issued— TLS cert is ready, the hostname now serves HTTPS.domain.cert.renewed— auto-renewal succeeded.domain.cert.failed— renewal failed; needs attention.domain.cert.expiring— cert is N days from expiration.domain.unreachable— DNS or cert check failed; customer probably broke something on their side.domain.deleted— record removed from the platform.
What a webhook payload looks like
{
"id": "evt_aBc123",
"type": "domain.verified",
"createdAt": "2026-05-13T12:00:00Z",
"data": {
"domain": "app.customer.com",
"workspaceId": "ws_xYz",
"verifiedAt": "2026-05-13T11:59:42Z"
}
}
With an HMAC signature header so you can verify the sender:
Webhook-Signature: t=1715601600,v1=4f6a3d...
You compute HMAC-SHA256 over the body with your shared signing secret, compare to the v1 value, accept or reject.
Why webhooks beat polling
For a platform like Domainee or a custom-domain product, the alternative to webhooks is polling: every minute, every customer's domain status gets checked.
- Polling at 1 minute granularity = 60 reqs/customer/hour = 1.4M reqs/customer/month.
- Webhooks fire on change = ~3-5 reqs/customer/month.
Webhooks are 300,000x more efficient. Polling is fine until you have ~50 customers, then it stops scaling.
Idempotency
Webhooks can be delivered more than once. Network blips, retries on receiver 5xx, duplicate events from the platform. Your receiver has to dedupe:
- Each event has an
id. Track which IDs you've processed (Redis SET or DB table). - On receipt: check ID, if seen, return 200 and stop. If new, process, store ID, return 200.
If you don't dedupe, you'll send duplicate emails to customers when "domain verified" fires twice.
Failure handling on the receiver side
Webhook senders retry on non-2xx responses, usually with exponential backoff for ~24 hours. After that, they drop the event. Your receiver should:
- Return 200 quickly. Don't do heavy work synchronously; enqueue and return.
- If processing fails, return 5xx so the sender retries. But fix the bug, because retries fill your queue.
- Have a "replay" endpoint at the sender's dashboard. If your webhook handler was broken for 6 hours, you can re-deliver missed events instead of reconstructing state.
In a SaaS
If you're building a custom-domain platform, webhooks are table stakes. If you're integrating one, the webhook endpoint is one of the first three things you build: registration, listing, webhook handler.