Skip to main content

API Documentation

Integrate CompliaScan into your development workflow with our REST API. Programmatically create scans, retrieve results, enforce CI/CD quality gates, and receive real-time webhook notifications.

Base URL: https://compliascan.com/api/v1

Authentication

All API requests require a Bearer token in the Authorization header. API keys are prefixed with cs_ and can be generated from your dashboard settings.

Authorization: Bearer cs_live_your_api_key_here

Rate Limits: Endpoints are rate-limited per plan — Pro: 200/min, Business: 1000/min. API access requires a Pro or Business plan. All responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. Exceeding the limit returns 429 with a Retry-After header.

Endpoints

POST/api/v1/scan

Create a new accessibility scan. The scan runs asynchronously and returns immediately with a scan ID you can use to poll for results.

Request Body

ParameterTypeRequiredDescription
urlstringYesThe URL to scan. Must be a valid, publicly accessible URL.
multiPagebooleanNoWhen true, crawls and scans linked pages from the root URL. Defaults to false.
callbackUrlstringNoA webhook URL to receive a POST notification when the scan completes.
waitForSelectorstringNoCSS selector to wait for before scanning. Useful for SPAs that load content dynamically.
waitTimenumberNoAdditional wait time in milliseconds (0-10000) after page load before scanning.

Response 202 Accepted

{
  "scanId": "scn_a1b2c3d4e5f6",
  "status": "pending",
  "statusUrl": "/api/v1/scan/scn_a1b2c3d4e5f6"
}
GET/api/v1/scan/{scanId}

Retrieve the results of a completed scan. While the scan is still running, the response will include "status": "running". Poll this endpoint until the status changes to "completed".

Response 200 OK

{
  "id": "scn_a1b2c3d4e5f6",
  "url": "https://example.com",
  "status": "completed",
  "score": 72,
  "totalIssues": 18,
  "criticalCount": 2,
  "seriousCount": 5,
  "moderateCount": 7,
  "minorCount": 4,
  "rulesChecked": 108,
  "rulesPassed": 90,
  "pageTitle": "Example Domain",
  "scanDurationMs": 12450,
  "pagesScanned": 1,
  "pagesTotal": 1,
  "createdAt": "2026-02-15T10:30:00Z",
  "completedAt": "2026-02-15T10:30:12Z",
  "pdfUrl": "https://compliascan.com/api/v1/scan/scn_a1b2c3d4e5f6/pdf",
  "issues": [
    {
      "ruleId": "color-contrast",
      "impact": "serious",
      "description": "Elements must have sufficient color contrast",
      "helpText": "Ensure foreground and background colors meet WCAG 2 AA minimum contrast ratio thresholds.",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast",
      "wcagCriteria": ["1.4.3"],
      "nodeCount": 3,
      "affectedNodes": [
        {
          "html": "<p class=\"light-text\">...</p>",
          "selector": ".hero > p.light-text",
          "failureSummary": "Element has insufficient color contrast of 2.8:1 (foreground: #999999, background: #ffffff, expected ratio: 4.5:1)"
        }
      ]
    }
  ]
}
GET/api/v1/scan/{scanId}/gate

CI/CD quality gate endpoint. Returns a pass or fail verdict based on configurable thresholds. Use this in your deployment pipeline to block releases that introduce accessibility regressions.

Query Parameters

ParameterTypeDescription
thresholdnumberMinimum accessibility score to pass (0-100). Defaults to 70.
maxCriticalnumberMaximum critical issues allowed before failing. Optional.
maxSeriousnumberMaximum serious issues allowed before failing. Optional.

Response 200 OK202 Accepted

Note: If the scan is still pending or running, this endpoint returns 202 Accepted with "status": "pending" or "status": "running". Poll until you receive a 200 OK with the full gate verdict.
{
  "passed": true,
  "score": 92,
  "threshold": 70,
  "gates": {
    "score": { "passed": true, "actual": 92, "threshold": 70 },
    "critical": { "passed": true, "actual": 0, "threshold": 1 }
  },
  "summary": {
    "totalIssues": 5,
    "critical": 0,
    "serious": 2,
    "moderate": 2,
    "minor": 1
  },
  "scanUrl": "https://compliascan.com/scan/scn_a1b2c3d4e5f6"
}
GET/api/v1/export

Export all scan data for your account as JSON. Includes full scan results and monitored sites. Useful for data warehousing, custom reporting, or backing up your compliance history. Returns up to 500 most recent scans.

