For agencies and platforms
Run the full SEOking audit programmatically and get every finding back as JSON: scores, severities, evidence and the affected URLs. Built for agencies auditing a client book, and for platforms that want to show their users what's wrong with their site.
Every request carries your key in an X-API-Key header. Keys are issued with a daily quota. Ask us for one.
curl -X POST http://18.202.16.187/api/v1/scan \
-H "X-API-Key: bza_your_key_here" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com"}'{
"job_id": "wU3f...",
"domain": "example.com",
"state": "queued",
"poll": "http://18.202.16.187/api/v1/job/wU3f..."
}Audits crawl multiple pages and wait on Google's PageSpeed API, so they run asynchronously. Poll every second or two; a typical audit finishes in 30–90 seconds.
curl http://18.202.16.187/api/v1/job/wU3f... \ -H "X-API-Key: bza_your_key_here"
{ "state": "running", "percent": 62, "message": "Crawled 7/11 pages" }curl http://18.202.16.187/api/v1/report/example.com \ -H "X-API-Key: bza_your_key_here"
{
"domain": "example.com",
"score": 71, "grade": "C", "verdict": "Needs work",
"counts": { "checks": 58, "passed": 41, "failed": 15, "critical": 2 },
"categories": {
"security": { "label": "Security & trust", "score": 88 },
"email": { "label": "Email deliverability", "score": 42 }
},
"findings": [
{
"key": "spf_single",
"category": "email",
"label": "Exactly one SPF record",
"state": "fail",
"severity": "critical",
"detail": "2 SPF records are published. RFC 7208 allows exactly one...",
"fix": "Delete both records and publish one merged record...",
"evidence": "v=spf1 include:_spf.google.com ~all\nv=spf1 include:...",
"affected": []
}
]
}For an agency auditing a client book. Returns a portfolio URL and a CSV. Batches run in their own lane, one domain at a time, so the interactive audit stays responsive, so expect roughly a minute per domain.
curl -X POST http://18.202.16.187/api/v1/batch \
-H "X-API-Key: bza_your_key_here" \
-H "Content-Type: application/json" \
-d '{"label": "Client book", "domains": "one.com\ntwo.com\nthree.com"}'{
"batch_id": 12, "accepted": 3, "rejected": [],
"portfolio": "http://18.202.16.187/batch/<token>",
"csv": "http://18.202.16.187/batch/<token>.csv"
}Register an endpoint and stop polling. Events: scan.completed, batch.completed, monitor.regression.
curl -X POST http://18.202.16.187/api/v1/webhooks \
-H "X-API-Key: bza_your_key_here" \
-H "Content-Type: application/json" \
-d '{"url": "https://yourapp.example/hooks/bz",
"events": ["monitor.regression"]}'The response carries a secret, shown once. Every delivery is signed:
X-BZ-Event: monitor.regression
X-BZ-Delivery: d7Kx9… unique per delivery; deduplicate on this
X-BZ-Timestamp: 1786930000
X-BZ-Signature: sha256=… HMAC-SHA256 over "{timestamp}.{raw body}"Verify in your own code before trusting a payload:
expected = hmac.new(secret, f"{timestamp}.".encode() + raw_body,
hashlib.sha256).hexdigest()
assert hmac.compare_digest(f"sha256={expected}", signature)
assert abs(time.time() - int(timestamp)) < 300 reject replaysX-BZ-Delivery.| Code | Meaning |
|---|---|
| 200 | Success. |
| 400 | The domain could not be parsed, or resolves to a private network. |
| 401 | Missing or revoked API key. |
| 404 | No audit exists for that domain yet. POST /api/v1/scan first. |
| 429 | Daily quota reached. |
"state": "skipped" could not be measured and are excluded from scoring.