Back to Docs

REST API

Build custom integrations with ScanAtlas

Authentication

All API requests require authentication using an API key. Include your key in the Authorization header:

Authorization: Bearer sa_live_your_api_key_here

Generate your API key in Settings → API. API access requires a Starter or Pro plan.

Rate Limits

General API

60 requests/minute

Scan Creation

10 requests/minute

Rate limit headers are included in all responses:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1704067200

Quick Start

Create a scan

curl -X POST "https://scanatlas.com/api/v1/scans" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

List your scans

curl "https://scanatlas.com/api/v1/scans?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

Get scan details

curl "https://scanatlas.com/api/v1/scans/SCAN_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

Endpoints Reference

POST/api/v1/scans

Create a new scan

Request Body:

{ "url": "https://example.com" }

Response:

{
  "data": {
    "id": "uuid",
    "siteUrl": "https://example.com",
    "status": "queued",
    "createdAt": "2024-01-01T00:00:00.000Z"
  },
  "usage": {
    "scansUsed": 1,
    "scansLimit": 10,
    "scansRemaining": 9
  }
}
GET/api/v1/scans

List your scans

Query Parameters:

  • limit (default: 20, max: 100)
  • offset (default: 0)
  • status (filter)

Response:

{
  "data": [...],
  "pagination": { "limit": 20, "offset": 0, "hasMore": true }
}
GET/api/v1/scans/:id

Get scan details

Response:

{
  "data": {
    "id": "uuid",
    "siteUrl": "https://example.com",
    "status": "completed",
    "healthScore": 85,
    "totalPages": 10,
    "errorCount": 2,
    "warningCount": 5
  }
}
GET/api/v1/scans/:id/pages

Get pages for a scan

Response:

{
  "data": [
    { "url": "/", "statusCode": 200, "loadTime": 1234 },
    ...
  ]
}
GET/api/v1/scans/:id/issues

Get issues for a scan

Query Parameters:

  • severity (error, warning, info)
  • category

Response:

{
  "data": [
    {
      "severity": "error",
      "category": "seo",
      "message": "Missing meta description",
      "pageUrl": "/"
    },
    ...
  ]
}
GET/api/v1/scans/:id/report

Get a text report optimized for LLMs

Response:

{ "data": { "content": "..." } }

Error Codes

CodeDescription
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - API access requires paid plan
404Not Found - Resource doesn't exist
429Too Many Requests - Rate limit exceeded
500Internal Server Error

Common Workflows

Scan and Wait for Completion

// 1. Start a scan
const { data: scan } = await fetch('/api/v1/scans', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: 'https://example.com' })
}).then(r => r.json());

// 2. Poll for completion
let status = scan.status;
while (status !== 'completed' && status !== 'failed') {
  await new Promise(r => setTimeout(r, 5000)); // Wait 5 seconds
  const { data } = await fetch(`/api/v1/scans/${scan.id}`, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  }).then(r => r.json());
  status = data.status;
}

// 3. Get results
const results = await fetch(`/api/v1/scans/${scan.id}/issues`, {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());

Get LLM-Friendly Report

The /report endpoint returns a text report optimized for AI assistants.

const { data } = await fetch('/api/v1/scans/SCAN_ID/report', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}).then(r => r.json());

// data.content contains a formatted text report suitable for LLMs

Prefer AI Integration?

For direct integration with Claude, Cursor, or other AI assistants, check out our MCP Server for natural language website scanning.