Skip to content

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.

{
"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"]
}
}
  • findingCounts — total active findings by severity after this audit
  • newFindings — 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
{
"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
}
}
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');
});

Webhooks are strongly preferred over polling for production integrations:

PollingWebhooks
LatencyUp to poll intervalNear-real-time (< 30s)
API callsMany (while waiting)One (to fetch findings after event)
Missed eventsPossible if poll gapsRetried automatically
ComplexitySimple (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.