A finding is a single security issue identified by a probe and scored by three independent judges plus a meta-judge. Findings carry severity, framework references, evidence, and status.
GET /api/v2/findings
curl -sS "https://penaxtra.com/api/v2/findings?severity=high" \
-H "Authorization: Bearer $TOKEN"
Required scope: findings:read. Result set capped at 200 rows; newest first.
Query parameters
| Param | Type | Notes |
|---|---|---|
severity | enum | One of critical, high, medium, low, info. |
Additional filters (endpoint_id, scan_id, framework_ref, from, to, cursor-based pagination) are planned. Today the list returns the most recent 200 rows after the severity filter.
Response
{
"data": [
{
"id": "<uuid>",
"scan_id": "<uuid>",
"title": "Indirect prompt injection via RAG corpus",
"severity": "high",
"status": "open",
"jira_issue_key": null,
"discovered_at": "2026-05-22T10:24:01Z"
}
]
}
GET /api/v2/findings/{id}
curl -sS "https://penaxtra.com/api/v2/findings/<uuid>" \
-H "Authorization: Bearer $TOKEN"
Required scope: findings:read.
Response
{
"id": "<uuid>",
"scan_id": "<uuid>",
"title": "Indirect prompt injection via RAG corpus",
"severity": "high",
"status": "open",
"jira_issue_key": null,
"discovered_at": "2026-05-22T10:24:01Z",
"risk_refs": ["OWASP_LLM01", "MITRE_ATLAS_AML_T0051", "EU_AI_ACT_Art15"],
"summary": "Short, redacted excerpt of the finding rationale."
}
Extended detail (evidence payload, per-judge breakdown, automated remediation hint) is planned.
Errors
| Code | Body | Reason |
|---|---|---|
400 | {"error":"invalid_finding_id"} | Id is missing or not a UUID. |
404 | {"error":"finding_not_found"} | Id does not belong to the caller's tenant. |
PATCH /api/v2/findings/{id}
curl -sS -X PATCH "https://penaxtra.com/api/v2/findings/<uuid>" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"triaged"}'
Required scope: findings:write.
Accepted status values match the database constraint (migration 008):
open, triaged, fixed, false_positive, risk_accepted
Sending any other value returns 400 invalid_status.
Response
{
"updated": true,
"id": "<uuid>",
"status": "triaged"
}
Errors (PATCH)
| Code | Body | Reason |
|---|---|---|
400 | {"error":"bad_id"} | Path id is malformed. |
400 | {"error":"invalid_status"} | Status value is not on the accepted list. |
404 | {"error":"finding_not_found"} | Id does not belong to the caller's tenant. |
Audit
Every PATCH is recorded as an api.call row plus a finding.status_changed row carrying before / after status. Use the audit log API to reconcile.
Security notes
- Findings older than the tenant's configured audit retention are pruned automatically.
- The list endpoint does not return finding bodies; use the single-GET above for the per-row detail set.
Related
Last reviewed: 2026-06-13. Reviewed by: Engineering. Content type: Developer documentation. Reach the maintainers: [email protected] .