Skip to content

API reference

Quick start

bash
# Health check
curl http://localhost:8080/health

# Create a run against OWASP Juice Shop
curl -X POST http://localhost:8080/runs \
  -H "Content-Type: application/json" \
  -d '{
    "scope_id": "local-juice-shop",
    "targets": ["http://juice-shop:3000"],
    "test_pack": "juice-shop-detect"
  }'

# Poll run status
curl http://localhost:8080/runs/run_550e8400-e29b-41d4-a716-446655440000

# Read event history (NDJSON)
curl http://localhost:8080/runs/run_550e8400-e29b-41d4-a716-446655440000/events

Endpoints

MethodPathDescription
GET/healthLiveness check
GET/runsList all runs
GET/runs/statsAggregated status counts
POST/runsCreate a run (one job per target)
POST/runs/bulkCreate many runs (benchmarking)
GET/runs/{run_id}Get run metadata
DELETE/runs/{run_id}Delete run and its events
GET/runs/{run_id}/eventsEvent history as NDJSON
POST/runs/{run_id}/cancelMark run cancelled
POST/admin/queue/clearClear queue state (noop placeholder)
POST/admin/runs/clearDelete all run records

Create run

POST /runs

Creates a run record in Postgres and publishes one NATS job per target.

Request body

json
{
  "scope_id": "local-juice-shop",
  "targets": ["http://juice-shop:3000"],
  "test_pack": "juice-shop-detect"
}
FieldRequiredDescription
scope_idyesMust match a worker scope and NATS subject suffix
targetsyesOne or more base URLs to test
test_packyesTest pack name (filename without .yaml)

Response

json
{
  "run_id": "run_550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "outcome": "unknown"
}

The test_pack value is validated at request time. The file must exist at /app/test-packs/{test_pack}.yaml inside the control-api container.

Bulk create

POST /runs/bulk

Creates a separate run for each target. When targets is omitted, the single target value is repeated count times.

Request body

json
{
  "scope_id": "local-juice-shop",
  "target": "http://juice-shop:3000",
  "test_pack": "juice-shop-detect",
  "count": 100
}

Response

json
{
  "status": "queued",
  "created": 100
}

Run lifecycle

StatusMeaning
queuedRun created; job published to NATS
runningWorker claimed job and started target
completedWorker finished all test-pack steps
cancelledCancelled via API
failedReserved for future use
OutcomeMeaning
unknownRun not finished
not_exploitableCompleted with no critical/high findings
potentially_exploitableA critical or high severity finding was emitted
exploitableReserved for future use
errorReserved for future use

Workers update status and outcome in Postgres as events are emitted. See Run events below.

Run events

GET /runs/{run_id}/events

Returns newline-delimited JSON. Each line is one event object:

json
{"event_type":"target.started","run_id":"run_...","target":"http://juice-shop:3000","message":"running test pack juice-shop-detect","severity":null}
{"event_type":"request.sent","run_id":"run_...","target":"http://juice-shop:3000","message":"root GET /","severity":null}
{"event_type":"finding.created","run_id":"run_...","target":"http://juice-shop:3000","message":"OWASP Juice Shop detected","severity":"critical"}
{"event_type":"target.completed","run_id":"run_...","target":"http://juice-shop:3000","message":"target completed","severity":null}

Common event types:

EventDescription
worker.job.claimedWorker picked up the job
target.startedTest pack execution began
request.sentHTTP request dispatched
request.completedHTTP response received
request.errorRequest failed (timeout, DNS, etc.)
assert.passedAssertion succeeded
assert.failedAssertion failed; later steps skipped
extract.completedVariable extracted from response
extract.failedRegex extraction failed
finding.createdSecurity finding recorded
scope.blockedRequest blocked by scope rules
step.skippedStep skipped after prior failure
target.completedAll steps finished for target
test_pack.errorTest pack missing or invalid

Set HELLION_VERBOSE_EVENTS=false on workers to suppress low-signal events from storage while still updating run status.

Admin endpoints

Use these before benchmarks or e2e tests to reset state:

bash
curl -X POST http://localhost:8080/admin/queue/clear
curl -X POST http://localhost:8080/admin/runs/clear

NATS subjects

Jobs are published to:

hellion.jobs.http.{scope_id}

Workers subscribe with queue group hellion-http-workers; jobs are load-balanced across worker instances.

Error responses

CodeCause
400Missing fields, invalid JSON, or unknown test pack
404Run not found
405Wrong HTTP method
500Postgres or NATS error

Native tools, weird experiments, and practical performance work.