πŸ›‘ Pentestas β€Ί help

Scans API

Base URL: https://app.pentestas.com. All endpoints require authentication β€” see Authentication.

Create a scan

POST /api/scans

Body:

json
{
  "target_url": "https://app.example.com",
  "scan_types": ["web", "api", "discovery"],
  "config": {
    "custom_headers": {"Authorization": "Bearer <token>"},
    "cookies": {"sid": "abc..."},
    "credentials": {"username": "scanner@example.com", "password": "..."},
    "oauth_refresh": {
      "token_url": "https://auth.example.com/oauth/token",
      "refresh_token": "rt_..."
    },
    "max_depth": 3,
    "active_verify": false
  }
}

Response:

json
{
  "scan_id": "c4e6f0b3-...",
  "status": "pending",
  "tenant_id": "...",
  "target_url": "https://app.example.com",
  "scan_types": ["web", "api", "discovery"],
  "created_at": "2026-04-20T21:00:00Z"
}

The scan is enqueued immediately. Progress streams on /ws/scan/{scan_id}?token=<jwt>.

Field reference

Field Type Required Notes
target_url string yes Full URL with scheme
scan_types array[string] yes web / api / network / cloud / azure / google_workspace / discovery / auth / subdomain
config object no See below
config.custom_headers map no Injected on every request
config.cookies map no Cookie name β†’ value
config.credentials object no {username, password, login_url?} for form login
config.oauth_refresh object no See Authenticated scans
config.max_depth int no Crawl depth (default 3, max plan-dependent)
config.active_verify bool no Pro+ only; confirm with destructive probes
config.agent_id uuid no Dispatch scan through a specific agent

List scans

GET /api/scans?status=running&limit=50&offset=0

Filters:

  • status β€” pending / running / completed / failed / cancelled
  • target_url β€” substring match
  • scan_type β€” filter to scans including a specific type
  • since β€” ISO 8601 datetime
  • limit β€” 1–100, default 20
  • offset β€” pagination

Response: { total, scans: [{scan_id, status, target_url, findings_count, created_at, ...}] }.

Get a scan

GET /api/scans/{scan_id}

Returns the full scan object including live progress fields (current_phase, progress_message).

Get findings for a scan

GET /api/scans/{scan_id}/findings?severity=HIGH&verified=true

See Findings API.

Get the exploit graph

GET /api/scans/{scan_id}/graph

Returns attack chains + mermaid diagram text + graph edges. See Attack chain synthesis.

Export a report

GET /api/scans/{scan_id}/report?format=pdf

Formats: html, pdf, docx, json. Response is the binary; Content-Disposition: attachment set.

Cancel a scan

POST /api/scans/{scan_id}/cancel

Sets status to cancelled. A checkpoint is written so you can POST /api/scans/{scan_id}/resume later.

Resume

POST /api/scans/{scan_id}/resume

Restarts from the last checkpoint (typically a phase boundary).

Delete

DELETE /api/scans/{scan_id}

Cascade-deletes findings + reports. Audit-logged.

Rate limits

  • POST /api/scans β€” 30/min per tenant.
  • GET endpoints β€” 30/s per IP, burst 60.
  • Concurrent scan cap enforced: Free = 1, Pro = 5, Enterprise = negotiated.

Errors

Status Meaning
400 Validation failed (bad URL, unknown scan type)
401 Missing / invalid auth
403 Target domain not verified; demo user scanning outside allowed domains
404 Scan not found OR belongs to a different tenant
409 Too many concurrent scans
429 Rate limit
503 Celery queue full β€” retry with exponential backoff

See also