API Reference
Scan API

Scan API

The Scan API lets you start security and functional test scans, retrieve detailed results, list historical scans, and export reports in multiple formats.

Authentication

All scan endpoints require your API key. The tenant is resolved automatically from the key — no separate tenant ID header is needed.

X-API-Key: nat_pk_your_api_key_here

Base URL

https://api.nat-testing.io/api/v1

Endpoints

Start a scan

Starts a new scan against the specified target. Returns immediately with a scan_id — poll the results endpoint to check status.

POST /api/v1/scan

Request body:

FieldTypeRequiredDescription
urlstringTarget API base URL
spec_urlstringOpenAPI/Swagger spec URL (recommended)
spec_contentstringBase64-encoded spec content (alternative to spec_url)
auth.typestringbearer, header, basic, oauth2, none
auth.tokenstringBearer token value
auth.header_namestringHeader name for header auth type
auth.header_valuestringHeader value for header auth type
auth.usernamestringUsername for basic auth
auth.passwordstringPassword for basic auth
auth.oauth2_token_urlstringOAuth2 token endpoint
auth.oauth2_client_idstringOAuth2 client ID
auth.oauth2_client_secretstringOAuth2 client secret
options.concurrencyintegerParallel request count (default: 5)
options.timeoutintegerPer-request timeout in seconds (default: 30)
options.fail_onstringSeverity threshold for failure: critical, high, medium, low
options.excludestring[]Path patterns to exclude
curl -X POST https://api.nat-testing.io/api/v1/scan \
  -H "X-API-Key: $NAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com",
    "spec_url": "https://api.example.com/openapi.json",
    "auth": {
      "type": "bearer",
      "token": "eyJhbGciOiJSUzI1NiJ9..."
    },
    "options": {
      "concurrency": 5,
      "timeout": 30,
      "fail_on": "high"
    }
  }'

Response 202 Accepted:

{
  "scan_id": "scan_abc123xyz",
  "status": "running",
  "created_at": "2025-01-15T10:30:00Z"
}

Error responses:

StatusCodeDescription
402QUOTA_EXCEEDEDMonthly scan quota exhausted
429CONCURRENT_LIMITToo many scans running simultaneously
401UNAUTHORIZEDMissing or invalid API key
400INVALID_REQUESTMalformed request body

Get scan results

Returns the full results for a completed scan. Poll this endpoint until status is completed.

GET /api/v1/scan/{id}/results

Path parameters:

ParameterTypeDescription
idstringScan ID returned by POST /api/v1/scan
curl https://api.nat-testing.io/api/v1/scan/scan_abc123xyz/results \
  -H "X-API-Key: $NAT_API_KEY"

Response 200 OK (in-progress):

{
  "scan_id": "scan_abc123xyz",
  "status": "running",
  "progress_percent": 45
}

Response 200 OK (completed):

{
  "scan_id": "scan_abc123xyz",
  "status": "completed",
  "passed": 10,
  "failed": 2,
  "total": 12,
  "elapsed_seconds": 45.32,
  "agent_count": 3,
  "tasks": [
    {
      "task_id": "task_001",
      "name": "BOLA check on /api/users/{id}",
      "status": "failed",
      "severity": "high",
      "evidence": "User A could access User B's record via /api/users/42"
    }
  ],
  "dom_snapshots": [...],
  "screenshots": [...],
  "visual_regression": {
    "comparisons": [...],
    "diffs_detected": 1
  },
  "accessibility": {
    "pages_scanned": 12,
    "violations": [
      {
        "rule": "color-contrast",
        "impact": "serious",
        "elements": 3,
        "description": "Insufficient color contrast ratio"
      }
    ],
    "compliance_score": 87.5
  },
  "performance": {
    "pages_tested": 12,
    "metrics": [
      {
        "page": "/dashboard",
        "lcp_ms": 1850,
        "fid_ms": 45,
        "cls": 0.08,
        "ttfb_ms": 220
      }
    ],
    "performance_score": 72.1
  }
}

Result fields:

FieldTypeDescription
passedintegerNumber of test tasks that passed
failedintegerNumber of test tasks that failed
totalintegerTotal number of test tasks
elapsed_secondsfloatTotal scan duration
agent_countintegerNumber of AI agents used
tasksarrayIndividual test task results
visual_regressionobjectVisual diff comparisons (Pro/Team only)
accessibilityobjectAccessibility audit results (Pro/Team only)
performanceobjectCore Web Vitals and performance scores (Pro/Team only)

The visual_regression, accessibility, and performance sections are only populated on Pro and Team plans.


List scans

Returns a paginated list of all scans for your tenant, ordered by creation date (most recent first).

GET /api/v1/scans

Query parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
per_pageinteger20Results per page (max 100)
statusstringFilter by status: running, completed, failed
curl "https://api.nat-testing.io/api/v1/scans?page=1&per_page=20" \
  -H "X-API-Key: $NAT_API_KEY"

Response 200 OK:

{
  "scans": [
    {
      "scan_id": "scan_abc123xyz",
      "status": "completed",
      "url": "https://api.example.com",
      "passed": 10,
      "failed": 2,
      "total": 12,
      "created_at": "2025-01-15T10:30:00Z",
      "completed_at": "2025-01-15T10:31:15Z"
    }
  ],
  "total": 47,
  "page": 1,
  "per_page": 20,
  "total_pages": 3
}

Export scan report

Downloads a scan report in the specified format.

GET /api/v1/scan/{id}/export

Path parameters:

ParameterTypeDescription
idstringScan ID

Query parameters:

ParameterTypeRequiredDescription
formatstringExport format: html, json, csv
# Export as HTML
curl "https://api.nat-testing.io/api/v1/scan/scan_abc123xyz/export?format=html" \
  -H "X-API-Key: $NAT_API_KEY" \
  -o report.html
 
# Export as JSON
curl "https://api.nat-testing.io/api/v1/scan/scan_abc123xyz/export?format=json" \
  -H "X-API-Key: $NAT_API_KEY" \
  -o report.json
 
# Export as CSV
curl "https://api.nat-testing.io/api/v1/scan/scan_abc123xyz/export?format=csv" \
  -H "X-API-Key: $NAT_API_KEY" \
  -o report.csv

Response: Binary file content with the appropriate Content-Type header:

FormatContent-Type
htmltext/html
jsonapplication/json
csvtext/csv

Rate limiting

All scan endpoints are rate-limited per API key. When you exceed your plan's request rate, the API returns 429 Too Many Requests.

Rate limit headers returned on every response:

HeaderDescription
X-RateLimit-LimitMaximum requests per minute for your plan
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds to wait before retrying (only on 429 responses)

Rate limits by plan:

PlanRequests/minute
Free10
Pro60
Team200
Enterprise1,000

Example 429 response:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 12
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
 
{
  "error": "RATE_LIMITED",
  "message": "Rate limit exceeded. Retry after 12 seconds.",
  "retry_after": 12
}

See Pricing & Plans for a full breakdown of rate limits and quotas by plan.


See also

Was this helpful?