Developers
Run accessibility scans from your pipeline, pull scores and issues into your own dashboards, and fetch ready-to-apply fixes for a site you own. Everything the WordPress plugin does, it does through this API.
https://scanpoof.com/api/v1Get an API key →curl -X POST https://scanpoof.com/api/v1/activate \
-H "Authorization: Bearer adap_your_key_here" \
-H "Content-Type: application/json" \
-d '{"domain":"scanpoof.com"}'Send your key as a bearer token on every request. Keys start with adap_. We store only a SHA-256 hash of the key, so a lost key cannot be recovered — generate a new one instead.
Authorization: Bearer adap_your_key_here
One key, one site. A key binds to the first domain it is activated on and only works for that domain afterwards. This keeps a leaked key from touching the rest of your account. Move a key with /deactivate, or mint a new one per site.
Errors return a JSON body with a human-readable error and, where you might want to branch on it, a stable code.
{ "error": "Activate this key on the site first.", "code": "activate_required" }| Status | Code | Meaning |
|---|---|---|
| 401 | — | Missing, malformed or unknown API key. |
| 402 | upgrade_required | Applying fixes needs a paid plan. Scanning still works. |
| 403 | activate_required | The key has not been activated on a domain yet. |
| 403 | no_site | That domain is not in your account. |
| 403 | verify_required | The domain is added but ownership is not verified. |
| 404 | — | No matching site, scan or resource. |
| 409 | bound_elsewhere | This key is already active on another domain. |
/api/v1/meWho this key belongs to, and every site in the account with its latest accessibility score. Useful as a connectivity check.
auth: API key
curl https://scanpoof.com/api/v1/me -H "Authorization: Bearer adap_..."
Response
{
"org": { "name": "Scanpoof", "plan": "agency" },
"sites": [
{ "id": "cmx...", "domain": "scanpoof.com", "score": 76 }
]
}/api/v1/activateBind this key to one domain. Required before /fixes, /rescan and /scan-status will work.
auth: API key
| Field | Meaning |
|---|---|
| domain | The site's hostname. Scheme, port, path and a leading www. are stripped for you. |
curl -X POST https://scanpoof.com/api/v1/activate \
-H "Authorization: Bearer adap_..." \
-H "Content-Type: application/json" \
-d '{"domain":"scanpoof.com"}'Response
{ "activated": true, "domain": "scanpoof.com" }/api/v1/deactivateRelease the key from its domain so it can be activated somewhere else.
auth: API key
curl -X POST https://scanpoof.com/api/v1/deactivate -H "Authorization: Bearer adap_..."
Response
{ "deactivated": true }/api/v1/overviewThe full dashboard bundle for the activated site: composite score and letter grades, severity counts, 30-scan history, top issues ranked by impact with a fix-effort estimate, per-tool scores (performance, SEO, AI-readiness, security, uptime), remediation progress and alerts.
auth: API key · must be activated
Response
{
"site": "scanpoof.com",
"overall": 61,
"grades": { "overall": "D", "accessibility": "F", "performance": "F",
"seo": "D", "aeo": "B", "security": "B" },
"score": 76,
"counts": { "critical": 0, "serious": 12, "moderate": 28, "minor": 5, "total": 45 },
"history": [ { "at": "2026-09-14T07:00:00Z", "score": 61, "issues": 57 } ],
"topIssues": [
{ "ruleId": "image-of-text-suspect", "name": "Text baked into an image",
"impact": "serious", "wcag": "1.4.5", "occurrences": 43,
"effort": "20 min", "fixBy": "content" }
],
"tools": { "performance": { "score": 41 }, "aeo": { "score": 67 } },
"fixes": { "remediation": { "open": 3, "fixed": 1 } },
"alerts": []
}/api/v1/fixesEverything needed to actually repair the site: a remediation stylesheet, per-element patches (alt text, labels, language), corrected contrast colours, and the issues that no tool can fix automatically.
auth: API key · must be activated · paid plan
Response
{
"plan": "agency",
"aiFixes": true,
"sites": [{
"site": "scanpoof.com",
"scannedAt": "2026-09-14T07:00:00Z",
"pagesScanned": 34,
"score": 76,
"css": "/* remediation stylesheet */",
"patches": [ { "selector": "img[src$='logo.png']", "alt": "Company logo" } ],
"contrast": [ { "selector": ".menu a", "color": "#5a3b2e" } ],
"unfixable": [ { "ruleId": "pdf-no-text-layer", "occurrences": 4,
"reason": "This PDF is a scan with no text inside…" } ],
"issues": [ { "ruleId": "image-alt", "wcag": "1.1.1", "impact": "critical",
"selector": "img.hero", "occurrences": 2,
"explanation": "…", "wpFix": "…", "codeFix": "…" } ]
}]
}explanation, wpFix and codeFix fields are populated only with the AI Fix add-on./api/v1/rescanQueue a fresh scan of the activated site. If a scan is already queued or running you get that one back instead of a duplicate.
auth: API key · must be activated
curl -X POST https://scanpoof.com/api/v1/rescan -H "Authorization: Bearer adap_..."
Response
{ "queued": true, "runId": "cmx..." }/api/v1/scan-statusPoll the latest scan for the activated site — use it to show progress, or to block a deploy until the scan finishes.
auth: API key · must be activated
Response
{
"status": "running", // queued | running | done | error | none
"active": true,
"runId": "cmx...",
"pagesScanned": 12,
"score": null, // filled in once status is "done"
"startedAt": "2026-09-20T07:00:00Z",
"finishedAt": null
}/api/v1/scanScan any single URL, without adding it to your account. Handy for auditing a page before you own it. Returns immediately with an id to poll.
auth: API key
| Field | Meaning |
|---|---|
| url | The page to scan. https:// is assumed if you leave the scheme off. |
curl -X POST https://scanpoof.com/api/v1/scan \
-H "Authorization: Bearer adap_..." \
-H "Content-Type: application/json" \
-d '{"url":"https://scanpoof.com/pricing"}'Response
{ "id": "cmx...", "status": "running" } // 201 Created/api/v1/scan/{id}Fetch the result of a single-URL scan.
auth: API key
Response
{
"id": "cmx...",
"url": "https://scanpoof.com/pricing",
"status": "done",
"score": 64,
"critical": 1, "serious": 4, "moderate": 2, "minor": 0,
"issues": [ { "ruleId": "image-alt", "impact": "critical",
"wcag": "1.1.1", "help": "Images must have alt text", "count": 2 } ]
}These two are public — WordPress fetches them with no credentials, and the plugin is inert until a valid key is activated inside it.
/api/v1/plugin-update— current version, changelog and download URL./api/v1/plugin.zip— the plugin itself, always the latest build.The plugin identifies itself with an X-Scanpoof-Plugin: 1.2.8 header so the dashboard can show which version each site is running. Your own integrations can send it too.
Queue a scan, wait for it, and stop the pipeline if the score drops below your bar.
#!/usr/bin/env bash
set -euo pipefail
API="https://scanpoof.com/api/v1"
AUTH="Authorization: Bearer $SCANPOOF_KEY"
MIN_SCORE=70
curl -fsS -X POST "$API/rescan" -H "$AUTH" > /dev/null
for _ in $(seq 1 60); do
body=$(curl -fsS "$API/scan-status" -H "$AUTH")
[ "$(echo "$body" | jq -r .active)" = "false" ] && break
sleep 20
done
score=$(curl -fsS "$API/scan-status" -H "$AUTH" | jq -r .score)
echo "accessibility score: $score"
[ "$score" -ge "$MIN_SCORE" ] || { echo "below $MIN_SCORE — failing build"; exit 1; }Something missing or unclear? Email [email protected] — a real person answers. The API is versioned under /v1; breaking changes get a new version, and new fields are added without one.