Audit Webhooks
When an audit completes (or fails), VisibilityIQ can push an audit.completed or audit.failed event to your registered webhook endpoints.
See Webhooks integration guide for setup, signature verification, and idempotency patterns.
audit.completed payload
Section titled “audit.completed payload”{ "id": "evt_abc123def456", "event": "audit.completed", "projectId": "proj_xyz789", "timestamp": "2026-06-15T14:38:00Z", "data": { "auditId": "audit_qqq111", "domain": "example.com", "pagesCrawled": 847, "duration": 892, "findingCounts": { "critical": 2, "high": 14, "medium": 47, "low": 103, "info": 8 }, "newFindings": { "critical": 1, "high": 3 }, "fixedFindings": { "high": 1, "medium": 2 }, "crawlMode": "rendered", "botsSimulated": ["Googlebot", "GPTBot", "ClaudeBot"] }}Key fields
Section titled “Key fields”findingCounts— total active findings by severity after this auditnewFindings— findings that are new in this audit (didn’t exist in the previous one)fixedFindings— findings from the previous audit that are no longer present (resolved)duration— crawl duration in seconds
audit.failed payload
Section titled “audit.failed payload”{ "id": "evt_xyz789abc", "event": "audit.failed", "projectId": "proj_xyz789", "timestamp": "2026-06-15T14:10:00Z", "data": { "auditId": "audit_qqq222", "domain": "example.com", "error": "Crawl blocked by robots.txt — Disallow: / for VisibilityIQ", "pagesCrawled": 0, "duration": 8 }}Recommended handler logic
Section titled “Recommended handler logic”app.post('/webhooks/visibilityiq', async (req, res) => { // 1. Verify signature (see Webhooks guide)
const { event, data, projectId } = req.body;
if (event === 'audit.completed') { // Alert if new Critical findings appeared if (data.newFindings.critical > 0) { await alertTeam({ message: `${data.newFindings.critical} new Critical finding(s) on ${data.domain}`, auditUrl: `https://visibilityiq365.com/projects/${projectId}/audit/${data.auditId}` }); }
// Fetch and store findings in your own system const findings = await fetchFindings(projectId, data.auditId); await storeFindings(findings); }
res.status(200).send('ok');});Using webhooks instead of polling
Section titled “Using webhooks instead of polling”Webhooks are strongly preferred over polling for production integrations:
| Polling | Webhooks | |
|---|---|---|
| Latency | Up to poll interval | Near-real-time (< 30s) |
| API calls | Many (while waiting) | One (to fetch findings after event) |
| Missed events | Possible if poll gaps | Retried automatically |
| Complexity | Simple (just loop) | Requires public HTTPS endpoint |
For CI/CD pipelines on ephemeral infrastructure (where a persistent HTTPS endpoint isn’t available), polling with a reasonable interval (15–30 seconds) is acceptable. Use webhooks for production dashboards, Slack integrations, and monitoring systems.