Webhooks
Event delivery for domain lifecycle and billing changes.
DomainGenius posts JSON events to your endpoint over HTTPS when something changes server-side — registration completing, balance dropping, a domain expiring soon.
Configure
In the dashboard, go to Settings → Webhooks and add an endpoint URL. Pick the events you care about. We sign every request.
Events
| Event | Fires when |
|---|---|
domain.registered | Registry confirms registration |
domain.transfer.started | Transfer-in initiated, awaiting auth code |
domain.transfer.completed | Transfer-in finished |
domain.expiring.30d / .7d / .1d | Domain expiry within window, no auto-renew |
domain.expired | Past expiry |
domain.deleted | Registry-deleted (after grace) |
dns.changed | A record was created, updated, or deleted |
balance.low | Org balance dropped below the auto-top-up trigger |
invoice.paid | Top-up or subscription invoice paid |
Payload shape
{
"id": "evt_01HF82...",
"type": "domain.registered",
"created": "2026-05-01T08:42:00Z",
"data": {
"domain": "example.com.au",
"org_oid": "org_01HF80...",
"expires_at": "2027-05-01T00:00:00Z"
}
}Verify the signature
Every request carries DG-Signature: t=<unix>,v1=<hex>:
import crypto from "node:crypto";
const verify = (raw: string, header: string, secret: string) => {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${raw}`)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
};Reject requests where t is older than five minutes; that’s the replay window.
Retries
We retry non-2xx responses with exponential backoff: 30s, 2m, 10m, 1h, 6h, 24h. After 24h of failures the endpoint is paused and you get an email.
Respond 200 OK as soon as you’ve durably enqueued the event. Long handlers cause timeouts and retries.
Inbound webhooks
The endpoints under /api/v1/webhooks/stripe and /api/v1/webhooks/clerk are inbound — Stripe and Clerk POST to us. They are not configurable from your side and not part of the public API surface.