Start a pentest
Copy page
Start a pentest
Starts a pentest draft that has a completed estimate. The confirmed credits are deducted when the pentest starts. Only organisation admins can call it.
Set
expected_creditsto the estimate’stotal_credits, plustriage_fee_creditsif triage is required or you settriage_enabled. If the current cost differs from this total, the endpoint returns409without spending credits. If the organisation has insufficient credits, it returns402.Every login target needs a login check that passed within the last hour. Run the checks with
POST /pentests/{id}/login-checks.
After it starts, follow the pentest with GET /scans/{id}/status using the same scan_id, read its results with GET /scans/{id}/findings, or stop it with POST /scans/{id}/stop.
Request
POST /pentests/{id}/start
Send an API key
with the write scope
in the X-Api-Key header.
Path parameters
| Parameter | Description |
|---|---|
id string, required |
Body
A required application/json body.
| Field | Description |
|---|---|
expected_credits integer, required | The total the user confirmed: the estimate's total_credits, plus triage_fee_credits when triage is required or opted in. At least 1. |
triage_enabled boolean | Opt in to human triage of findings when it is not already required. |
Responses
200 OK
| Field | Description |
|---|---|
scan_id string (uuid), required | Stable pentest id; task_id changes when it starts. |
status string, required | One of pending, running, completed, failed, stopped, cancelled, skipped, pending_verification, pending_triage, draft, estimating, or estimated. |
repos array of object, required | |
repos[]. array of string | Whitebox scope: gitignore-style globs (relative to the repo root) that narrow the scan to matching paths. Empty means the whole repository. |
repos[]. array of string | Whitebox scope: gitignore-style globs removed from the scan after include_paths is applied; use *.md to drop a file type. |
repos[]. string | One of connected, public, or upload. |
repos[]. string, read-only | Resolved by the server at scan start; ignored on input. One of github, gitlab, bitbucket, or azure. |
repos[]. string | Repository URL. |
repos[]. string | Branch name, tag name, or commit SHA. |
repos[]. string | How branch was selected (UI hint for draft re-use). One of branch, tag, or sha. |
repos[]. string | Scan archive ID. |
repos[]. number | GitHub App installation ID (connected repos only). |
target_urls array of string, required | |
login_targets array of object, required | |
login_targets[]. string, required | |
login_targets[]. string, required | Whether Hacktron could sign in with the login the site has now. A pass lasts an hour, and changing the site or login makes it unverified. One of unverified, pending, running, succeeded, failed, cancelled, or expired. |
login_targets[]. string, required, nullable | Why the check failed, without credentials. |
custom_context string, required, nullable | |
application_id string (uuid), required, nullable | |
cost_estimation_id string (uuid), required, nullable | |
triage_enabled boolean, required, nullable | |
credits_used number, required, nullable |
400 Bad Request
A login target has no passing login check from the last hour.
402 Payment Required
Insufficient credits.
409 Conflict
expected_credits no longer matches the total; read the estimate again and confirm the new total.