Skip to content

Endpoints: Metrics & Audit

All metrics endpoints require admin role, and are scoped to the caller’s own organization. Three span types are recorded automatically:

TypeRecorded whenKey fields in data
requestEvery HTTP requestmethod, path, status_code, auth_type (api_key/session/anonymous)
ingestEvery ingest — POST .../ingest and POST .../analyze (see below)namespace, analyzer, resource_count
analysisSuccessful analysis submissionresource_type, resource_address, finding_count, severity_counts

Every span carries key_id (the API-key principal, if any) and user_id (the session principal, if any) as separate top-level fields — exactly one is non-null on a given span, mirroring AuthContext’s own split. These used to be merged into one key_id field; they’re independent now specifically so a span can be filtered or attributed to a genuine human actor without conflating them with a machine one.


Aggregated statistics for the last N days.

ParameterTypeDefaultDescription
daysint7Aggregation window (1–365)

Response 200

{
"period_days": 7,
"requests": {
"total": 1240,
"by_status": {"200": 900, "201": 180, "401": 60, "404": 100},
"by_method": {"GET": 980, "POST": 180, "PUT": 80},
"error_count": 160,
"error_rate_pct": 12.9,
"avg_duration_ms": 38.4
},
"ingest": {"total": 42, "total_resources": 310},
"analysis": {
"total": 310,
"by_severity": {"CRITICAL": 12, "HIGH": 88, "MEDIUM": 130, "LOW": 45, "INFO": 35},
"avg_findings_per_resource": 2.9
}
}

Paginated raw span log, newest first.

ParameterTypeDefaultDescription
typestringFilter: request, ingest, or analysis
user_idstringFilter to spans from this human (session) actor
key_idstringFilter to spans from this machine (API-key) actor
limitint100Number of results (1–1000)
offsetint0Pagination offset

Response 200

[
{
"span_id": "3f4a...",
"trace_id": "x-request-id-value",
"type": "ingest",
"timestamp": "2026-01-01T12:00:00Z",
"duration_ms": 45.2,
"key_id": "config",
"user_id": null,
"data": {
"namespace": "prod-deploy-42",
"analyzer": "terraform-plan",
"resource_count": 7
}
}
]

Per-key request counts, sorted descending.

ParameterTypeDefaultDescription
daysint7Aggregation window (1–365)

Response 200

[
{"key_id": "config", "request_count": 540},
{"key_id": "3f4a5b6c-...", "request_count": 700}
]

key_id is _anon when auth is disabled. Only counts api_key-authenticated requests (see the Metrics section’s note above) — a session-authenticated dashboard user never appears here bucketed under their user_id as if it were a key.


Distinct from the spans above: spans describe HTTP shape (method/path/status/ duration) and coarse ingest/analysis counts; audit events describe privileged actions — who changed what, on which target, with before/after values. All audit endpoints require admin role and are scoped to the caller’s own organization (see Platform admin below for the cross-org equivalent).

Instrumented actions (first cut — see the note at the end of this section for what’s deliberately not yet covered):

ActionTarget typeFired by
settings.updateplatform_settingsPATCH /admin/settings
org.lockorganizationPATCH /admin/organizations/{org_id}/lock
org.plan_updateorganizationPATCH /admin/organizations/{org_id}/plan
org.2fa_policy_updateorganizationPATCH /admin/organizations/{org_id}/2fa-policy
superadmin.grantuserPOST /admin/users/{user_id}/superadmin
member.role_updatemembershipPATCH /orgs/{org_id}/members/{user_id} (org-admin) or its superadmin mirror PATCH /admin/organizations/{org_id}/members/{user_id}
member.removemembershipDELETE /orgs/{org_id}/members/{user_id} or its superadmin mirror
member.password_resetuserPOST /orgs/{org_id}/members/{user_id}/reset-password or its superadmin mirror
member.2fa_resetuserPOST /orgs/{org_id}/members/{user_id}/reset-2fa or its superadmin mirror
user.account_updateuserPATCH /admin/users/{user_id} (account-wide, not org-scoped)
user.password_resetuserPOST /admin/users/{user_id}/reset-password (account-wide)
user.2fa_resetuserPOST /admin/users/{user_id}/2fa-reset (account-wide)
api_key.create / api_key.revokeapi_keyPOST /auth/keys / DELETE /auth/keys/{key_id}
sso.updatesso_connectionPATCH /orgs/{org_id}/sso
finding.status_updatefindingPATCH /findings/{resource_hash}/{rule_id}
team.create / team.update / team.deleteteamPOST/PATCH/DELETE /orgs/{org_id}/teams[/{team_id}]
team.member_add / team.member_removeteam_memberPOST/DELETE /orgs/{org_id}/teams/{team_id}/members[/{user_id}]
rule.create / rule.update / rule.deletecustom_rulePOST/PATCH/DELETE /orgs/{org_id}/rules[/{rule_id}], or their superadmin cross-tenant mirror under /admin/custom-rules
report_template.create / report_template.update / report_template.deletereport_templatePOST/PATCH/DELETE /orgs/{org_id}/report-templates[/{template_id}]
invite.create / invite.revokeorg_invitePOST /orgs/{org_id}/invites / DELETE /orgs/{org_id}/invites/{invite_id}
scim.config.create / scim.config.update / scim.config.deletescim_configPOST/PATCH/DELETE /orgs/{org_id}/scim
scim.token.rotatescim_configPOST /orgs/{org_id}/scim/rotate-token
scim.user.provisioned / scim.user.deactivated / scim.user.reactivateduser/scim/v2/{org_id}/Users[/{id}] create/deactivate/reactivate/delete
scim.group.created / scim.group.renamed / scim.group.deletedteam/scim/v2/{org_id}/Groups[/{id}] create/rename/delete
scim.group.membership_syncedteamPATCH/PUT /scim/v2/{org_id}/Groups/{id} (member add/remove)

Paginated audit events for the caller’s organization, newest first.

ParameterTypeDefaultDescription
actionstringFilter by action, e.g. settings.update
actor_idstringMatches either actor_user_id or actor_key_id
target_typestringFilter by target type, e.g. api_key
since / untilstring (ISO-8601)Inclusive time-range bounds
limitint100Number of results (1–1000)
offsetint0Pagination offset

Response 200

{
"events": [
{
"event_id": "3f4a...",
"org_id": "org-id",
"action": "api_key.create",
"target_type": "api_key",
"target_id": "key-id",
"actor_user_id": "user-id",
"actor_key_id": null,
"actor_email": "[email protected]",
"actor_is_superadmin": false,
"ip": "203.0.113.5",
"before": null,
"after": {"role": "member", "name": "ci-bot", "ip_allowlist": null},
"request_id": "x-request-id-value",
"timestamp": "2026-01-01T12:00:00Z"
}
],
"total_returned": 1
}

Download the same filtered query as CSV or JSON, up to 10,000 rows.

ParameterTypeDefaultDescription
formatstringjsoncsv or json
action, actor_id, target_type, since, untilSame filters as GET /metrics/audit
limitint1000Number of results (1–10000)

Returns a file download (Content-Disposition: attachment) rather than an inline JSON body — before/after are JSON-encoded into their own CSV cells, since the field set varies per action.