Icymango Scanner API

Programmatic access to SEO audits, WordPress security scans, and multi-tool security assessments.

Overview

The Scanner API lets you launch and monitor audits from any application. All requests return JSON. Scans run asynchronously — you launch a scan, receive a jobId, then poll the status endpoint until the job is complete.

All scan jobs are queued and run one at a time. Long scans (many pages + security tools) may take several minutes. Use the polling pattern shown in the examples.

Authentication

Protected endpoints require an API key passed in the X-API-Key header. Generate keys from the API Keys panel in the scanner UI.

# All protected requests
curl -H "X-API-Key: msk_your_key_here" https://your-scanner.com/api/...

Alternatively, use the Authorization header:

Authorization: Bearer msk_your_key_here
API keys are shown only once at creation. Store them securely — treat them like passwords. If a key is compromised, revoke it immediately from the API Keys panel.

Base URL

http://your-scanner-host:4001

Replace with your actual deployment URL. All paths below are relative to this base.

Error Responses

All errors return a JSON object with an error field and an appropriate HTTP status code.

{
  "error": "Provide a valid url starting with http(s)://"
}
StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — missing, invalid, or revoked API key
404Not found — unknown job ID or report not yet available
500Server error — check server logs

Launch Scan

POST /api/audit Start a new scan job

Launches an asynchronous scan. Returns a jobId immediately — use it to poll status and retrieve results.

Request Body

FieldTypeRequiredDefaultDescription
urlstringrequiredFull URL to scan, including https://
maxPagesnumberoptional25Max pages to crawl (1–200)
lighthousebooleanoptionaltrueRun Lighthouse performance & SEO analysis
wpscanbooleanoptionalfalseRun WordPress security scan (CVE lookups, plugin/theme detection)
security-scanbooleanoptionalfalseEnable full security scan suite
nuclei-scanbooleanoptionalfalseRun Nuclei vulnerability templates
nmap-scanbooleanoptionalfalseRun Nmap port & service scan
ssl-scanbooleanoptionalfalseAnalyse SSL/TLS configuration
dns-scanbooleanoptionalfalseDNS security analysis (SPF, DMARC, DNSSEC)
cmsmap-scanbooleanoptionalfalseRun CMSmap CMS vulnerability scanner
zap-scanbooleanoptionalfalseRun OWASP ZAP active scan

Example — SEO audit only

curl -X POST https://your-scanner.com/api/audit \
  -H "Content-Type: application/json" \
  -H "X-API-Key: msk_your_key_here" \
  -d '{
    "url": "https://example.com",
    "maxPages": 10,
    "lighthouse": true
  }'

Example — WordPress security scan

curl -X POST https://your-scanner.com/api/audit \
  -H "Content-Type: application/json" \
  -H "X-API-Key: msk_your_key_here" \
  -d '{
    "url": "https://yourwordpresssite.com",
    "maxPages": 1,
    "lighthouse": false,
    "wpscan": true
  }'

Response

200 OK
{
  "id":         "a1b2c3d4e5f6g7h8",
  "status":     "/api/status/a1b2c3d4e5f6g7h8",
  "reportBase": "/reports/a1b2c3d4e5f6g7h8/"
}

Check Status

GET /api/status/:jobId Poll job progress

Returns the current state and live logs of a scan job. Poll this endpoint every 5–10 seconds until state is done or error.

States

StateMeaning
queuedJob is waiting for a free worker
runningScan is actively in progress
doneScan completed successfully — results available
errorScan failed — check the error field
cancelledJob was cancelled by the user

Example

curl https://your-scanner.com/api/status/a1b2c3d4e5f6g7h8

Response

200 OK
{
  "id":          "a1b2c3d4e5f6g7h8",
  "url":         "https://example.com",
  "state":       "done",
  "startedAt":   "2026-03-26T10:00:00.000Z",
  "finishedAt":  "2026-03-26T10:04:32.000Z",
  "files": {
    "report.html":        "/reports/a1b2c3d4e5f6g7h8/report.html",
    "data":               "/reports/a1b2c3d4e5f6g7h8/data",
    "wpscan-report.html": "/reports/a1b2c3d4e5f6g7h8/wpscan-report.html"
  },
  "logs": ["Starting crawl...", "Page 1/10 done"]
}

Get Results

GET /reports/:jobId/data/report.json Full structured scan data

Returns the complete scan results as a JSON object. Available once state === "done".

Top-level fields

FieldDescription
originScanned URL
totalsPages crawled, issues found, HTTP errors, screenshots
pages[]Per-page results: URL, status, issues, SEO data, screenshots
rollup[]Aggregated issue counts across all pages, sorted by frequency
lighthousePerformance, SEO, accessibility, best-practices scores (0–100)
wpscanWordPress detection, version, plugins, themes, CVEs, security checks
security_scanResults from Nuclei, Nmap, SSL, DNS, CMSmap, ZAP
sitewideSeoScoreComputed SEO score 0–100
seoInsightsTop keywords, orphan pages, readability averages

WPScan sub-object (when wpscan: true)

{
  "wpscan": {
    "url": "example.com",
    "scan_results": {
      "is_wordpress":      true,
      "wordpress_version": "6.7.5",
      "plugins":           [{ "slug": "woocommerce", "version": "8.0.0", "outdated": true }],
      "themes":            [{ "slug": "avada", "source": "html-parse" }],
      "cve_check": {
        "wordpress": [{ "id": "CVE-2024-xxxx", "score": 9.8, "severity": "CRITICAL" }],
        "php":       [],
        "themes":    {}
      },
      "security_checks": {
        "readme_exposed":    true,
        "xmlrpc_enabled":   false,
        "php_version":      "8.3.27",
        "security_headers": { "hsts": false, "csp": false }
      },
      "summary": {
        "total_vulnerabilities": 21,
        "critical_vulnerabilities": 2,
        "security_issues": ["readme.html is publicly accessible"],
        "recommendations": ["Update WordPress core"]
      }
    }
  }
}

