What a row contains
Actions
Owners and admins read every row in the viewer and the export. The third column says who the row is usually for.
A data-plane
tool.execute carries metadata.dataplane: true, duration_ms, spend_cents, payloads_stored and, for a result that arrived after the dispatch had expired, late_result: true with denial_reason: late_result. A workflow execution carries metadata.surface: workflow, workflow_id, execution_id and step.
Which surfaces are audited
- API calls, single and batch, with the caller’s key, ip and request id and a hash of the parameters. The organization is the acting organization of the request (the
danube-org-idheader or the key’s organization). - MCP calls, which reach the same API through the MCP server. The row shows the key, and a
danube-org-idheader passed by the MCP client attributes the call to that organization. - Hosted workflows, whose executions do not pass through the API. Their rows are filed under the tool’s own organization when it has one, and otherwise under the caller’s personal organization.
- Data-plane results, reported by the agent inside your network, plus the events the agent streams itself with a sequence number.
- Governance changes made in the dashboard or through the API: membership, teams, grants, settings, keys, credentials, catalog writes.
Read the log
1
Open the viewer
Go to Dashboard > Organization > Audit Log. Admins and owners only.
2
Filter
Filter by action, status, actor, tool, and a time range. The actor filter offers the organization’s members by name, or a profile id typed by hand for an actor who is no longer a member. The list is newest first and paginated.
The response is
{"events": [...], "total": N, "page": 1, "page_size": 50}.
Export
GET /v1/organizations/{org_id}/audit/export downloads the log as a file, newest first, with the same filters as the viewer. The dashboard’s Export CSV button downloads the currently filtered view.
formatiscsv(default,text/csv) orndjson(application/x-ndjson, one JSON object per line). The file name isaudit-<org slug>-<date>.<format>.- The columns are fixed, in this order, and a new column is only ever added at the end:
created_at, action, status, actor_type, actor_profile_id, api_key_id, ip, request_id, resource_type, resource_id, service_id, tool_id, tool_name, args_hash, denial_reason, metadata. In CSV the metadata column is JSON; in NDJSON each line carries the same keys in the same order. enddefaults to the moment the export starts, so rows written during a long export never shift its pages.- Row cap. An export stops at 200,000 rows and ends with a marker line whose
actionisaudit.export_truncated(statusinfo,metadatawithtruncated: true,max_rowsand a message). Narrow the date range and export again for the rest. If a read fails part-way the file ends with anaudit.export_failedmarker (statuserror) and the export should be retried. A marker has the shape of a row, so a parser reading by column still reads it; the action names what it is. - Every export is itself recorded as
audit.exportwith the format, the filters, the number of rows and whether it was truncated or failed.
Retention
By default audit events are kept forever. An owner or admin setsaudit_retention_days under Organization > Settings > Retention or with PATCH /v1/organizations/{org_id}/settings (30 to 3650; null returns to keeping everything). A nightly job at 03:41 UTC deletes the organization’s events older than the retention, in batches of 5,000 rows and at most 100,000 rows a night across all organizations, so a backlog the day a short retention is first set drains over a few nights.
The floor is 30 days: the setting refuses a smaller value and the purge clamps to 30 as well, so a value written to the database by hand cannot shorten it either. The corresponding switch for execution history is execution_retention_days, described under Data Plane.
Guarantees
- Append-only. The table refuses updates unconditionally at the database level and refuses deletes from every path except the scheduled retention purge, which opens a transaction-local door that no API connection can use.
- Never blocks the call. A failed audit write is logged as a warning and the audited operation still completes. A silent gap is not possible: the failure is visible in server logs.
- No raw parameters. Only the
args_hashdigest is stored, andmetadatacarries names of things, never tool inputs or results. - Data-plane events are idempotent. Agents inside your network stream events with a per-agent sequence number, buffer them while offline, and retry. Intermittent connectivity neither loses nor duplicates rows.
