Project Scoping
All scan endpoints support multi-tenancy via theX-Project-UUID header. When provided, scans are created and queried within the specified project. Responses include the project_uuid field to confirm the project context.
Single-Target Scans
POST /api/scan-url — Scan a URL
Starts an asynchronous scan of a single URL. Equivalent to the CLIscan-url command. Returns 202 Accepted immediately with a scan ID.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Target URL to scan |
method | string | No | HTTP method (default: GET) |
body | string | No | Request body |
headers | map[string]string | No | Custom request headers |
modules | string | No | Comma-separated module IDs to run |
no_passive | bool | No | Skip passive modules |
POST /api/scan-request — Scan a Raw HTTP Request
Starts an asynchronous scan from a base64-encoded raw HTTP request. Equivalent to the CLIscan-request command. Returns 202 Accepted immediately with a scan ID.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
raw_request | string | Yes | Base64-encoded raw HTTP request |
target_url | string | No | Override target URL (scheme://host) for the request |
modules | string | No | Comma-separated module IDs to run |
no_passive | bool | No | Skip passive modules |
| Code | Condition |
|---|---|
| 400 | Missing required fields or invalid input |
GET /api/scan/status to check the progress of the scan.
Scan Management
POST /api/scans/run — Run Target Scan
Triggers a background scan against target URLs. Equivalent tovigolium scan -t <url>. At least one target URL is required unless repo_path or repo_url is provided for SAST scanning — use POST /api/scan-all-records to scan existing DB records.
Returns 202 Accepted on success, 200 OK for dry runs, or 409 Conflict if a scan is already running.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
targets | string[] | Yes* | Target URLs (like -t). At least one target or url is required, unless repo_path/repo_url is provided. |
urls | string[] | Yes* | Alias for targets. Both fields are merged if provided. |
dry_run | bool | No | Validate params and create scan record without launching the runner |
strategy | string | No | Strategy preset: lite, balanced, deep, whitebox |
only | string | No | Single phase isolation (like --only). Accepts aliases. |
skip | string[] | No | Skip specific phases (like --skip). Accepts aliases. |
modules | string[] | No | Module IDs with fuzzy match (like -m) |
module_tags | string[] | No | Filter modules by tag (like --module-tag) |
concurrency | int | No | Number of parallel workers |
timeout | string | No | Request timeout as Go duration (e.g. "30s") |
max_per_host | int | No | Maximum concurrent requests per host |
rate_limit | int | No | Maximum request submissions per second |
scanning_max_duration | string | No | Global max scan duration as Go duration (like --scanning-max-duration). Per-phase durations are derived automatically using duration_factor from the scanning pace config (e.g. spidering gets 0.15 × max_duration). |
scope_origin | string | No | Scope origin mode: all, relaxed, balanced, strict |
heuristics_check | string | No | Heuristics check level: none, basic, advanced |
headers | map[string]string | No | Custom HTTP headers included in all requests |
scanning_profile | string | No | Scanning profile name or path |
repo_path | string | No | Absolute path to local source repo for SAST scan (like --repo). Mutually exclusive with repo_url. |
repo_url | string | No | Git URL to clone for SAST scan (like --repo-url). Mutually exclusive with repo_path. |
SAST scanning: WhenPhase duration factors: Therepo_pathorrepo_urlis provided without targets and without explicitonly/skip, the scan automatically runs in SAST-only mode (only: "sast"). Thescan_modein the response is set to"sast". You can combine SAST with target scanning by providing both targets and a repo path.
scanning_max_duration field sets the global max duration. Each phase derives its own limit by multiplying the global value by its duration_factor from the scanning pace config. Default factors:
| Phase | Default Factor | Example (2h global) |
|---|---|---|
| Spidering | 0.15 | 18m |
| External Harvester | 0.20 | 24m |
| Audit | 1.00 | 2h |
| KnownIssueScan | 3.00 | 6h |
max_duration overrides in the YAML config take precedence over the factor calculation.
Phase names and aliases:
| Canonical name | Aliases |
|---|---|
discovery | deparos, discover |
spidering | spitolas |
audit | dynamic-assessment |
extension | ext |
ingestion | — |
external-harvest | — |
known-issue-scan | — |
sast | — |
Note:onlyandskipare mutually exclusive — providing both returns400.
scanning_max_duration and per-phase duration factors are applied correctly.
| Code | Condition |
|---|---|
| 400 | Missing targets (when no repo provided), invalid parameters, or missing DB |
| 400 | repo_path and repo_url both provided (mutually exclusive) |
| 400 | repo_path is not an absolute path or does not exist |
| 400 | repo_url clone failed |
| 409 | A scan is already running |
| 500 | Failed to create scan runner |
GET /api/scan/status — Scan Status
Returns the status of the current or most recent scan. Thestatus field reflects pause state when applicable.
DELETE /api/scan — Cancel Scan
Cancels a running scan.Scan History
GET /api/scans — List Scans
Returns paginated scan history ordered by creation date (newest first). Query parameters:| Parameter | Type | Default | Description |
|---|---|---|---|
limit | int | 50 | Number of scans to return (max 500) |
offset | int | 0 | Offset for pagination |
GET /api/scans/:uuid — Get Scan Detail
Returns a single scan by UUID.| Code | Condition |
|---|---|
| 400 | Missing UUID |
| 404 | Scan not found |
| 503 | Database unavailable |
DELETE /api/scans/:uuid — Delete Scan
Deletes a scan record by UUID.| Code | Condition |
|---|---|
| 400 | Missing UUID |
| 404 | Scan not found |
| 503 | Database unavailable |
POST /api/scans/:uuid/stop — Stop a Running Scan
Stops a specific running scan by UUID. The scan must be the currently active scan. Workers finish their current tasks before fully stopping.| Code | Condition |
|---|---|
| 400 | Missing UUID |
| 409 | No scan running, or UUID is not the active scan |
POST /api/scans/:uuid/pause — Pause a Running Scan
Pauses a running scan. Workers finish their current item then block until resumed. The scan status is set to"paused" in the database.
| Code | Condition |
|---|---|
| 400 | Missing UUID |
| 409 | No scan running, UUID is not the active scan, or scan is already paused |
POST /api/scans/:uuid/resume — Resume a Paused Scan
Resumes a previously paused scan. Blocked workers continue processing items and the scan status is set back to"running".
| Code | Condition |
|---|---|
| 400 | Missing UUID |
| 409 | No scan running, UUID is not the active scan, or scan is not paused |
GET /api/scans/:uuid/logs — Get Scan Logs
Returns log entries for a scan, ordered by creation time ascending. Logs are captured at multiple levels:- Structured events (
info,warn,error): Phase lifecycle events (start, complete, fail, skip), scan start/finish, pause/resume, configuration snapshots, and panic recovery. - Raw console output (
trace): Every line printed to the terminal during the scan, with ANSI color codes stripped. This includes phase headers, traffic lines (❯ spider │ [200] GET ...), progress feedback, and scan configuration banners.
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | int | 100 | Number of log entries to return |
offset | int | 0 | Offset for pagination |
level | string | Filter by log level: trace, info, warn, error. Use trace to replay raw console output. | |
phase | string | Filter by scan phase: config, heuristics, harvest, spidering, discovery, known-issue-scan, audit, sast, seed. Use config to retrieve the scan configuration snapshot. |
level=info):
level=trace):
phase=config):
| Field | Type | Description |
|---|---|---|
id | int | Auto-incrementing log entry ID |
scan_uuid | string | UUID of the scan this log belongs to |
level | string | Log level: trace, info, warn, or error |
phase | string | Scan phase (see table below), or empty for global events (scan start/finish, pause/resume) |
message | string | Human-readable log message. For trace entries, this is the raw console line with ANSI codes stripped. |
metadata | string | Optional JSON blob with structured context. Present on config snapshots and phase-start events. |
created_at | string | ISO 8601 timestamp |
| Phase | Description |
|---|---|
config | Scan configuration snapshot (logged once at scan start) |
heuristics | Target root page probing to optimize phase selection |
harvest | External URL harvesting from intelligence sources |
spidering | Browser-based crawling |
sast | Static analysis / route extraction from source code |
discovery | Input ingestion + content discovery |
seed | CLI target seeding (when discovery is skipped) |
known-issue-scan | Known issue scan (Nuclei + Kingfisher) |
audit | Active/passive module scanning |
| Level | Description |
|---|---|
trace | Raw console output lines (ANSI-stripped). High volume — includes traffic lines, phase banners, progress feedback. Buffered and batch-inserted every 2 seconds. |
info | Structured lifecycle events: phase start/complete/skip, config snapshots, scan start/finish. |
warn | Non-fatal issues: phase deduplication failures, heuristics warnings. |
error | Phase failures, panic recovery, critical errors. |
| Code | Condition |
|---|---|
| 400 | Missing UUID |
| 404 | Scan not found |
| 503 | Database unavailable |
Selective Record Scan
POST /api/scan-records — Scan Specific HTTP Records
Starts an asynchronous scan on specific HTTP records identified by UUID. Returns202 Accepted on success or 409 Conflict if a scan is already running. Only one scan can run at a time.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
record_uuids | string[] | Yes | UUIDs of HTTP records to scan |
enable_modules | string[] | No | Restrict scan to specific module IDs |
| Code | Condition |
|---|---|
| 400 | Missing record_uuids or no valid records found |
| 409 | A scan is already running |
| 503 | Database unavailable |
GET /api/scan/status or GET /api/scans/:uuid to check scan progress.
POST /api/scan-all-records — Scan All DB Records
Scans existing HTTP records from the database with optional filtering. Equivalent to the DB-record scan mode, but as a dedicated route with rich filtering options. Returns202 Accepted on success, 200 OK for dry runs, or 409 Conflict if a scan is already running.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
hostname | string | No | Hostname filter (supports * wildcards, e.g. *.example.com) |
methods | string[] | No | HTTP methods filter (e.g. ["GET", "POST"]) |
path | string | No | Path filter (supports * wildcards, e.g. /api/*) |
status_codes | int[] | No | Status code filter (e.g. [200, 301]) |
source | string | No | Record source filter (e.g. ingest-server, scanner) |
search | string | No | Search across URL and path |
min_risk_score | int | No | Minimum risk score filter |
remark | string | No | Remark substring filter |
force | bool | No | Force full rescan (scan mode full vs incremental) |
dry_run | bool | No | Count matching records without launching the scan |
modules | string[] | No | Module IDs with fuzzy match (like -m) |
module_tags | string[] | No | Filter modules by tag (like --module-tag) |
concurrency | int | No | Number of parallel workers |
timeout | string | No | Request timeout as Go duration (e.g. "30s") |
max_per_host | int | No | Maximum concurrent requests per host |
rate_limit | int | No | Maximum request submissions per second |
scanning_max_duration | string | No | Global max scan duration as Go duration. Per-phase durations are derived using duration_factor (see phase duration factors above). |
heuristics_check | string | No | Heuristics check level: none, basic, advanced |
headers | map[string]string | No | Custom HTTP headers included in all requests |
scanning_profile | string | No | Scanning profile name or path |
| Code | Condition |
|---|---|
| 400 | No records match filters, or invalid params |
| 409 | A scan is already running |
| 503 | Database unavailable |
Repository Management
Endpoints for uploading and managing source code repositories for SAST scanning. Uploaded repos are stored under~/.vigolium/source-aware/uploads/<repo_id>/ (configurable via source_aware.storage_path in vigolium-configs.yaml).
POST /api/repos/upload — Upload Source Repository
Accepts a zip, tar.gz, or tar archive containing source code. Extracts it into a unique directory and returns the path for use withPOST /api/scans/run’s repo_path field.
Request: multipart/form-data with a file field. Maximum upload size: 500 MB.
Supported formats: .zip, .tar.gz / .tgz, .tar
| Code | Condition |
|---|---|
| 400 | Missing file field or unsupported archive format |
| 413 | Request body exceeds 500 MB |
| 500 | Failed to extract archive |
DELETE /api/repos/:id — Delete Uploaded Repository
Removes an uploaded repository directory by its repo ID.| Code | Condition |
|---|---|
| 400 | Missing or invalid repo ID |
| 404 | Repository not found |
| 500 | Failed to delete directory |
