Trigger scans, retrieve findings, and integrate security data into your pipeline.
All API v1 endpoints require an API key passed as a Bearer token. You can create API keys from your dashboard settings (Watchtower plan).
Keys use the avk_ prefix followed by 64 hex characters.
The full key is shown once on creation and stored as a one-way hash. Rate limits are per-key, reset daily at UTC midnight.
All endpoints return a consistent envelope.
// Success
{
"data": { ... },
"meta": {
"requestId": "req_abc123...",
"timestamp": "2026-01-15T10:30:00.000Z",
"rateLimit": { "remaining": 994, "reset": "2026-01-16T00:00:00.000Z" }
}
}
// Error
{
"error": {
"code": "DOMAIN_NOT_FOUND",
"message": "Domain not found",
"requestId": "req_abc123..."
}
}/scansStart a new scan for a domain that already exists in your account. Returns immediately with a scan ID you can poll.
{
"hostname": "example.com",
"port": 443,
"scheme": "https",
"compare_to": "previous"
}hostname string, required - The domain to scan. Must already exist in your account.port number, optional - Port to target (1-65535). Defaults to 443.scheme string, optional - http or https. Defaults to https.compare_to string, optional - Set to "previous" to include a scan-to-scan diff when you later GET the scan result.{
"data": {
"scanId": "clx...",
"status": "queued",
"hostname": "example.com"
},
"meta": { "requestId": "...", "timestamp": "...", "rateLimit": { ... } }
}404 - Domain not found in your account.409 - A scan is already running for this domain.429 - Rate limit exceeded (max 10 scans/domain/day)./scans/:scanIdReturns the scan status, findings with compliance tags, and a severity summary. Poll this until status is "completed".
compare_to optional - Set to "previous" to include a diff against the previous completed scan. Also activates if compare_to was set when the scan was created.{
"data": {
"scan": {
"id": "clx...",
"status": "completed",
"hostname": "example.com",
"createdAt": "2026-01-15T10:30:00Z",
"updatedAt": "2026-01-15T10:31:12Z"
},
"findings": [
{
"id": "clx...",
"checkId": "tls-protocol",
"status": "open",
"severity": "medium",
"title": "Legacy TLS protocol supported",
"evidence": "Server accepts TLS 1.0/1.1 connections",
"compliance": [
{ "framework": "soc2", "controlId": "CC6.1" },
{ "framework": "pciDss", "controlId": "4.2.1" }
]
}
],
"summary": {
"total": 5,
"bySeverity": { "critical": 1, "high": 2, "medium": 1, "low": 1 }
},
"diff": {
"comparedTo": "clx_previous_scan_id",
"checks": {
"new": 1, "newDetections": 0, "fixed": 2, "regressed": 0,
"details": {
"new": [{ "id": "csp-missing", "title": "No CSP header", "impact": "medium" }],
"fixed": [...],
"regressed": []
}
},
"components": { "added": 1, "removed": 0, "versionChanged": 1 },
"entryPoints": { ... }
}
},
"meta": { ... }
}The diff field is only present when compare_to=previous is active and the scan is completed.
queued - Waiting to start.running - Scan started, resolving DNS and TLS.mapping - Crawling and analyzing.completed - Done. Findings available.failed - Scan errored out.cancelled - Scan was stopped before completion./scans/:scanId/retestRe-run specific checks against a completed scan. Useful for verifying a fix without running a full scan.
{
"checkIds": ["tls-cert-expiring", "security-headers-hsts"]
}checkIds string[], required - Check IDs to retest. These are resolved to analyzer groups server-side.{
"data": {
"jobId": "clx...",
"scanId": "clx...",
"existed": false,
"analyzerIds": ["tls", "security-headers"],
"checkIds": ["tls-cert-expiring", "security-headers-hsts"]
},
"meta": { ... }
}existed is true if an identical retest job was already queued (idempotent).
400 - Missing or empty checkIds, or scan not completed.404 - Scan not found./domainsReturns all domains in your account with their latest completed scan and open finding counts.
{
"data": {
"domains": [
{
"hostname": "example.com",
"createdAt": "2026-01-10T08:00:00Z",
"latestScan": {
"id": "clx...",
"status": "completed",
"createdAt": "2026-01-15T10:30:00Z"
},
"findings": {
"open": { "high": 2, "medium": 3, "low": 1 }
}
}
]
},
"meta": { ... }
}latestScan is null if no completed scan exists. findings.open only includes severities with at least one open finding.
/domains/:hostnameReturns domain detail, latest scan, finding summary, and Watchtower monitoring status.
{
"data": {
"domain": {
"hostname": "example.com",
"createdAt": "2026-01-10T08:00:00Z",
"watchtower": {
"enabled": true,
"nextCheckAt": "2026-01-16T09:00:00Z"
}
},
"latestScan": {
"id": "clx...",
"status": "completed",
"createdAt": "2026-01-15T10:30:00Z",
"updatedAt": "2026-01-15T10:31:12Z"
},
"findings": {
"totalOpen": 6,
"bySeverity": { "high": 2, "medium": 3, "low": 1 }
}
},
"meta": { ... }
}404 - Domain not found in your account./domains/:hostname/findingsReturns findings for a domain with compliance tags. Supports filtering and cursor-based pagination.
status optional - Filter by finding status (open, fixed, accepted).severity optional - Filter by severity (critical, high, medium, low).checkId optional - Filter by check ID (e.g. tls-cert-expiring).limit optional - Results per page, 1-500. Default 100.cursor optional - Pagination cursor from previous response.{
"data": {
"findings": [
{
"id": "clx...",
"checkId": "dmarc-missing",
"status": "open",
"severity": "high",
"title": "No DMARC record found",
"evidence": "No DMARC TXT record at _dmarc.example.com",
"firstSeenAt": "2026-01-10T08:00:00Z",
"lastSeenAt": "2026-01-15T10:31:12Z",
"compliance": [
{ "framework": "iso27001", "controlId": "A.8.8" }
]
}
],
"nextCursor": "clx..."
},
"meta": { ... }
}Pass nextCursor as the cursor param to get the next page. null when no more results.
/surface/:hostnameReturns a domain's connection map: nodes are related domains, IPs, certificates, and nameservers; edges are the relationships between them.
{
"data": {
"nodes": [
{
"id": "clx...",
"nodeType": "hostname",
"key": "example.com",
"label": "example.com",
"properties": { ... },
"firstSeenAt": "2026-01-10T08:00:00Z",
"lastSeenAt": "2026-01-15T10:30:00Z"
}
],
"edges": [
{
"id": "clx...",
"edgeType": "resolves_to",
"sourceId": "clx_node_a",
"targetId": "clx_node_b",
"properties": { ... },
"firstSeenAt": "2026-01-10T08:00:00Z",
"lastSeenAt": "2026-01-15T10:30:00Z"
}
]
},
"meta": { ... }
}hostname - A domain or subdomain.ip - An IP address.certificate - A TLS certificate.nameserver - A DNS nameserver.404 - Domain not found in your account./surface/:hostname/driftReturns discovery events for a domain, ordered by sequence number. Use cursor-based pagination to stream changes over time.
after optional - Cursor (eventSeq) from previous response. Returns events after this sequence number.limit optional - Results per page, 1-200. Default 50.{
"data": {
"events": [
{
"id": "clx...",
"eventSeq": "12345",
"eventType": "node.appeared",
"eventVersion": 1,
"payload": { "nodeType": "hostname", "key": "api.example.com" },
"createdAt": "2026-01-15T10:30:00Z",
"runId": "clx..."
}
],
"cursor": "12345"
},
"meta": { ... }
}Pass cursor as the after param for the next page. When no more events exist, events is empty and cursor holds the last known position.
400 - Invalid cursor format.404 - Domain not found in your account./docsReturns the full OpenAPI 3.0 spec as JSON. No authentication required.
Rate limits are per API key, reset daily at UTC midnight. Limits depend on your plan.
When you hit the limit, the API returns 429 Too Many Requests.
| Plan | Daily requests |
|---|---|
| Watchtower | 1,000 |
| Hunter | 10,000 |
Every response includes rate limit info in the meta.rateLimit object and in headers: X-RateLimit-Remaining and X-RateLimit-Reset.
All v1 endpoints support CORS with the Authorization header allowed.
You can call the API from browser-based applications.
Trigger a scan and poll for results:
# Trigger a scan
curl -X POST https://attackerview.com/api/v1/scans \
-H "Authorization: Bearer avk_your_key" \
-H "Content-Type: application/json" \
-d '{"hostname": "example.com"}'
# Check status (poll until status is "completed")
curl https://attackerview.com/api/v1/scans/SCAN_ID \
-H "Authorization: Bearer avk_your_key"
# List all open findings for a domain
curl "https://attackerview.com/api/v1/domains/example.com/findings?status=open" \
-H "Authorization: Bearer avk_your_key"Or use the CLI or GitHub Actions for a simpler workflow.