Void API — your domains, over REST.
Check availability, register and renew, switch nameservers, put a domain behind Cloudflare and manage its DNS, security switches and redirects — from your own code, on the same account and balance as the bot.
Webhooks
we call you when something happens to a domainRegister an HTTPS endpoint and we POST a signed JSON event to it — a domain landing on a blocklist (Google Safe Browsing, MetaMask, registrar hold) is the one you most likely want, but registration, renewal and expiry are there too. Up to 5 endpoints per account. Events are queued and retried with backoff (1 min → 5 → 30 → 2 h → 6 h → 24 h); an endpoint that fails 50 deliveries in a row is switched off (active: false) until you re-enable it.
Events
| event | when | data |
|---|---|---|
domain.blocked | the 10-minute sweep finds the name on a new blocklist | domainId, domain, flags[] (new: google · metamask · registrar), allFlags[] |
domain.unblocked | a flag disappears again | domainId, domain, cleared[], allFlags[] |
domain.registered | registration succeeded (bot or API) | domainId, domain, price, expiresAt |
domain.renewed | manual or automatic renewal | domainId, domain, price, expiresAt |
domain.expiring | 7, 3 and 1 day before expiry | domainId, domain, daysLeft, expiresAt, autoRenew |
domain.expired | expiry date passed; 30-day renewal window opens | domainId, domain, expiresAt, renewableUntil |
ping | you called /test | message |
Delivery format
POST https://your.host/void-webhook
Content-Type: application/json
X-Void-Event: domain.blocked
X-Void-Delivery: 5c1b0f7e-… # unique per delivery — use it for idempotency
X-Void-Timestamp: 1756731600 # unix seconds
X-Void-Signature: sha256=8f3c… # HMAC-SHA256(secret, timestamp + "." + raw body)
{ "id": "5c1b0f7e-…", "event": "domain.blocked", "createdAt": "2026-09-01T13:00:00.000Z",
"data": { "domainId": "0a79…", "domain": "example.org", "flags": ["google"], "allFlags": ["google"] } }Answer 2xx within 10 seconds; anything else (or a redirect) counts as a failure and is retried. Verify the signature over the raw body before parsing it, and reject timestamps older than a few minutes:
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, headers, rawBody) {
const ts = headers["x-void-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = "sha256=" + createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const got = headers["x-void-signature"] ?? "";
return got.length === expected.length && timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}The list of event names you can subscribe to.
{ "ok": true, "data": [ { "id": "b2e1…", "url": "https://your.host/void-webhook", "events": ["domain.blocked", "domain.unblocked"],
"active": true, "failures": 0, "lastStatus": 200, "lastDeliveredAt": "2026-09-01T13:00:02.000Z", "createdAt": "…" } ] }| body | type | |
|---|---|---|
urlrequired | URL | public https:// endpoint (no localhost / private ranges / credentials in the URL) |
events | string[] | subset of the event names; empty or omitted = everything |
{ "url": "https://your.host/void-webhook", "events": ["domain.blocked", "domain.unblocked"] }
{ "ok": true, "data": { "id": "b2e1…", "url": "…", "events": ["domain.blocked", "domain.unblocked"], "active": true, …,
"secret": "whsec_…" } } // the secret is returned only here — store it{ "active": true | false } — pause an endpoint, or re-enable one we switched off after repeated failures (the failure counter resets).
Removes the endpoint and its delivery history.
Queues a ping event to this endpoint; watch it land in /deliveries within ~15 seconds.
Issues a new secret (returned once); deliveries queued after the call are signed with it.
{ "ok": true, "data": [ { "id": "5c1b…", "event": "ping", "status": "SENT", "attempts": 1, "lastStatus": 200, "lastError": null,
"createdAt": "…", "sentAt": "…", "nextAt": null } ] } // status: PENDING · SENT · FAILED