Vulnerabilities API

HTTP reference for listing findings, state transitions, bulk updates, comments, evidence files, history, summary, quality gates and export.

All paths are relative to https://api.aleex-rank.ai/api/v2 and authenticate with X-API-Key: rk_... (see REST API). Findings hang off a pentest, so most paths begin with /pentests/{id}/vulnerabilities. For the lifecycle model — states, severity, SLAs and evidence — read Vulnerabilities.

List vulnerabilities

GET /pentests/{id}/vulnerabilities

Returns the findings for a pentest. Supports page and per_page, and can be filtered by status, severity and priority.

{
  "success": true,
  "data": {
    "items": [
      {
        "id": 42,
        "title": "Reflected XSS in search",
        "severity": "high",
        "status": "open",
        "priority": "normal",
        "due_date": "2026-02-17 14:30:00",
        "assigned_to": null,
        "created_at": "2026-02-10 14:30:00"
      }
    ],
    "pagination": {"total": 1, "count": 1, "per_page": 20, "current_page": 1, "total_pages": 1}
  }
}

Retrieve, update, delete

GET    /pentests/{id}/vulnerabilities/{vulnId}
PATCH  /pentests/{id}/vulnerabilities/{vulnId}
DELETE /pentests/{id}/vulnerabilities/{vulnId}

GET returns the full finding. PATCH updates editable fields. DELETE removes it.

State transitions

A finding is always open, in_progress, resolved, false_positive or accepted_risk. The dedicated endpoints below carry the extra data each transition needs; the generic status endpoint only moves a finding to open or in_progress.

Resolve

POST /pentests/{id}/vulnerabilities/{vulnId}/resolve
{
  "resolution_type": "evidenced",
  "comment": "Upgraded nginx and added output encoding"
}

resolution_type is evidenced (requires at least one uploaded evidence file, else 400) or without_evidence.

Reopen

POST /pentests/{id}/vulnerabilities/{vulnId}/reopen

Sends a closed finding back to open and recomputes its due date. Reopening a false positive clears the stored reason.

False positive

POST /pentests/{id}/vulnerabilities/{vulnId}/false-positive
{
  "reason": "Endpoint is behind authentication and not externally reachable",
  "comment": "Confirmed with the infrastructure team"
}

reason is required (max 2000 characters).

Accept risk

POST /pentests/{id}/vulnerabilities/{vulnId}/accept-risk
{"reason": "Accepted for this release; tracked in RISK-128"}

Generic status and priority

PATCH /pentests/{id}/vulnerabilities/{vulnId}/status
PATCH /pentests/{id}/vulnerabilities/{vulnId}/priority
{"status": "in_progress"}
{"priority": "urgent"}

The status endpoint accepts only open and in_progress. Use the dedicated endpoints above for resolved, false_positive and accepted_risk.

Assignment

POST   /pentests/{id}/vulnerabilities/{vulnId}/assign
DELETE /pentests/{id}/vulnerabilities/{vulnId}/assign

The pentest must belong to a team and the assignee must be a member of it. Assigning an open finding moves it to in_progress automatically and emails the assignee.

{"user_id": 42, "comment": "Please verify the patch"}

DELETE …/assign unassigns (no body).

Comments

GET    /pentests/{id}/vulnerabilities/{vulnId}/comments
POST   /pentests/{id}/vulnerabilities/{vulnId}/comments
PATCH  /pentests/{id}/vulnerabilities/{vulnId}/comments/{commentId}
DELETE /pentests/{id}/vulnerabilities/{vulnId}/comments/{commentId}

GET returns a combined feed of user comments and automatic system entries. Filter with ?type=comment, ?type=status_change or ?type=assignment. You may only edit and delete your own comment entries (max 5000 characters).

{"comment": "Verified the fix is deployed to production"}

Evidence files

POST   /pentests/{id}/vulnerabilities/{vulnId}/evidence-files
GET    /pentests/{id}/vulnerabilities/{vulnId}/evidence-files
GET    /pentests/{id}/vulnerabilities/{vulnId}/evidence-files/{fileId}
DELETE /pentests/{id}/vulnerabilities/{vulnId}/evidence-files/{fileId}

