Documentation Index
Fetch the complete documentation index at: https://docs.vigolium.com/llms.txt
Use this file to discover all available pages before exploring further.
Starting the Server
# Start with an API key
export VIGOLIUM_API_KEY=my-secret-key
vigolium server
# Custom host and port
export VIGOLIUM_API_KEY=my-secret-key
vigolium server --host 127.0.0.1 --service-port 9002
# With transparent HTTP proxy for recording traffic
export VIGOLIUM_API_KEY=my-secret-key
vigolium server --ingest-proxy-port 9003
# Without authentication (development only)
vigolium server -A
The server listens on 0.0.0.0:9002 by default.
CORS Configuration
The server’s CORS behavior is controlled by cors_allowed_origins in ~/.vigolium/vigolium-configs.yaml:
server:
cors_allowed_origins: reflect-origin
| Value | Behavior |
|---|
reflect-origin (default) | Echoes the requesting Origin header back. Allows credentials. |
* | Allows all origins without credentials (standard wildcard). |
| (empty string) | Disables CORS middleware entirely. |
https://app.example.com, https://admin.example.com | Comma-separated allowlist. Allows credentials. |
Project Scoping
All server operations are scoped to a project via the X-Project-UUID request header. If omitted, the default project is used.
# Ingest into a specific project
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "X-Project-UUID: a1b2c3d4-..." \
-H "Content-Type: application/json" \
-d '{"input_mode": "url", "content": "https://example.com"}'
All queries (findings, HTTP records, stats, scans) return data scoped to the project specified in the header. See Projects for the full multi-tenancy reference.
Authentication
All API requests (except /health) require a Bearer token:
Authorization: Bearer my-secret-key
API key resolution order: VIGOLIUM_API_KEY env var > server.auth_api_key in config file.
API Endpoints
| Method | Path | Description |
|---|
| GET | / | App info (no auth required) |
| GET | /health | Health check (no auth required) |
| GET | /metrics | Prometheus metrics (no auth required) |
| GET | /swagger/* | Swagger UI and OpenAPI spec (no auth required) |
| GET | /server-info | Server status, queue depth, record/finding counts |
| GET | /api/modules | List available scanner modules |
| GET | /api/http-records | Query stored HTTP records |
| GET | /api/findings | Query scan findings |
| POST | /api/ingest-http | Ingest HTTP traffic into the database |
| GET | /api/stats | Aggregated scan statistics |
| GET | /api/scope | View scope configuration |
| POST | /api/scope | Update scope configuration |
| GET | /api/config | View server configuration |
| POST | /api/config | Update server configuration |
| POST | /api/scan | Trigger a background scan |
| GET | /api/scan/status | Check scan status |
| DELETE | /api/scan | Cancel a running scan |
| GET | /api/source-repos | List source repos |
| POST | /api/source-repos | Create a source repo |
| GET | /api/source-repos/:id | Get a source repo |
| PUT | /api/source-repos/:id | Update a source repo |
| DELETE | /api/source-repos/:id | Delete a source repo |
| POST | /api/agent/run/query | Single-shot agent prompt execution |
| POST | /api/agent/run/autopilot | Autonomous AI-driven scanning session |
| POST | /api/agent/run/swarm | AI-guided multi-phase vulnerability scan |
| POST | /api/agent/chat/completions | OpenAI-compatible chat completions (synchronous) |
| GET | /api/agent/status/list | List agent runs |
| GET | /api/agent/status/:id | Get agent run status (includes full result when completed) |
| GET | /api/agent/sessions | Paginated session history |
| GET | /api/agent/sessions/:id | Full session detail with debug fields |
| GET | /api/agent/sessions/:id/logs | Read or tail runtime.log (SSE supported) |
| GET | /api/agent/sessions/:id/artifacts | List session artifact files |
| GET | /api/agent/sessions/:id/artifacts/{name} | Read a specific artifact |
Ingesting Data via API
The /api/ingest-http endpoint accepts multiple input modes. All requests use POST with a JSON body.
Ingest a Single URL
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"input_mode": "url",
"content": "https://example.com/api/users?id=1"
}'
Ingest Multiple URLs (url_file mode)
Pass a newline-separated list of URLs. Lines starting with # are treated as comments.
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"input_mode": "url_file",
"content": "https://example.com/api/users?id=1\nhttps://example.com/api/posts?page=2\nhttps://example.com/login"
}'
Ingest a curl Command
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"input_mode": "curl",
"content": "curl -X POST https://example.com/api/login -H \"Content-Type: application/json\" -d \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"test\\\"}\""
}'
Using content_base64 to avoid JSON escaping issues:
# Encode the curl command
ENCODED=$(echo -n 'curl -X POST https://example.com/api/login -H "Content-Type: application/json" -d "{\"username\":\"admin\",\"password\":\"test\"}"' | base64)
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d "{
\"input_mode\": \"curl\",
\"content_base64\": \"$ENCODED\"
}"
Ingest a Raw HTTP Request (Burp-style)
Send a base64-encoded raw HTTP request, optionally with its response:
# Encode raw request
RAW_REQ=$(printf 'GET /api/users?id=1 HTTP/1.1\r\nHost: example.com\r\nCookie: session=abc123\r\n\r\n' | base64)
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d "{
\"input_mode\": \"burp_base64\",
\"http_request_base64\": \"$RAW_REQ\"
}"
With both request and response:
RAW_REQ=$(printf 'POST /api/login HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/json\r\n\r\n{"username":"admin","password":"test"}' | base64)
RAW_RESP=$(printf 'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{"token":"eyJhbGciOiJIUzI1NiJ9..."}' | base64)
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d "{
\"input_mode\": \"burp_base64\",
\"http_request_base64\": \"$RAW_REQ\",
\"http_response_base64\": \"$RAW_RESP\"
}"
Ingest a Raw HTTP Request with a URL Hint
Raw HTTP requests don’t contain the scheme (https vs http), and the Host header may not match the public hostname (e.g. behind a load balancer). Use the url field to provide the correct scheme and host:
RAW_REQ=$(printf 'POST /api/login HTTP/1.1\r\nHost: internal-lb\r\nContent-Type: application/json\r\n\r\n{"user":"admin"}' | base64)
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d "{
\"input_mode\": \"burp_base64\",
\"url\": \"https://app.example.com\",
\"http_request_base64\": \"$RAW_REQ\"
}"
Ingest an OpenAPI / Swagger Spec
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"input_mode": "openapi",
"content": "{\"openapi\":\"3.0.0\",\"info\":{\"title\":\"Example\",\"version\":\"1.0\"},\"servers\":[{\"url\":\"https://api.example.com\"}],\"paths\":{\"/users\":{\"get\":{\"summary\":\"List users\"}},\"/users/{id}\":{\"get\":{\"summary\":\"Get user\",\"parameters\":[{\"name\":\"id\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"integer\"}}]}}}}"
}'
Using base64 for larger specs:
SPEC=$(base64 < openapi.yaml)
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d "{
\"input_mode\": \"openapi\",
\"content_base64\": \"$SPEC\"
}"
Ingest a Postman Collection
COLLECTION=$(base64 < collection.json)
curl -X POST http://localhost:9002/api/ingest-http \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d "{
\"input_mode\": \"postman_collection\",
\"content_base64\": \"$COLLECTION\"
}"
Ingesting Data via CLI
The vigolium ingest command supports both remote (server) and local (direct-to-database) modes.
Remote Ingestion (to a running server)
export VIGOLIUM_API_KEY=my-secret-key
# Pipe URLs from stdin
cat urls.txt | vigolium ingest -s http://localhost:9002
# From a file
vigolium ingest -s http://localhost:9002 --input targets.txt
# OpenAPI spec with a base URL
vigolium ingest -s http://localhost:9002 \
--input api.yaml -I openapi -t https://api.example.com
# Control submission rate
vigolium ingest -s http://localhost:9002 \
--input urls.txt --concurrency 20 -r 200
Local Ingestion (direct to database)
When --server is omitted, requests are fetched and stored directly in the local database:
# Ingest URLs (fetches each and stores request + response)
cat urls.txt | vigolium ingest
# From an OpenAPI spec
vigolium ingest --input api.yaml -I openapi -t https://api.example.com
# With a custom scan ID for tagging
vigolium ingest --input urls.txt --scan-id recon-2026-02
# Use a specific database file
vigolium ingest --input urls.txt --db ./project.db
# Ingest into a specific project
vigolium ingest --input urls.txt --project-id a1b2c3d4-...
Ingesting via Transparent Proxy
Start the server with a proxy port to passively record HTTP traffic:
export VIGOLIUM_API_KEY=my-secret-key
vigolium server --ingest-proxy-port 9003
Then route your tools through the proxy:
# curl through the proxy
curl -x http://localhost:9003 https://example.com/api/users
# httpx through the proxy
echo "https://example.com" | httpx -proxy http://localhost:9003
# nuclei through the proxy
nuclei -u https://example.com -proxy http://localhost:9003
All proxied HTTP traffic is automatically recorded in the database. HTTPS CONNECT tunneling is passed through without recording.
Querying Ingested Data
List HTTP Records
# All records (paginated, default limit=50)
curl -s http://localhost:9002/api/http-records \
-H "Authorization: Bearer my-secret-key" | jq .
# Filter by domain
curl -s "http://localhost:9002/api/http-records?domain=example.com" \
-H "Authorization: Bearer my-secret-key" | jq .
# Filter by status code and method
curl -s "http://localhost:9002/api/http-records?status_code=200,302&method=GET,POST" \
-H "Authorization: Bearer my-secret-key" | jq .
# Search across URLs and headers
curl -s "http://localhost:9002/api/http-records?search=admin&limit=10" \
-H "Authorization: Bearer my-secret-key" | jq .
# Pagination
curl -s "http://localhost:9002/api/http-records?limit=20&offset=40" \
-H "Authorization: Bearer my-secret-key" | jq .
List Findings
# All findings
curl -s http://localhost:9002/api/findings \
-H "Authorization: Bearer my-secret-key" | jq .
# Filter by severity
curl -s "http://localhost:9002/api/findings?severity=high,critical" \
-H "Authorization: Bearer my-secret-key" | jq .
# Filter by module
curl -s "http://localhost:9002/api/findings?module_name=xss-reflected" \
-H "Authorization: Bearer my-secret-key" | jq .
# Filter by domain
curl -s "http://localhost:9002/api/findings?domain=example.com" \
-H "Authorization: Bearer my-secret-key" | jq .
Server Info
curl -s http://localhost:9002/server-info \
-H "Authorization: Bearer my-secret-key" | jq .
Response:
{
"version": "0.1.0",
"uptime": "2h15m30s",
"service_addr": "0.0.0.0:9002",
"proxy_addr": "0.0.0.0:9003",
"db_driver": "sqlite",
"queue_depth": 0,
"total_records": 1542,
"total_findings": 23
}
Scan Management via API
After ingesting HTTP records, trigger a vulnerability scan via the API.
Trigger a Scan
curl -s -X POST http://localhost:9002/api/scan \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{}' | jq .
Force re-scan with specific modules:
curl -s -X POST http://localhost:9002/api/scan \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"force": true,
"enable_modules": ["xss-scanner", "sqli-error-based"]
}' | jq .
Returns 202 Accepted on success, 409 Conflict if a scan is already running.
Check Scan Status
curl -s http://localhost:9002/api/scan/status \
-H "Authorization: Bearer my-secret-key" | jq .
Cancel a Running Scan
curl -s -X DELETE http://localhost:9002/api/scan \
-H "Authorization: Bearer my-secret-key" | jq .
See the API Reference for full request/response details.
Running AI Agents via API
The agent API provides three run modes that mirror the vigolium agent CLI subcommands. Only one agent run can be active at a time (returns 409 Conflict if busy).
Query, Single-Shot Agent Run
curl -s -X POST http://localhost:9002/api/agent/run/query \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"prompt_template": "security-code-review",
"source": "/home/user/src/my-app"
}' | jq .
At least one of prompt_template, prompt_file, or prompt is required. Returns 202 Accepted on success. Set "stream": true for real-time SSE output. The legacy repo_path JSON field is still accepted as an alias for source.
Autopilot, Autonomous Scanning
curl -s -X POST http://localhost:9002/api/agent/run/autopilot \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"target": "https://example.com",
"focus": "API injection",
"intensity": "balanced",
"stream": true
}'
Swarm, AI-Guided Multi-Phase Scan
curl -s -X POST http://localhost:9002/api/agent/run/swarm \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{
"input": "https://example.com",
"discover": true,
"triage": true,
"stream": true
}'
SSE events are data: lines with JSON payloads: {"type":"chunk","text":"..."} for real-time output, {"type":"phase","phase":"..."} for swarm phase transitions, {"type":"done","result":{...}} on completion, or {"type":"error","error":"..."} on failure.
Provider overrides are CLI-only. The server resolves the olium provider once from agent.olium.* in vigolium-configs.yaml. To switch providers on a server-side workload, edit the YAML and reload, there is no per-request provider field.
List All Agent Runs
curl -s http://localhost:9002/api/agent/status/list \
-H "Authorization: Bearer my-secret-key" | jq .
Check Agent Run Status
curl -s http://localhost:9002/api/agent/status/agt-550e8400... \
-H "Authorization: Bearer my-secret-key" | jq .
Once the run completes, the response includes a result field with the full agent output (raw text, findings, HTTP records).
See Agent Mode for the full agent documentation (autopilot, swarm, vigolium-audit, query, olium) and the API Reference for request/response details.
| Mode | Content Field | Description |
|---|
url | content | A single URL |
url_file | content | Newline-separated list of URLs |
curl | content or content_base64 | A curl command string |
burp_base64 | http_request_base64 | Base64-encoded raw HTTP request |
openapi / swagger | content or content_base64 | OpenAPI/Swagger spec (JSON or YAML) |
postman_collection | content or content_base64 | Postman Collection (JSON) |
For burp_base64 mode, you can also include http_response_base64 to store the response alongside the request.
For modes that accept large payloads, prefer content_base64 to avoid JSON escaping issues.