Webhooks push signed events to your backend when a moderation decision is made, a review is resolved, or a redaction finishes. Deliveries are asynchronous, so they never slow your API calls.
Create endpoints per project from Dashboard → Webhooks and subscribe to the events you care about.
i
Every delivery is HMAC-signed. Always verify the signature before trusting an event — the SDK helpers do this for you.
Event types
Subscribe an endpoint to one or more events. Moderation projects emit moderation and review events; redaction projects emit redaction.completed.
Event
Fired when
moderation.completed
Every successful POST /moderate decision.
moderation.review_required
A moderation decision was queued for manual review.
review.approved
A queued review was approved in the dashboard.
review.rejected
A queued review was rejected in the dashboard.
redaction.completed
Every successful POST /redact on a redaction project.
Event payload
Every delivery is a JSON envelope with a stable shape. The event-specific fields live under data.
The signature is v1=<hex> where the HMAC SHA-256 is computed over `${timestamp}.${rawBody}` using your endpoint secret. Verify against the raw request body — not a re-serialized object.
Install @visoracloud/client. The framework handlers verify the signature, parse the event, and narrow event.data by event.type so no casting is required.
// Throws VisoraWebhookSignatureError if the signature is invalid.
constevent=constructWebhookEvent({
secret:process.env.VISORA_WEBHOOK_SECRET!,
payload:rawBody,
timestamp:req.headers["visora-timestamp"],
signature:req.headers["visora-signature"],
});
Secret rotation
Rotate a signing secret from the webhook detail page. The previous secret stays valid for 24 hours so in-flight deliveries keep verifying. Accept both during the window:
Verify during rotation
// During rotation, accept the current and previous secret for 24 hours.
constvalid=verifyWebhookSignature({
secret:[
process.env.VISORA_WEBHOOK_SECRET!,
process.env.VISORA_PREVIOUS_WEBHOOK_SECRET!,
],
payload:rawBody,
timestamp,
signature,
});
Delivery semantics
Property
Behavior
Async
Deliveries never block the /moderate or /redact response.
Signed
HMAC SHA-256 over `timestamp.rawBody` with your endpoint secret.
Retried
Failed deliveries are retried with backoff.
Dead-letter
After repeated failures the event moves to a DLQ; you can retry it from the dashboard.
Per project
Each endpoint belongs to a project and only receives that project's events.
Respond with a 2xx quickly to acknowledge receipt. Non-2xx responses and timeouts are retried; persistent failures land in the dead-letter queue, where you can inspect and retry them from Dashboard → Webhooks.