Scans

Scan hosts, ports, domains, and URLs, then read results, summaries, and checks.

What a scan is

A scan job targets hosts, ports, domains, URLs, or specific CVEs. Host and port combinations are scanned together. Domains get DNS and HTTP collection. URLs get HTTP collection.

Create returns the scan. data.job_id is the id you poll. data.status starts as pending, moves through in progress, and finishes as complete. A rejected request comes back as rejected with errors and rejected_* arrays. canceled means the scan was stopped.

POST/v3/scans

Create a scan job

Request fields

FieldTypeNotes
hostsstring[]IPs, CIDRs, or a saved host list name
portsstring[]Ports, ranges (80-88), top_1000, or a saved port list name
protostringtcp (default) or udp
domainsstring[]Domain names to collect
urlsstring[]Exact URLs to collect
pathsstring[]Paths appended to hosts and domains
paths_httpsbooleanUse https for path collection
cvesstring[]CVE ids to check. Cannot be combined with urls or paths
fingerprintbooleanIdentify the service on open ports. Doubles request_count
checksbooleanRun vulnerability checks on open services
checks_optionsobjectcves_only, min_severity, max_severity
collectobjectService name to the ports to collect
callbackobjectSee Callbacks. Empty phases can be filled from preferences
tagsstring[]At most 10 tags, 40 characters each
descriptionstringAt most 300 characters

Severity values are info, low, medium, high, and critical. min_severity cannot be above max_severity.

cves cannot be combined with urls or paths. With cves set, hosts and domains are targets for those checks only. With urls or paths set, hosts and domains are HTTP collection targets, and normal port scanning is not run.

curl -sS -X POST "https://api.efflux.io/v3/scans" \
  -H "Authorization: Bearer $EFFLUX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hosts": ["1.2.3.4", "10.0.0.0/24", "my_internal_servers"],
    "ports": ["22", "80-88", "top_1000", "my_common_ports"],
    "proto": "tcp",
    "fingerprint": false,
    "checks": true,
    "checks_options": { "cves_only": false, "min_severity": "high" },
    "collect": { "ssh": ["22", "2222"], "rdp": ["3389"] },
    "tags": ["web", "security"],
    "description": "External web tier",
    "callback": {
      "success": { "url": "https://example.com/hook/$job_id", "method": "POST" }
    }
  }'

Names inside hosts and ports refer to lists you already saved. Unknown names land in rejected_hosts or rejected_ports.

Dry run

POST /scans/eval checks the same body and returns the counts for that scan without creating it. status is acceptable when the scan can be created.

POST/v3/scans/eval

Evaluate a scan without creating it

Read results

Poll GET /scans/{job_id} until status is complete.

GET/v3/scans/{job_id}

Get a scan job

GET/v3/scans/{job_id}/results

Full result report

GET/v3/scans/{job_id}/summary

Summary counts

Results and summary are the report. They are not wrapped in data. Pass details on the results route for the full report.

links on the job includes self, results, and summary.

GET/v3/scans

List your scan jobs

POST/v3/scans/{job_id}/repeat

Run the same request again

Repeat returns 201 and a new job id.

Checks found by the scan are queried separately. See Checks.

Errors and limits

StatusWhen
400Body failed validation
401Missing key, or a plan limit was reached
409An equivalent job is already pending
429Rate limit. Read retry_after_seconds

Pending and concurrent scan caps, and the monthly request budget, come from GET /limits. The create response includes request_count, the requests this scan uses from that budget. Fingerprinting doubles that count.