Pentests
Start and manage penetration test pentests
/v1/scansCreate a pentest
Create a self-hosted runner job for a target. APVISO records a `pending_runner` scan and returns a runner job; an online runner claims the job, performs preflight, launches the pinned scan image, and streams results back with a job-scoped token. For retests, specify the parent pentest ID and optionally limit the retest to specific finding IDs.
Request Body
| Name | Type | Description |
|---|---|---|
targetIdrequired | string | ID of the target to pentest. Ownership verification is not required for self-hosted targets. |
runnerId | string | Optional runner ID. When omitted, any eligible online runner for the organization can claim the job. |
isRetest | boolean | Whether this pentest is a retest of previously found vulnerabilities |
parentScanId | string | ID of the original pentest when running a retest. Required if isRetest is true |
findingIds | string[] | Specific finding IDs to retest. If omitted during a retest, all findings from the parent pentest are retested |
modelPreset | stringfreelowmediumhighultra | Pentest depth preset. Model provider credentials and actual model routing are runner-local BYOK configuration. |
promoCode | string | Deprecated compatibility field; ignored in self-hosted BYOK mode |
Example Request
curl -X POST "https://apviso.com/api/v1/scans" \
-H "X-API-Key: apvk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"targetId": "019414a8-f7c0-7d4a-b5e3-9c2d1e8f4a6b",
"runnerId": "runner-1",
"modelPreset": "high"
}'Response
Returns the new scan and runner job. The normal self-hosted lifecycle is `pending_runner` -> `assigned` -> `running` -> `completed` (or `preflight_failed`, `failed`, or `cancelled`).
{
"scan": {
"id": "019414c3-d5e6-7f8a-b9c0-1d2e3f4a5b6c",
"targetId": "019414a8-f7c0-7d4a-b5e3-9c2d1e8f4a6b",
"status": "pending_runner",
"runnerId": "runner-1",
"executionMode": "self_hosted_runner",
"targetVisibility": "public",
"scanImageDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"isRetest": false,
"parentScanId": null,
"config": {
"modelPreset": "high",
"execution": "self_hosted_runner"
},
"createdAt": "2026-05-03T09:30:14Z"
},
"runnerJob": {
"id": "job-1",
"scanId": "019414c3-d5e6-7f8a-b9c0-1d2e3f4a5b6c",
"runnerId": "runner-1",
"status": "pending_runner",
"imageRef": "ghcr.io/apviso/scan",
"imageDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updateChannel": "stable"
}
}/v1/scans/estimateEstimate pentest readiness
Check self-hosted license, target visibility, and runner readiness without creating a scan.
Request Body
| Name | Type | Description |
|---|---|---|
targetIdrequired | string | ID of the target to estimate |
isRetest | boolean | Whether this would be a retest (retests cost less) |
modelPreset | stringfreelowmediumhighultra | Pentest depth preset |
promoCode | string | Optional promotional code to factor into the estimate |
Example Request
curl -X POST "https://apviso.com/api/v1/scans/estimate" \
-H "X-API-Key: apvk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"targetId": "019414a8-f7c0-7d4a-b5e3-9c2d1e8f4a6b",
"modelPreset": "high"
}'Response
Returns readiness booleans and license/runner context. `priceCents` is zero in self-hosted BYOK mode.
{
"source": "self_hosted_license",
"priceCents": 0,
"hasPaymentMethod": true,
"eligible": true,
"runnerOk": true,
"visibilityOk": true,
"license": {
"plan": "team",
"licenseState": "active",
"runnerLimit": 10,
"concurrentJobLimit": 10
},
"runners": [
{
"id": "runner-1",
"name": "prod-runner-1",
"status": "online"
}
]
}/v1/scansList pentests
Retrieve a paginated list of all pentests for your account. Optionally filter by pentest status. Results are ordered by creation date (newest first).
Query Parameters
| Name | Type | Description |
|---|---|---|
page | numberDefault: 1 | Page number for pagination |
limit | numberDefault: 20 | Number of results per page (max 100) |
status | stringpending_runnerassignedqueuedprovisioningpreflight_failedrunningstalecompletedfailedcancelled | Filter by pentest status |
Example Request
curl -X GET "https://apviso.com/api/v1/scans" \
-H "X-API-Key: apvk_your_key_here"Response
Returns a paginated list of pentests with findings count breakdown by severity, timing information, and duration in seconds.
{
"scans": [
{
"id": "019414c3-d5e6-7f8a-b9c0-1d2e3f4a5b6c",
"targetId": "019414a8-f7c0-7d4a-b5e3-9c2d1e8f4a6b",
"target": {
"domain": "example.com"
},
"status": "completed",
"executionMode": "self_hosted_runner",
"runnerId": "runner-1",
"isRetest": false,
"parentScanId": null,
"config": {
"modelPreset": "high",
"execution": "self_hosted_runner"
},
"startedAt": "2026-05-03T09:32:08Z",
"completedAt": "2026-05-03T10:04:52Z",
"createdAt": "2026-05-03T09:30:14Z"
},
{
"id": "019414b8-e2f3-7a4b-c5d6-7e8f9a0b1c2d",
"targetId": "019414b2-a3d1-7e8b-c4f6-1d2e3f4a5b6c",
"target": {
"domain": "staging.example.com"
},
"status": "pending_runner",
"executionMode": "self_hosted_runner",
"runnerId": null,
"isRetest": false,
"parentScanId": null,
"config": {
"modelPreset": "medium",
"execution": "self_hosted_runner"
},
"startedAt": null,
"completedAt": null,
"createdAt": "2026-05-03T10:14:50Z"
}
],
"total": 2,
"page": 1,
"limit": 20,
"totalPages": 1
}/v1/scans/:idGet pentest details
Retrieve detailed information about a specific pentest, including its current status, agent progress, findings summary, and timing data.
Path Parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Pentest ID (UUIDv7) |
Example Request
curl -X GET "https://apviso.com/api/v1/scans/:id" \
-H "X-API-Key: apvk_your_key_here"Response
Returns the full pentest object with self-hosted runner metadata, target details, status, and timing fields.
{
"scan": {
"id": "019414c3-d5e6-7f8a-b9c0-1d2e3f4a5b6c",
"targetId": "019414a8-f7c0-7d4a-b5e3-9c2d1e8f4a6b",
"target": {
"domain": "example.com",
"authConfigMode": "runner_local"
},
"status": "completed",
"executionMode": "self_hosted_runner",
"runnerId": "runner-1",
"isRetest": false,
"parentScanId": null,
"config": {
"modelPreset": "high",
"execution": "self_hosted_runner"
},
"scanImageDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"startedAt": "2026-05-03T09:32:08Z",
"completedAt": "2026-05-03T10:04:52Z",
"createdAt": "2026-05-03T09:30:14Z"
}
}/v1/scans/:id/cancelCancel a pentest
Cancel a pentest that is currently queued or active. Self-hosted runner jobs receive a cancellation request and stop as soon as possible.
Path Parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Pentest ID (UUIDv7) |
Example Request
curl -X POST "https://apviso.com/api/v1/scans/:id/cancel" \
-H "X-API-Key: apvk_your_key_here"Response
Returns the updated pentest status. Self-hosted BYOK mode does not issue APVISO-hosted scan refunds.
{
"scan": {
"id": "019414c3-d5e6-7f8a-b9c0-1d2e3f4a5b6c",
"status": "cancelled",
"completedAt": "2026-05-03T09:31:02Z"
},
"refunded": false
}