Our engineers set up and run your first chatbot / LLM security scan. Get in touch

Scan suites API

← All docs

A scan suite is a saved selection of probes and endpoints. Suites are created and edited in the console at /app/suites; the API exposes them so automation can start a scan by naming a suite instead of carrying its probe list.

RouteScope
GET /api/v2/suitessuites:read
POST /api/v2/scans with suite_idscans:write

Use a suite when the probe selection is a policy decision that belongs with the security team rather than with the caller. A pipeline that passes probe_ids pins a list that goes stale as probes are added, renamed or retired; a pipeline that passes suite_id picks up the current selection on the next run.

List suites

curl -sS https://penaxtra.com/api/v2/suites \
  -H "Authorization: Bearer $TOKEN"
{
  "data": [
    {
      "id": "2a1e2496-8d50-40db-af5e-99e5eb7ee8bb",
      "name": "EU AI Act Evidence Pack - Monthly",
      "description": "Probe set the compliance team signs off on",
      "is_active": true,
      "schedule_cron": "0 3 1 * *",
      "last_run_at": "2026-08-01 03:00:11+00",
      "created_at": "2026-06-14 10:22:03+00",
      "endpoint_count": 5,
      "probe_count": 44
    }
  ]
}

Returns the 200 most recent suites for the tenant, newest first. probe_ids and endpoint_ids are summarised as counts rather than returned in full; probe content is not exposed over the API.

is_active reflects whether the suite's schedule is enabled. It does not prevent a suite from being used in a manual scan, so check it before treating last_run_at as evidence of a running schedule.

Start a scan from a suite

curl -sS -X POST https://penaxtra.com/api/v2/scans \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint_id": "11a3dd55-5369-4020-8d11-2652c26fe0d1",
    "suite_id": "2a1e2496-8d50-40db-af5e-99e5eb7ee8bb"
  }'

endpoint_id is still required and still names the single endpoint under test. suite_id supplies the probe selection. The suite's own endpoint_ids are not used here: they define which endpoints the suite's schedule covers, not which endpoint this request targets.

suite_id and probe_ids are mutually exclusive

Sending both returns 400 suite_id_conflicts_with_probe_ids. The two fields describe the same thing, and a request that carries a conflicting scope for a security scan is rejected rather than resolved by precedence. Pick one.

Errors

StatuserrorCause
400invalid_suite_idsuite_id is not a UUID
400suite_id_conflicts_with_probe_idsBoth fields were supplied
404suite_not_foundUnknown suite, or it belongs to another tenant
422suite_has_no_probesThe suite exists but its probe list is empty

An empty suite is refused rather than treated as "all probes". A caller naming a specific suite is asking for a specific selection, and expanding that to the full library would silently run a much larger scan than intended.

404 covers both an unknown id and a suite owned by another tenant, so this route cannot be used to test whether a suite id exists.

Worked example

Run every active suite against one endpoint:

set -euo pipefail
ENDPOINT=11a3dd55-5369-4020-8d11-2652c26fe0d1

curl -sS https://penaxtra.com/api/v2/suites -H "Authorization: Bearer $TOKEN" \
  | jq -r '.data[] | select(.is_active and .probe_count > 0) | .id' \
  | while read -r SUITE; do
      curl -sS -X POST https://penaxtra.com/api/v2/scans \
        -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
        -d "{\"endpoint_id\":\"$ENDPOINT\",\"suite_id\":\"$SUITE\"}"
    done

POST /api/v2/scans is limited to 6 calls per minute per token. Space the loop, or read retry_after_seconds from the 429 body and wait.

Related

Last reviewed: 2026-08-04. Reviewed by: Engineering. Content type: Developer documentation. Reach the maintainers: [email protected] .