Skip to main content

Project Scoping

All scan endpoints support multi-tenancy via the X-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.
If the header is omitted, the default project is used.

Single-Target Scans

POST /api/scan-url, Scan a URL

Starts an asynchronous scan of a single URL. Equivalent to the CLI scan-url command. Returns 202 Accepted immediately with a scan ID. Request body:
Response (202):
A target the scope refuses is 422, not an accepted scan (v0.5.3). POST /api/scan-url and /api/scan-request run the same scope-admission check the CLI does, before anything is sent, and answer 422 with details: "no_targets_in_scope" rather than returning a 202 for a scan that would do nothing. The response names the rule that refused it.REST scans resolve their options the same way vigolium scan does as of v0.5.3 — the two used to drift, so a profile or intensity that worked on the CLI could behave differently over the API.

POST /api/scan-request, Scan a Raw HTTP Request

Starts an asynchronous scan from a base64-encoded raw HTTP request. Equivalent to the CLI scan-request command. Returns 202 Accepted immediately with a scan ID. Since v0.5.3 it settles a schemeless request like the CLI does: when the raw request gives no hint of http vs https, the scheme is probed rather than guessed. Request body:
Response (202):
Error responses (both endpoints): Use 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 to vigolium scan -t <url>. At least one target URL is required, 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:
Source-aware whitebox analysis lives in agent mode. Use POST /api/agent/run/swarm with a source field for AI-driven route extraction + code audit + targeted scanning, POST /api/agent/run/autopilot for autonomous pentest with code context, or POST /api/agent/run/audit (CLI: vigolium agent audit) for the unified source-audit driver dispatcher.
Phase duration factors: The 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: Per-phase max_duration overrides in the YAML config take precedence over the factor calculation. Phase names and aliases:
Note: only and skip are mutually exclusive, providing both returns 400.
Response (202):
Response, dry run (200):
Scan Configuration output: When a scan starts (via API or CLI), the runner logs a configuration summary to stderr showing the effective settings. This is useful for verifying that scanning_max_duration and per-phase duration factors are applied correctly.
Error responses:

GET /api/scan/status, Scan Status

Returns the status of the current or most recent scan. The status field reflects pause state when applicable.
Running:
Paused:
Idle (no scan running):

To cancel a running scan, call POST /api/scans/:uuid/stop (covered under Scan Management) — there is no global DELETE /api/scan route.

Scan History

GET /api/scans, List Scans

Returns paginated scan history ordered by creation date (newest first). Query parameters:

GET /api/scans/:uuid, Get Scan Detail

Returns a single scan by UUID.
Error responses:

Scan completeness

Added in v0.5.2. status says whether the scan process reached its end. completeness says whether the run actually covered the input it was given. They are independent, and both are needed: a scan can reach its end having scanned half its records. Each phase outcome carries: The same fields ride --format jsonl and the scan document vigolium scan -j prints, so one reading of “did this run cover the target” works across the CLI and the API.
reasons and limits are different claims. A limit is a bound you configured being honoured; a reason is coverage you asked for and did not get. Alerting on limits will page you for scans that worked exactly as specified.

DELETE /api/scans/:uuid, Delete Scan

Deletes a scan record by UUID.
Error responses:

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.
Error responses:

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.
Error responses:

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".
Error responses:

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.
Query parameters:
v0.4.2: this endpoint returns the last 2 MiB of runtime.log by default rather than the whole file on every poll — a long-running scan’s log grows without bound, and a dashboard polling it was re-reading all of it each time. Raise the window with ?max_bytes= (hard cap 64 MiB).
Response, structured events (level=info):
Response, raw console output (level=trace):
Response, configuration snapshot (phase=config):
Log entry fields: Phase values: Log levels: Error responses:

Selective Record Scan

POST /api/scan-records, Scan Specific HTTP Records

Starts an asynchronous scan on specific HTTP records identified by UUID. Returns 202 Accepted on success or 409 Conflict if a scan is already running. Only one scan can run at a time. Request body:
Fixed in v0.4.2: record UUIDs were validated unscoped, so a leaked UUID could pull another project’s traffic into a scan. They are now resolved within the requesting project only. The endpoint also caps record_uuids at 10,000 and checks scan admission before enumerating them, so a rejected request costs nothing.
Response (202):
Error responses: Use 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. Returns 202 Accepted on success, 200 OK for dry runs, or 409 Conflict if a scan is already running. Request body:
Response (202):
Response, dry run (200):
Error responses:

Source Code Upload

Source code uploads for AI-driven analysis (swarm, autopilot, audit) are handled via the cloud-storage API. See Storage API:
  • POST /api/storage/upload-source: upload a source archive (zip, tar.gz, tar.bz2, tar.xz)
  • GET /api/storage/source/:key: download a previously-uploaded archive
  • POST /api/storage/presign: get a presigned URL for direct client-side upload
The returned storage_url (e.g. gs://<project-uuid>/ugc/source.tar.gz) can be passed to --source (CLI) or the source field on POST /api/agent/run/{query,autopilot,swarm,audit}.