Upload up to 20 files per finding, each up to 10 MB, of type jpg, jpeg, png, gif, webp, pdf, txt or csv. Each file is validated by extension, declared MIME type and actual content. Upload as multipart/form-data with files[], or as base64 JSON:

{
  "files": [
    {"name": "patch-proof.png", "data": "data:image/png;base64,iVBORw0KGgo..."}
  ]
}

Fetching a file returns a time-limited signed download URL:

{
  "id": 1,
  "vulnerability_id": 42,
  "file_name": "patch-proof.png",
  "file_type": "image/png",
  "file_size": 245760,
  "download_url": "https://storage.googleapis.com/...",
  "created_at": "2026-02-10 12:00:00"
}

GET /pentests/{id}/vulnerabilities/{vulnId}/evidence (singular) returns the original discovery evidence the agents produced, distinct from resolution evidence files.

History

GET /pentests/{id}/vulnerabilities/{vulnId}/history

An immutable audit trail of every status change.

{
  "success": true,
  "data": {
    "history": [
      {
        "id": 3,
        "changed_by": 1,
        "old_status": "false_positive",
        "new_status": "open",
        "reason": "Confirmed the issue is real after retest",
        "created_at": "2026-02-10 14:30:00"
      }
    ],
    "total": 1,
    "page": 1,
    "per_page": 50
  }
}

Bulk status update

PATCH /pentests/{id}/vulnerabilities/bulk-status

Update many findings in one transaction — ideal for pipeline triage. Up to 100 ids, transitions limited to open and in_progress. Findings that can’t transition are skipped, not failed.

{
  "vulnerability_ids": [1, 2, 3, 5, 8],
  "status": "in_progress",
  "comment": "Triaging after scan v2.4.1",
  "reason": "Pipeline automated triage"
}
{
  "success": true,
  "data": {
    "message": "5 vulnerability(ies) updated",
    "updated": 5,
    "skipped": 0,
    "total_requested": 5,
    "errors": []
  }
}

Summary

GET /pentests/{id}/vulnerabilities/summary

A rollup for dashboards and gates. The summary object is returned directly inside data.

{
  "total": 45,
  "by_status": {"open": 12, "in_progress": 8, "resolved": 20, "false_positive": 3, "accepted_risk": 2},
  "by_severity": {"critical": 2, "high": 10, "medium": 18, "low": 15, "info": 0},
  "by_priority": {"urgent": 3, "high": 7, "normal": 30, "low": 5},
  "resolution_rate": 0.556,
  "mean_time_to_resolve_hours": 48.3,
  "overdue_count": 4
}

A global summary across all your pentests is available at GET /vulnerabilities/summary.

Quality gate

POST /pentests/{id}/vulnerabilities/quality-gate

Evaluate pass/fail rules against the current findings — use it to block a deploy.

{
  "rules": [
    {"severity": "critical", "max_open": 0},
    {"severity": "high", "max_open": 5},
    {"min_resolution_rate": 0.8},
    {"max_overdue": 0}
  ]
}
{
  "passed": false,
  "failures": [
    {"rule": "critical max_open 0", "actual": 2, "expected": 0}
  ]
}

Supported rule types: severity + max_open, min_resolution_rate (0–1), and max_overdue.

Export

GET /pentests/{id}/vulnerabilities/export?format=csv
GET /pentests/{id}/vulnerabilities/export?format=json

Download every finding for a pentest. CSV responses include a Content-Disposition: attachment header. Fields include id, title, description, severity, status, priority, assigned_to, resolution_type, false_positive_reason, due_date, created_at, resolved_at and resolved_by.

Availability

Bulk status, quality gate and webhooks are gated by tier. Assignment to team members requires a team plan; individual Ultra accounts have full triage but no team assignment. See Teams & tiers. To get notified when findings change, see Webhooks.