Response 200 OK

{
  "exportedAt": "2026-02-15T12:00:00Z",
  "userId": "user_abc123",
  "plan": "pro",
  "scans": [
    {
      "id": "scn_a1b2c3d4e5f6",
      "url": "https://example.com",
      "status": "completed",
      "score": 72,
      "totalIssues": 18,
      "criticalCount": 2,
      "seriousCount": 5,
      "moderateCount": 7,
      "minorCount": 4,
      "rulesChecked": 108,
      "rulesPassed": 90,
      "createdAt": "2026-02-15T10:30:00Z",
      "completedAt": "2026-02-15T10:30:12Z",
      "results": [...]
    }
  ],
  "sites": [
    {
      "id": "uuid",
      "domain": "example.com",
      "name": "Example Site",
      "lastScore": 85,
      "monitoringEnabled": true,
      "monitoringFrequency": "weekly"
    }
  ],
  "totalScans": 142,
  "totalSites": 3
}
POST/api/v1/scan/{scanId}/fixPro+

Generate fix instructions for all violations in a completed scan. Uses your BYOK API key (OpenAI, Anthropic, or Gemini) if configured, otherwise returns deterministic rule-based suggestions.

Response 200 OK

{
  "fixes": [
    {
      "scanResultId": "uuid",
      "ruleId": "color-contrast",
      "impact": "serious",
      "instruction": "Increase the contrast ratio...",
      "codeSnippet": "<!-- Before -->\n<p style=\"color: #999\">...\n<!-- After -->\n<p style=\"color: #595959\">...",
      "provider": "deterministic",
      "model": "rule-templates-v1",
      "nodeFixes": [
        {
          "html": "<p style=\"color: #999\">Light text</p>",
          "selector": ".hero > p",
          "before": "<p style=\"color: #999\">",
          "after": "<p style=\"color: #595959\">"
        }
      ]
    }
  ],
  "count": 18
}
GET/api/v1/scan/{scanId}/fix/{resultId}Pro+

Get a specific fix instruction for a single scan result. Returns the cached fix if already generated.

Response 200 OK

{
  "fix": {
    "id": "uuid",
    "scanResultId": "uuid",
    "ruleId": "image-alt",
    "impact": "critical",
    "instruction": "Add descriptive alt text...",
    "codeSnippet": "<img src=\"logo.png\" alt=\"Company logo\" />",
    "provider": "openai",
    "model": "gpt-4o-mini",
    "createdAt": "2026-02-15T10:30:00Z",
    "nodeFixes": [
      {
        "html": "<img src=\"logo.png\">",
        "selector": "header > img",
        "before": "<img src=\"logo.png\">",
        "after": "<img src=\"logo.png\" alt=\"Company logo\">"
      }
    ]
  }
}
GET/api/v1/sites/{siteId}/history

Get score history for a monitored site. Useful for tracking accessibility improvements over time.

Query Parameters

ParameterTypeDescription
daysnumberNumber of days of history to return (1-365). Defaults to 30.

Response 200 OK

{
  "history": [
    {
      "score": 78,
      "totalIssues": 12,
      "criticalCount": 1,
      "seriousCount": 3,
      "recordedAt": "2026-02-15T10:30:00Z"
    },
    {
      "score": 82,
      "totalIssues": 9,
      "criticalCount": 0,
      "seriousCount": 2,
      "recordedAt": "2026-02-08T10:30:00Z"
    }
  ],
  "days": 30
}
GET/api/v1/sites/{siteId}/alerts

Get monitoring alert configurations for a site. Alerts trigger email notifications when accessibility metrics change.

Response 200 OK

{
  "alerts": [
    {
      "alertType": "score_drop",
      "threshold": 5,
      "enabled": true,
      "notifyEmail": "dev@example.com"
    },
    {
      "alertType": "new_critical",
      "enabled": true,
      "notifyEmail": "dev@example.com"
    }
  ]
}
GET/api/v1/sites

List all monitored sites for your account, including domain, monitoring settings, and last scan score.

Response 200 OK

{
  "sites": [
    {
      "id": "uuid",
      "domain": "example.com",
      "name": "Example Site",
      "lastScore": 85,
      "lastScannedAt": "2026-02-15T10:30:00Z",
      "monitoringEnabled": true,
      "monitoringFrequency": "weekly",
      "createdAt": "2026-01-01T00:00:00Z"
    }
  ]
}
POST/api/v1/sites

Add a new monitored site. The domain is normalized automatically (protocol and www prefix are stripped).

