Skip to content

Trigger an Audit

This guide shows the full lifecycle of programmatically triggering an audit — start, poll, fetch results.

Terminal window
curl -X POST https://visibilityiq365.com/api/v1/projects/proj_abc123/audits \
-H "Authorization: Bearer vis_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"crawlDepth": null,
"renderMode": "html",
"botSimulation": ["Googlebot", "GPTBot", "ClaudeBot"]
}'

Response:

{
"ok": true,
"data": {
"auditId": "audit_xyz789",
"status": "running",
"startedAt": "2026-06-15T14:23:00Z"
}
}

Poll the audit status endpoint until status is completed or failed:

async function waitForAudit(projectId: string, auditId: string, apiKey: string) {
const maxWaitMs = 30 * 60 * 1000; // 30 minutes
const pollInterval = 15_000; // 15 seconds
const start = Date.now();
while (Date.now() - start < maxWaitMs) {
const res = await fetch(
`https://visibilityiq365.com/api/v1/projects/${projectId}/audits/${auditId}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const { data } = await res.json();
if (data.status === 'completed') return data;
if (data.status === 'failed') throw new Error(`Audit failed: ${data.error}`);
await new Promise(r => setTimeout(r, pollInterval));
}
throw new Error('Audit timed out');
}

Typical completion times:

  • Small site (< 100 pages): 1–3 minutes
  • Medium site (100–1,000 pages): 5–15 minutes
  • Large site (1,000–10,000 pages): 15–60 minutes

Using webhooks instead of polling is strongly recommended for production integrations — see Webhooks.

Terminal window
# All Critical findings, paginated
curl "https://visibilityiq365.com/api/v1/projects/proj_abc123/issues?severity=critical&auditId=audit_xyz789&limit=50" \
-H "Authorization: Bearer vis_live_YOUR_KEY_HERE"
Terminal window
# All findings regardless of severity
curl "https://visibilityiq365.com/api/v1/projects/proj_abc123/issues?auditId=audit_xyz789&limit=50&offset=0" \
-H "Authorization: Bearer vis_live_YOUR_KEY_HERE"
ParameterTypeDescription
severitycritical|high|medium|low|infoFilter by severity
scopepage|template|site|clusterFilter by scope
checkIdstringFilter by specific check (e.g., canonical.loop)
auditIdstringFilter to a specific audit run (defaults to latest)
limitnumberResults per page (max 1000, default 50)
offsetnumberPagination offset
{
"ok": true,
"data": {
"findings": [ /* AuditFinding[] */ ],
"total": 142,
"page": 1,
"limit": 50,
"auditId": "audit_xyz789",
"completedAt": "2026-06-15T14:38:00Z",
"pagesCrawled": 847
}
}

For CI/CD pipelines, the typical pattern is:

  1. Trigger audit after deployment
  2. Poll (or use webhook) until complete
  3. Fetch Critical + High findings
  4. Fail the pipeline if any Critical findings are new (not present in previous audit)
  5. Post finding summary as a PR comment or CI annotation

See CI Integration guide for a complete working example.