API Quickstart
This guide gets you from zero to a working API call in under five minutes. It uses
the live /v1 surface — the same contract published at
/api/v1/openapi.json and
documented in the full API reference.
Prerequisites
Section titled “Prerequisites”- A VisibilityIQ account with at least one project.
- A completed audit on that project (run one first if you have none — the
auditsendpoint returnsnulluntil a crawl finishes).
Step 1 — Mint an API key
Section titled “Step 1 — Mint an API key”- Sign in and open Developer API at
/dashboard/developer. - Click Create key, name it (e.g.
quickstart-test), and grant the scopes you need. For this walkthrough, selectaudits:readandrankings:read. - Copy the key the moment it appears. The secret is shown once — only its SHA-256 hash is stored, so a lost key is regenerated, never recovered.
Keys are prefixed viq_live_. Never embed one in client-side code; treat it like a
password.
Step 2 — Authenticate
Section titled “Step 2 — Authenticate”Every /v1 endpoint takes a Bearer key in the Authorization header. Export it once
so the examples below stay copy-pasteable:
export VIQ_KEY="viq_live_xxxxxxxxxxxxxxxxxxxxxxxx"A missing, malformed, unknown, or revoked key returns 401 — the auth chain never
reveals which, so you cannot probe for valid keys. A key that authenticates but lacks
the endpoint’s scope returns 403 {"error":"missing_scope:<scope>"}.
Step 3 — Call a real endpoint
Section titled “Step 3 — Call a real endpoint”The cheapest first call is the latest-audit summary. It reads your own data from D1,
so it costs 0 credits and is safe to poll. Replace uscoinshows with your own
project ID (visible in the dashboard URL):
curl https://visibilityiq365.com/api/v1/audits/uscoinshows \ -H "Authorization: Bearer $VIQ_KEY"Step 4 — Handle the response
Section titled “Step 4 — Handle the response”Success responses use the envelope { "success": true, "data": { … } }; failures use
{ "success": false, "error": "<code>" }. A real 200 body:
{ "success": true, "data": { "projectId": "uscoinshows", "domain": "uscoinshows.com", "audit": { "id": "audit-1781524209869-wjp57j", "status": "completed", "score": 93, "totalIssues": 16897, "criticalIssues": 0, "warnings": 727, "notices": 16170, "pagesCrawled": 5000, "completedAt": "2026-06-15T13:32:06.473Z", "createdAt": "2026-06-15T11:50:09.869Z" } }}audit is null when the project has no completed audit yet — check for it before
reading audit.score. In code:
const res = await fetch( `https://visibilityiq365.com/api/v1/audits/${projectId}`, { headers: { Authorization: `Bearer ${process.env.VIQ_KEY}` } },);
if (res.status === 401) throw new Error('Bad or revoked API key');if (res.status === 403) throw new Error('Key is missing the audits:read scope');if (res.status === 429) { const wait = Number(res.headers.get('Retry-After') ?? '60'); throw new Error(`Rate limited — retry after ${wait}s`);}
const body = await res.json();if (!body.success) throw new Error(`API error: ${body.error}`);
const audit = body.data.audit;if (audit === null) { console.log('No completed audit yet — run a crawl first.');} else { console.log(`Score ${audit.score}, ${audit.criticalIssues} critical issues.`);}Reading the credit headers
Section titled “Reading the credit headers”Every response carries credit and rate-limit state in headers — read them rather than guessing your remaining budget:
| Header | Meaning |
|---|---|
X-Credits-Cost | Credits charged for this request (0 for own-data reads) |
X-Credits-Remaining | Credits left in the current monthly period |
X-RateLimit-Remaining | Calls left in the current per-minute window |
Retry-After | Seconds to wait before retrying (on 429 only) |
A failed request (4xx/5xx) is refunded — you are charged only on 200. A spent
budget returns 402 {"error":"credit_exhausted"}.
Next steps
Section titled “Next steps”- Full API reference — every endpoint, scope, credit cost, and the complete error model.
- Trigger an audit programmatically — start a crawl and poll for completion.
- Fetch backlink data — pull referring-domain
profiles via
/v1/backlinks. - Set up webhooks — get pushed an
audit.completedevent instead of polling. - SERP overlay endpoint — the
/v1/serp/overlayread powering the browser extension.