Audit

Per-action audit report

Aggregates audit logs for a window into per-action counts, average latency, and top policies, tenant-scoped and optionally filtered by user and a single canonical action. Counts reconcile with /api/v1/audit/search for the same filters.

post/api/v1/audit/report

Request

Headers

X-Tenant-IDstring required

Tenant identifier scoping the request. The AxonFlow Agent gateway sets this header after authentication; the orchestrator fails closed when it is absent (401 on audit/decision endpoints, 400 on others — see each operation). Clients cannot widen their scope through it: handlers force the tenant filter from this header, never from the request body.

Request body

start_timestring date-time required

Window start (RFC3339)

end_timestring date-time required

Window end (RFC3339, must be after start_time; range at most 1 year)

user_emailstring

Optional case-insensitive partial match

actionstring

Optional single canonical action filter

Response

Per-action report. A fail-closed read (X-Axonflow-Read-Scope: none) returns the seeded all-zeroes report, which has the same shape as "no rows in the window".

tenant_idstring
user_emailstring

Echoed filter; omitted when not filtered

start_timestring date-time
end_timestring date-time
totalinteger

Governed decisions in the window (lifecycle events excluded)

by_actionobject

Counts folded onto the canonical verdicts

avg_latency_msnumber double nullable

Mean ENFORCEMENT latency in milliseconds over the rows in the range that carried a measurement, or null when none did (#3424).

null is not 0. Whole planes record no enforcement duration by design (HITL approvals, workflow lifecycle rows, the connector-exec MCP closure), and provider round trips on the LLM plane are a different quantity and are excluded rather than averaged in, so a range whose traffic was entirely one of those has nothing to report. It used to be coalesced to 0, which reads exactly like a measured zero. Clients MUST accept null here; a strict deserializer binding this to a non-optional float will raise. It can also be BELOW 1: response_time_ms is whole milliseconds, so a decision completing in under a millisecond contributes a 0.

Read latency_sample_count to tell "fast" from "empty".

latency_sample_countinteger

How many rows backed avg_latency_ms. 0 exactly when avg_latency_ms is null. Never greater than total: both are narrowed to the same verdict rows.

total_policiesinteger

How many DISTINCT policies fired in the range BEFORE the 10-entry top_policies limit truncated it. 0 when nothing fired. On this REGULATOR-FACING report an undisclosed truncation is the sharper of the two surfaces' risks: when this exceeds the array length, disclose "top 10 of N" rather than implying the remainder does not exist.

Changes

No recorded changes to this operation across all 1 revision of this API.