Evidence & audit API
HTTP reference for sealed capture artifacts, the engagement manifest, the hashed audit chain, finding provenance and retention policy.
All paths are relative to https://api.aleex-rank.ai/api/v2 and authenticate with X-API-Key: rk_... (see REST API). Rank keeps sealed capture artifacts, a signed engagement manifest, and a hashed audit chain as three separate systems. Finding provenance and the retention policy sit alongside them. Do not mix these up with triage evidence-files or the legacy operation-narrative list.
Sealed artifacts
GET /pentests/{id}/evidence
GET /pentests/{id}/evidence/{artifactId}
Each artifact is hashed at capture. kind is screenshot, http_exchange, tool_output, packet_capture or report. classification is internal, sensitive or credential. Reading an artifact is audited (an audit-chain entry is appended).
{
"success": true,
"data": {
"items": [
{
"id": 17,
"vulnerability_id": 42,
"kind": "http_exchange",
"classification": "sensitive",
"status": "sealed",
"sha256": "a3c19e0c8b7d4f1a2e6b90c4d8e1f0ab1234567890abcdef1234567890abcdef",
"size_bytes": 18432,
"mime_type": "application/json",
"label": "boolean differential",
"captured_at": "2026-03-02 10:14:22",
"captured_by": "sqli-boolean/v1",
"retention_until": "2027-03-02 10:14:22",
"sealed_at": "2026-03-02 16:45:00"
}
],
"pagination": {"total": 1, "count": 1, "per_page": 20, "current_page": 1, "total_pages": 1},
"pentest_id": 15
}
}
Filter with ?vulnerability_id=, page and per_page. Listed statuses are sealed and purged.
GET …/evidence/{artifactId} returns {artifact, url, content_base64}. credential artifacts are inlined as base64 — there is no shareable URL. Every other classification returns a time-limited signed URL in url:
{
"success": true,
"data": {
"artifact": {
"id": 17,
"vulnerability_id": 42,
"kind": "screenshot",
"classification": "sensitive",
"status": "sealed",
"sha256": "b7e20144aa90c1d2e3f4567890abcdef1234567890abcdef1234567890abcd",
"size_bytes": 245760,
"mime_type": "image/png",
"label": null,
"captured_at": "2026-03-02 10:15:01",
"captured_by": "playwright",
"retention_until": "2027-03-02 10:15:01",
"sealed_at": "2026-03-02 16:45:00"
},
"url": "https://storage.googleapis.com/...",
"content_base64": null
}
}
A credential artifact sets url to null and fills content_base64:
{
"success": true,
"data": {
"artifact": {
"id": 18,
"kind": "tool_output",
"classification": "credential",
"status": "sealed",
"sha256": "c8f31255bb01d2e3f4567890abcdef1234567890abcdef1234567890abcd12",
"size_bytes": 512,
"mime_type": "text/plain",
"captured_at": "2026-03-02 10:16:44"
},
"url": null,
"content_base64": "LS0tLS1CRUdJTiBFWEFNUExFLS0tLS0KLi4u"
}
}
Engagement manifest
GET /pentests/{id}/manifest
The sealed summary of the engagement: a merkle_root over the artifact hashes, whether the signature verifies, and when it was sealed. 404 until the pentest is sealed (This run has not been sealed yet).
{
"success": true,
"data": {
"pentest_id": 15,
"artifact_count": 12,
"total_bytes": 1843200,
"merkle_root": "f3a91c4e7b2d8801a6c5e9d0b4f7a1234567890abcdef1234567890abcdef12",
"chain_seq": 140,
"chain_hash": "9d4e2c1b8a706f5e4d3c2b1a0987654321fedcba9876543210abcdef12345678",
"signature": "MEUCIQDx...",
"signature_alg": "ECDSA_P256_SHA256",
"sealed_at": "2026-03-02 16:45:00",
"signature_valid": true,
"artifacts_outside_seal": 0
}
}
Audit chain
GET /pentests/{id}/audit-chain
GET /pentests/{id}/audit-chain/verify
The hashed control trail (RoE activation, kill, approvals, artifact reads) — not the capture artifacts themselves. Filter with event_type, date_from, date_to, page and per_page.
{
"success": true,
"data": {
"events": [
{
"id": 901,
"event_type": "kill_requested",
"actor": "user:7",
"payload": {"reason": "Out of authorized window"},
"created_at": "2026-03-02 11:20:00",
"chain_seq": 141,
"entry_hash": "9d4e2c1b8a706f5e4d3c2b1a0987654321fedcba9876543210abcdef12345678"
}
],
"total": 142,
"page": 1,
"per_page": 50
}
}
GET …/audit-chain/verify recomputes the whole hashed trail (not only this pentest’s slice) and reports whether it still adds up. The HTTP field is valid:
{
"success": true,
"data": {
"valid": true,
"checked": 142,
"from_seq": 1,
"to_seq": 142,
"complete": true,
"unsealed": 0,
"anchors_verified": 3,
"anchors_total": 3,
"broken_at": null,
"pentest_id": 15
}
}
Finding provenance
GET /pentests/{id}/vulnerabilities/{vulnId}/provenance
Which agent, model and prompt produced the finding, which tools it invoked, and whether the stored evidence digest still matches.
{
"success": true,
"data": {
"vulnerability_id": 42,
"pentest_id": 15,
"evidence_sha256": "e1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f80",
"evidence_intact": true,
"validation": {
"status": "validated",
"method": "sqli-boolean/v1",
"validated_at": "2026-03-02 10:18:00",
"confidence_score": 40,
"confidence_rationale": "Boolean differential on the username parameter."
},
"origin": {
"operation_id": 88,
"agent_id": 101,
"agent_role": "analysis",
"model_id": 3,
"model_alias": "gemini-2.5-flash",
"provider": "google",
"prompt_ref": "analysis/v3",
"prompt_sha256": "aa11bb22cc33dd44ee55ff6677889900aa11bb22cc33dd44ee55ff6677889900",
"tool_invocations": [{"tool": "http_request"}, {"tool": "screenshot"}],
"reasoning_digest": "ff00...",
"discovered_at": "2026-03-02 10:14:18",
"recorded_at": "2026-03-02 10:16:00"
}
}
}
origin is null when provenance was never recorded. evidence_intact is null when the finding has no stored digest.
Retention policy
GET /evidence/retention-policy
PUT /evidence/retention-policy
| Field | Type | Notes |
|---|---|---|
retention_days | int | Expiry window for non-credential artifacts |
credential_retention_days | int | Must be ≤ retention_days |
Omit query params to address the caller’s personal policy. Pass ?team_id= for a team. Changing the policy rewrites expiry of existing artifacts.
{"retention_days": 365, "credential_retention_days": 30}
{
"success": true,
"data": {
"owner_type": "user",
"owner_id": 7,
"retention_days": 365,
"credential_retention_days": 30,
"is_default": false,
"artifacts_reprofiled": 12
}
}
artifacts_reprofiled is present on PUT only. A credential window longer than the general window is rejected with 400.
Legacy operation narratives
GET /pentests/{id}/evidences
This list is operation narratives (the agent steps that produced findings), not sealed artifacts. It is documented with comments on the Pentests API. Resolution screenshots and patch proof stay on the finding as evidence-files.