Request Body

ParameterTypeRequiredDescription
domainstringYesThe domain to monitor (e.g. "example.com").
namestringNoA display name for the site. Defaults to the domain.

Response 201 Created

{
  "site": {
    "id": "uuid",
    "domain": "example.com",
    "name": "Example Site"
  }
}
GET/api/v1/sites/{siteId}

Get detailed information about a specific site, including the latest scan results summary.

Response 200 OK

{
  "site": {
    "id": "uuid",
    "domain": "example.com",
    "name": "Example Site",
    "lastScore": 85,
    "monitoringEnabled": true,
    "monitoringFrequency": "weekly"
  },
  "latestScan": {
    "id": "uuid",
    "score": 85,
    "totalIssues": 5,
    "criticalCount": 0,
    "seriousCount": 2,
    "completedAt": "2026-02-15T10:30:00Z"
  }
}
GET/api/v1/user/usage

Get your current plan usage metrics including scan counts, site usage, and billing period information.

Response 200 OK

{
  "plan": "pro",
  "scansUsed": 42,
  "scanLimit": -1,
  "sitesUsed": 3,
  "siteLimit": 15,
  "pagesScanned": 210,
  "pagesPerScan": 500,
  "onDemandUsed": 5,
  "onDemandLimit": 25,
  "periodStart": "2026-01-20T00:00:00Z",
  "periodEnd": "2026-02-19T00:00:00Z"
}
GET/api/v1/scan/{scanId}/pdfPro+

Download a PDF accessibility report for a completed scan. Business plan users receive white-labeled reports. Returns the PDF file directly as a binary download.

Response 200 OKContent-Type: application/pdf

Returns the PDF file as a binary attachment. The Content-Disposition header includes the filename.

POST/api/v1/scan/{scanId}/rescan

Trigger a rescan of a previously scanned URL. Uses your on-demand scan quota. The original scan must be completed or failed.

Response 202 Accepted

{
  "scanId": "new-scan-uuid",
  "originalScanId": "original-scan-uuid",
  "status": "pending",
  "statusUrl": "/api/v1/scan/new-scan-uuid"
}
GET/api/v1/scan/{scanId}/roadmapPaid

Get a prioritized remediation roadmap for a completed scan. Returns violations grouped by priority with estimated effort and WCAG criteria references.

Response 200 OK

{
  "phases": [
    {
      "name": "Critical Fixes",
      "priority": 1,
      "items": [
        {
          "ruleId": "image-alt",
          "impact": "critical",
          "description": "Images must have alt text",
          "nodeCount": 5,
          "wcagCriteria": ["1.1.1"]
        }
      ]
    }
  ],
  "totalViolations": 18,
  "estimatedEffort": "medium"
}
GET/api/v1/statementsPro+

List all accessibility statements for your account. Statements are ordered by last update date.

Response 200 OK

{
  "statements": [
    {
      "id": "uuid",
      "organizationName": "Acme Corp",
      "websiteUrl": "https://acme.com",
      "conformanceLevel": "AA",
      "conformanceStatus": "partial",
      "publicSlug": "acme-corp-x7k9m2",
      "createdAt": "2026-02-01T00:00:00Z",
      "updatedAt": "2026-02-15T10:30:00Z"
    }
  ]
}
GET/api/badge/{siteId}Public

Returns an SVG badge showing the current accessibility score for a site. No authentication required — designed for embedding in READMEs, dashboards, and websites.

Response 200 OKContent-Type: image/svg+xml · Cache-Control: 1 hour

Score Colors

ScoreColor
90+Green
70–89Yellow
50–69Orange
<50Red
No dataGray

Embed Example

<img
  src="https://compliascan.com/api/badge/{siteId}"
  alt="CompliaScan accessibility score"
/>

The siteId is the UUID returned when you create a site via POST /api/v1/sites.

Webhooks

If you provide a callback_url when creating a scan, CompliaScan will send a POST request to that URL when the scan completes. This eliminates the need for polling.

Webhook Payload

{
  "event": "scan.completed",
  "scanId": "scn_a1b2c3d4e5f6",
  "data": {
    "url": "https://example.com",
    "score": 72,
    "totalIssues": 18,
    "criticalCount": 2,
    "seriousCount": 5,
    "moderateCount": 7,
    "minorCount": 4
  },
  "detailsUrl": "https://compliascan.com/api/v1/scan/scn_a1b2c3d4e5f6"
}

