Webhooks
HMAC-SHA256 signed events, filterable by type, with exponential-backoff retries and a per-webhook dead-letter queue.
Webhooks let your services react to identity events. A subscription's events list
is also its opt-in filter — subscribe to exactly the event types you want (or leave it
empty to receive everything). Qeet ID signs each payload with HMAC-SHA256, retries
with exponential backoff (up to 60 attempts), and parks permanent failures in a
dead-letter state you can inspect and retry per delivery.
Register a webhook
/v1/webhooksCreate a webhook/v1/tenants/{tenantID}/webhooksList webhooks/v1/webhooks/{id}/testSend a test event/v1/webhooks/{id}Delete a webhook{
"tenant_id": "…",
"url": "https://your-app.example/hooks/qeetid",
"events": ["session.revoked", "token.claims_change"]
}Some event types worth knowing about
Beyond per-domain events (agent lifecycle, OIDC client changes, …), two are purpose-built for real-time revocation — see Sessions → Real-time revocation signals.
Verify the signature
Every delivery carries an HMAC-SHA256 signature over the raw body. Always verify before processing — and verify against the raw bytes, not a re-serialized object.
import crypto from "node:crypto";
export async function POST(req: Request) {
const body = await req.text(); // raw bytes
const sig = req.headers.get("x-qeetid-signature") ?? "";
const expected = crypto
.createHmac("sha256", process.env.QEETID_WEBHOOK_SECRET!)
.update(body)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return new Response("bad signature", { status: 400 });
}
// process the event …
return new Response(null, { status: 204 });
}Make handlers idempotent
Delivery is at-least-once, so the same event may arrive more than once (e.g. after a retry). De-duplicate on the event id.
Retries & the dead-letter queue
If your endpoint returns non-2xx or times out, Qeet ID retries with exponential
backoff, up to maxDeliveryAttempts (60) tries. A delivery that exhausts every retry
is marked dead — inspect and manually retry it per webhook:
/v1/webhooks/{id}/deliveriesList a webhook's deliveries (incl. dead ones)/v1/webhooks/{id}/deliveries/{deliveryID}/retryRetry a dead deliveryAPI keys & service principals
Scoped, expirable, hashed API keys for backend access, and service principals for OAuth client_credentials.
Audit
An append-only, SHA-256 hash-chained audit log with a /verify integrity endpoint and behavioral-baseline anomaly detection — provable tamper-evidence most CIAM platforms don't offer.