Cancel Scan

DELETE /api/audit/:jobId Cancel a running or queued job
curl -X DELETE https://your-scanner.com/api/audit/a1b2c3d4e5f6g7h8 \
  -H "X-API-Key: msk_your_key_here"
200 OK
{ "ok": true, "state": "cancelled" }

List Jobs

GET /api/jobs List all jobs across all states
curl https://your-scanner.com/api/jobs \
  -H "X-API-Key: msk_your_key_here"
200 OK
[
  {
    "id":         "a1b2c3d4e5f6g7h8",
    "url":        "https://example.com",
    "state":      "done",
    "startedAt":  "2026-03-26T10:00:00.000Z",
    "finishedAt": "2026-03-26T10:04:32.000Z"
  }
]

Delete Job

DELETE /api/jobs/:jobId Permanently delete a job and its reports
curl -X DELETE https://your-scanner.com/api/jobs/a1b2c3d4e5f6g7h8 \
  -H "X-API-Key: msk_your_key_here"
200 OK
{ "ok": true }

Generate AI Report

POST /api/ai-report Generate an AI-written executive briefing

Generates a written analysis report from completed scan results. Supports three report types. If the local AI (Ollama) is unavailable, a structured data-driven report is generated automatically.

Request Body

FieldTypeRequiredDescription
jobIdstringrequiredID of a completed scan job
reportTypestringoptionalaudit (default), wpscan, or security
formatstringoptionalhtml (default) or pdfpdf also generates HTML
modelstringoptionalOllama model name, default qwen3:4b

Example — branded WordPress executive briefing PDF

curl -X POST https://your-scanner.com/api/ai-report \
  -H "Content-Type: application/json" \
  -H "X-API-Key: msk_your_key_here" \
  -d '{
    "jobId": "a1b2c3d4e5f6g7h8",
    "reportType": "wpscan",
    "format": "pdf"
  }'
200 OK
{
  "ok":       true,
  "fallback": false,
  "files": {
    "markdown": "/reports/a1b2c3d4e5f6g7h8/ai-wpscan-report.md",
    "html":     "/reports/a1b2c3d4e5f6g7h8/ai-wpscan-report.html",
    "pdf":      "/reports/a1b2c3d4e5f6g7h8/ai-wpscan-report.pdf"
  }
}

Health Check

GET /api/health No auth required
{ "ok": true, "db": true }

Example: Full SEO Audit (JavaScript)

// Launch a crawl and wait for results
async function runSeoAudit(url) {
  const BASE = 'https://your-scanner.com';
  const KEY  = 'msk_your_key_here';
  const headers = { 'Content-Type': 'application/json', 'X-API-Key': KEY };

  // 1. Launch
  const launch = await fetch(`${BASE}/api/audit`, {
    method: 'POST', headers,
    body: JSON.stringify({ url, maxPages: 20, lighthouse: true })
  });
  const { id } = await launch.json();

  // 2. Poll until done
  let status;
  do {
    await new Promise(r => setTimeout(r, 6000));
    status = await (await fetch(`${BASE}/api/status/${id}`)).json();
  } while (status.state === 'running' || status.state === 'queued');

  if (status.state !== 'done') throw new Error(status.error);

  // 3. Fetch results
  const report = await (await fetch(`${BASE}/reports/${id}/data/report.json`)).json();
  return { id, report };
}

Example: WordPress Scan + AI Briefing (Python)

import requests, time

BASE = "https://your-scanner.com"
KEY  = "msk_your_key_here"
H    = { "X-API-Key": KEY, "Content-Type": "application/json" }

# Launch WordPress scan
r = requests.post(f"{BASE}/api/audit", headers=H,
    json={ "url": "https://yoursite.com", "maxPages": 1,
           "lighthouse": False, "wpscan": True })
job_id = r.json()["id"]

# Poll
while True:
    time.sleep(8)
    status = requests.get(f"{BASE}/api/status/{job_id}", headers=H).json()
    if status["state"] not in ("running", "queued"):
        break

# Generate branded PDF briefing
ai = requests.post(f"{BASE}/api/ai-report", headers=H,
    json={ "jobId": job_id, "reportType": "wpscan", "format": "pdf" }).json()

print("PDF:", BASE + ai["files"]["pdf"])

Example: Full Security Scan (curl)

curl -X POST https://your-scanner.com/api/audit \
  -H "Content-Type: application/json" \
  -H "X-API-Key: msk_your_key_here" \
  -d '{
    "url":          "https://target.com",
    "maxPages":     1,
    "lighthouse":   false,
    "wpscan":       true,
    "security-scan": true,
    "nuclei-scan":  true,
    "nmap-scan":    true,
    "ssl-scan":     true,
    "dns-scan":     true
  }'

Example: Robust Poll Helper (JavaScript)

async function waitForJob(jobId, { timeout = 600_000, interval = 7000 } = {}) {
  const deadline = Date.now() + timeout;
  while (Date.now() < deadline) {
    await new Promise(r => setTimeout(r, interval));
    const s = await (await fetch(`/api/status/${jobId}`,
      { headers: { 'X-API-Key': KEY } })).json();
    if (s.state === 'done')       return s;
    if (s.state === 'error')      throw new Error(s.error || 'Scan failed');
    if (s.state === 'cancelled')  throw new Error('Scan was cancelled');
  }
  throw new Error('Timed out waiting for scan');
}