Your endpoint should return a 2xx status code within 10 seconds. CompliaScan will retry failed deliveries up to 3 times with exponential backoff.

Verifying Webhook Signatures

When a webhook secret is configured in your dashboard, every webhook request includes two additional headers:

  • X-CompliaScan-Signature — HMAC-SHA256 hex digest
  • X-CompliaScan-Timestamp — Unix epoch in seconds when the webhook was sent

The signature is computed as HMAC-SHA256(secret, "{timestamp}.{rawBody}"). To prevent replay attacks, reject payloads where the timestamp is older than 300 seconds.

Node.js

const crypto = require('crypto');

const signature = req.headers['x-compliascan-signature'];
const timestamp = req.headers['x-compliascan-timestamp'];

// Reject stale payloads (replay protection)
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
  throw new Error('Timestamp too old');
}

const message = `${timestamp}.${JSON.stringify(req.body)}`;
const expected = crypto
  .createHmac('sha256', webhookSecret)
  .update(message)
  .digest('hex');

if (signature !== expected) {
  throw new Error('Invalid signature');
}

Python

import hmac, hashlib, time

timestamp = headers['X-CompliaScan-Timestamp']
signature = headers['X-CompliaScan-Signature']

# Reject stale payloads (replay protection)
if abs(time.time() - int(timestamp)) > 300:
    raise ValueError('Timestamp too old')

message = f"{timestamp}.{raw_body}"
expected = hmac.new(
    secret.encode(), message.encode(), hashlib.sha256
).hexdigest()

if not hmac.compare_digest(signature, expected):
    raise ValueError('Invalid signature')

Error Codes

All errors follow a consistent format with a machine-readable code and a human-readable message.

CodeHTTP StatusDescription
AUTH_REQUIRED401No Authorization header was provided in the request.
INVALID_KEY401The provided API key is invalid, expired, or revoked.
RATE_LIMITED429You have exceeded the rate limit for your plan. Retry after the duration specified in the Retry-After header.
VALIDATION400The request body failed validation. Check the details field for specific field errors.
INVALID_URL400The provided URL is malformed or not publicly accessible.
NOT_FOUND404The requested scan or site ID does not exist or does not belong to your account.
PLAN_REQUIRED403This feature requires a higher plan. Check the endpoint documentation for plan requirements.
SCAN_NOT_COMPLETE400The scan has not finished processing yet. Poll the scan status endpoint until complete.
QUOTA_EXCEEDED403You have used all on-demand rescans for your current billing period.
NOT_READY400The scan is still in progress. Wait for the scan to complete before accessing this resource.
UPGRADE_REQUIRED403This feature requires a higher plan tier. Upgrade your subscription to access this endpoint.
INVALID_CALLBACK_URL400The provided callback URL failed validation. Must be a valid, publicly accessible HTTPS URL.
PDF_ERROR500PDF report generation failed. Retry the request or contact support if the issue persists.
SITE_LIMIT403You have reached the maximum number of monitored sites for your plan. Remove a site or upgrade to add more.
DUPLICATE409The resource already exists (e.g., adding a site with a domain that is already monitored).

Error Response Format

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 32 seconds.",
    "retryAfter": 32
  }
}

Quick Start

Get up and running in two steps. Replace cs_live_your_api_key with your actual API key from the dashboard.

1. Create a scan

curl -X POST https://compliascan.com/api/v1/scan \
  -H "Authorization: Bearer cs_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "multiPage": false,
    "callback_url": "https://your-server.com/webhooks/compliascan"
  }'

2. Check scan results

curl https://compliascan.com/api/v1/scan/scn_a1b2c3d4e5f6 \
  -H "Authorization: Bearer cs_live_your_api_key"

3. Check CI/CD gate

curl "https://compliascan.com/api/v1/scan/scn_a1b2c3d4e5f6/gate?threshold=70&maxCritical=0" \
  -H "Authorization: Bearer cs_live_your_api_key"

4. Generate fix suggestions

curl -X POST https://compliascan.com/api/v1/scan/scn_a1b2c3d4e5f6/fix \
  -H "Authorization: Bearer cs_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{}'

5. Export all scan data

curl "https://compliascan.com/api/v1/export" \
  -H "Authorization: Bearer cs_live_your_api_key"

Code Examples

Quick examples for common API operations. Replace YOUR_API_KEY with your actual API key from Dashboard > Settings > API Keys.

curl

# Create a scan
curl -X POST https://compliascan.com/api/v1/scan \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "multiPage": true}'

