Webhooks
Subscribe to lifecycle events out-of-band from the inference path. Create subscriptions from the dashboard.
Event types
key_created— a new API key was mintedkey_revoked— an API key was revokedwebhook_created— this webhook (or a sibling) was just createdwebhook_revoked— a webhook was disabled*— subscribe to everything
Delivery
Each event POSTs JSON to your URL with two headers:
X-Sable-Event— the event type, e.g.key_revokedX-Sable-Signature—sha256=<hex>HMAC of the raw body using your webhook secret
Verifying signatures
import { createHmac, timingSafeEqual } from "node:crypto";
function verifySable(req: Request, secret: string): boolean {
const sig = req.headers.get("x-sable-signature") ?? "";
const expected = "sha256=" + createHmac("sha256", secret)
.update(req.body)
.digest("hex");
return timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}Retries & auto-disable
Delivery is retried with exponential backoff: an immediate attempt, then
retries after 30s, 5m, and 1h — up to four attempts per event.
Each event records exactly one webhook_deliveries row capturing the number of
attempts and the last status seen. A 4xx never retries (it can't be fixed by
waiting); 5xx and network errors do.
After 5 consecutive events fail every attempt, the webhook is automatically
disabled (disabled_at is set) and stops receiving events until you re-create
it. A single delivered event resets the counter.