Pentests
List pentests
GET /api/pentestsReturns all pentests for the authenticated account. Supports optional status (one of queued, capacity_queued, scanning, complete, failed) and search (matches target URL) query parameters.
Response 200 OK
[
{
"id": "9b2e6f4a-1c3d-4e5f-8a7b-6c5d4e3f2a10",
"targetUrl": "https://example.com",
"status": "complete",
"tier": "standard",
"severityCounts": { "high": 1, "medium": 3, "low": 2 },
"createdAt": "2026-03-15T10:00:00Z",
"completedAt": "2026-03-15T11:00:00Z"
}
]Create a pentest
POST /api/pentestsStarts a new penetration test. Requires a verified domain and an available credit.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
targetUrl | string | Yes* | Target URL (its domain must be verified) |
targetUrls | string[] | No | Multiple targets for a multi-domain pentest (max 20, one credit each) |
assetId | string | No | Launch against a verified asset instead of targetUrl |
repoUrl | string | No | GitHub repository URL - enables white-box tools (Code Scanner, Dep Scanner, Secret Scanner) |
notes | string | No | Scope notes passed to the AI agents (max 50,000 chars) |
credentials | string | No | Test credentials, stored encrypted (max 5,000 chars) |
creditId | string | No | Specific credit to consume (oldest available is used if omitted) |
tier | string | No | Consume a credit of a specific tier: recon, standard, deep, or blitz |
*One of targetUrl, targetUrls, or assetId is required.
The tier field uses the canonical slugs recon, standard, deep, and blitz - these are what the API and URLs use. The display names shown in the dashboard map to them as follows: Audit-Ready = standard, Threat-Hunt = deep, Adversarial-Depth = blitz (recon keeps the name Recon).
Response 201 Created
{
"id": "9b2e6f4a-1c3d-4e5f-8a7b-6c5d4e3f2a10",
"targetUrl": "https://example.com",
"status": "queued"
}If platform capacity is full, the response is 202 Accepted with "status": "capacity_queued" plus position and estimatedWaitMin fields; the pentest launches automatically when capacity frees up. A maximum of 5 pentests can be active per account at once (429 when exceeded), and only one active pentest is allowed per target (409 on conflict).
Get pentest details
GET /api/pentests/:idReturns detailed results for a specific pentest, including findings (sorted critical to info), tool results, and retest results. Supports findingsLimit (default 500, max 1000) and findingsOffset query parameters for pagination.
Response 200 OK
{
"id": "9b2e6f4a-1c3d-4e5f-8a7b-6c5d4e3f2a10",
"targetUrl": "https://example.com",
"status": "complete",
"findings": [
{
"severity": "high",
"title": "SQL Injection in login form",
"sourceTool": "Web Scanner",
"description": "..."
}
]
}Delete a pentest
DELETE /api/pentests/:idDeletes a pentest. If the pentest is still in progress it is aborted first, and its credit is refunded.
Response 200 OK
{ "success": true }Download PDF report
GET /api/pentests/:id/reportDownloads the full pentest report. Defaults to PDF; pass ?format= with one of pdf, json, markdown, xml, csv, plextrac, dradis, attackforge, or ghostwriter for other formats. Only available once the pentest status is complete.
Response 200 OK with Content-Type: application/pdf (or the matching content type for the requested format)
Download attestation letter
GET /api/pentests/:id/attestationDownloads the signed attestation letter for compliance purposes.
Response 200 OK with Content-Type: application/pdf
Authentication
Authenticate with the TurboPentest API using a Bearer token in the Authorization header on every request. Covers key format, required headers, and error responses.
Credits
List and manage your TurboPentest credits through the API, including filtering by status to see available, consumed, and expired pentest credits.