# Get scan results (poll until status is "completed")
curl https://compliascan.com/api/v1/scan/SCAN_ID \
  -H "Authorization: Bearer YOUR_API_KEY"

# CI/CD quality gate (fail if score < 80 or > 0 critical issues)
curl "https://compliascan.com/api/v1/scan/SCAN_ID/gate?threshold=80&maxCritical=0" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Download PDF report
curl -o report.pdf https://compliascan.com/api/v1/scan/SCAN_ID/pdf \
  -H "Authorization: Bearer YOUR_API_KEY"

# List monitored sites
curl https://compliascan.com/api/v1/sites \
  -H "Authorization: Bearer YOUR_API_KEY"

JavaScript (Node.js / Browser)

const API_KEY = "cs_live_YOUR_API_KEY";
const BASE = "https://compliascan.com/api/v1";

// Create a scan
const { scanId } = await fetch(`${BASE}/scan`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://example.com", multiPage: true }),
}).then((r) => r.json());

// Poll until complete
let scan;
do {
  await new Promise((r) => setTimeout(r, 5000));
  scan = await fetch(`${BASE}/scan/${scanId}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  }).then((r) => r.json());
} while (scan.status === "pending" || scan.status === "running");

console.log(`Score: ${scan.score}, Issues: ${scan.totalIssues}`);

// CI/CD gate check
const gate = await fetch(
  `${BASE}/scan/${scanId}/gate?threshold=80&maxCritical=0`,
  { headers: { Authorization: `Bearer ${API_KEY}` } }
).then((r) => r.json());

if (!gate.passed) {
  console.error("Quality gate failed:", gate.gates);
  process.exit(1);
}

Python

import requests, time

API_KEY = "cs_live_YOUR_API_KEY"
BASE = "https://compliascan.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Create a scan
resp = requests.post(
    f"{BASE}/scan",
    headers={**headers, "Content-Type": "application/json"},
    json={"url": "https://example.com", "multiPage": True},
)
scan_id = resp.json()["scanId"]

# Poll until complete
while True:
    scan = requests.get(f"{BASE}/scan/{scan_id}", headers=headers).json()
    if scan["status"] in ("completed", "failed"):
        break
    time.sleep(5)

print(f"Score: {scan['score']}, Issues: {scan['totalIssues']}")

# CI/CD gate check
gate = requests.get(
    f"{BASE}/scan/{scan_id}/gate",
    headers=headers,
    params={"threshold": 80, "maxCritical": 0},
).json()

if not gate["passed"]:
    print("Quality gate FAILED:", gate["gates"])
    exit(1)
print("Quality gate passed!")

OpenAPI Specification

Import our OpenAPI 3.0 spec into Postman, Insomnia, or your API client of choice for interactive exploration.

Download openapi.json

API Changelog

v1.0.0 — February 2026

Initial Release

  • 16 REST endpoints covering scans, sites, fixes, statements, and export
  • Bearer token authentication with per-plan rate limiting
  • CI/CD quality gate with configurable score and issue count thresholds
  • Webhook delivery for scan completion events
  • Multi-page scanning with plan-based page limits
  • PDF report downloads (white-labeled for Business plans)
  • Remediation roadmap generation
  • Score history and monitoring alert configuration
  • Full data export with scan results and sites (up to 500 scans)
  • OpenAPI 3.0 specification available at /api/openapi.json

Frequently Asked Questions

Which plans include API access?
API access is available on Pro ($179/mo) and Business ($349/mo) plans. API keys are generated from your dashboard settings.
What are the API rate limits?
Rate limits vary by plan: Pro gets 200 requests/minute and Business gets 1,000/minute. All responses include X-RateLimit headers so you can monitor usage. Exceeding the limit returns a 429 status with a Retry-After header.
Can I use the API in my CI/CD pipeline?
Yes. The /api/v1/scan/{scanId}/gate endpoint is designed specifically for CI/CD integration. Set a minimum score threshold and maximum critical/serious issue counts. The endpoint returns a pass/fail verdict you can use to block deploys that introduce accessibility regressions.
Does the API support webhook notifications?
Yes. Pass a callbackUrl when creating a scan and CompliaScan will POST the results to your URL when the scan completes. Your endpoint should return a 2xx response within 10 seconds. Failed deliveries are retried up to 3 times with exponential backoff.

Ready to integrate?

API access is available on paid plans. Generate API keys from your dashboard settings and start scanning programmatically today.

Get API Access

Related Resources