Authentication
Generate a key from your settings page. Send it as a Bearer token:
curl https://your-deploy.example.com/api/v1/domains \ -H "Authorization: Bearer sgk_..."
Keys are stored as SHA-256 hashes. Rotate at any time โ the old key stops working immediately.
Domains
List domains
GET /api/v1/domains
โ { "domains": [{ "id": "uuid", "hostname": "...", "verifiedAt": "..." }] }Add a domain
POST /api/v1/domains
{ "hostname": "example.com" }
โ { "domain": { "id": "uuid", "verifyToken": "uuid" } }The response includes the verifyToken to drop into your homepage as<meta name="auditly-verify" content="...">.
Verify ownership
POST /api/v1/domains/{id}/verify
โ { "verified": true | false, "reason"?: "..." }Update a domain
PATCH /api/v1/domains/{id}
{
"schedule": "off" | "daily" | "weekly" | "monthly",
"schedulePillars": ["accessibility", "cookies", ...],
"directoryEnabled": true,
"organizationName": "Acme Corp",
"description": "..."
}Scans
Start a scan
POST /api/v1/scans
{
"domainId": "uuid",
"pillars": ["accessibility", "cookies", "trackers", "privacy"]
}
โ 202 { "scan": { "id": "...", "status": "queued" }, "creditsRemaining": 23 }
โ 402 { "error": "insufficient_credits", "cost": 4 }
โ 400 { "error": "domain_not_verified" }Get a scan
GET /api/v1/scans/{id}
โ {
"scan": { "id": "...", "status": "succeeded", "finishedAt": "...", "error": null },
"results": [
{
"pillar": "accessibility",
"score": 78,
"findingCount": 7,
"payload": { ... full result JSON ... }
},
...
]
}List scans
GET /api/v1/scans
โ { "scans": [{ "id": "...", "status": "...", "queuedAt": "...", "pillars": [...] }] }Public endpoints (no auth)
Verification badge SVG
GET /api/v1/badge?id={domainId}
โ image/svg+xml (5-minute cache)Audit lead submission
POST /api/v1/audit-leads
{ "email": "...", "hostname": null, "score": 0..100, "answers": { ... } }Errors
All error responses have the shape { "error": "...", "issues"?: [...] }. Common codes:
401โ missing or invalid API key400โ input failed Zod validation (issues array included)402โ insufficient credits404โ domain or scan not found / not yours
Rate limits
BullMQ runs scans serially per worker. The API itself is not yet rate-limited; if you hit it from a tight loop, please pace your requests at ~5 RPS to avoid contention. Production rate limiting via Vercel + Upstash is on the near-term roadmap.