Audit Log
A workspace-wide record of who changed what, who read personal data, and when Fruxon staff accessed your workspace
The audit log records who did what in your workspace, when, from where, and how it ended. It covers changes made by your members, their tokens, and your service accounts, reads of personal data, and every time Fruxon staff access your workspace. Open it from Settings → Audit log, in the Security group, or read it through the API under /v1/tenants/{tenant}/auditEvents.
The audit log is an Enterprise feature. On other plans Fruxon records nothing in it except Fruxon staff access, so upgrading doesn't fill in earlier activity. Until then, Settings → Audit log shows a locked preview with sample rows, never your workspace's events.
What gets recorded
Every event has a category. The first column is the chip that filters on it in the dashboard.
| Filter | category | What it records |
|---|---|---|
| Changes | WRITE | A request that creates, changes, or deletes something: agents, revisions and deploys, secrets, tokens, members, integrations, triggers, billing, workspace settings, and so on |
| Reads | READ | A request that returns personal data. See Reads of personal data. |
| Staff access | STAFF_ACCESS | A Fruxon staff member acting on your workspace. See Fruxon staff access. |
| Exports | EXPORT | An export of the audit log |
Refused and failed requests are recorded as well as successful ones, because a run of refusals is often what a reviewer is looking for. The outcome comes from the request's HTTP status:
| Outcome | When |
|---|---|
| Succeeded | The request ended with a 2xx or 3xx status |
| Denied | The caller lacked permission (401 or 403), for example a token without the required scope |
| Failed | Any other error, such as 400, 404, 409, or 500 |
| Attempted | Written just before a fail-closed action runs. The event that concludes it follows and links back to it. |
Sensitive actions are fail-closed. They write an Attempted event before they run. They include member and role changes, invitations, secrets, tokens, service accounts, integration and LLM-provider configurations, encryption keys, deploys, deleting an agent, workflow, application, integration, or knowledge base, plan changes, data-retention and sign-in policies, domain verification, and audit-log exports. If that event can't be written, the request fails with 503 and nothing changes. An Attempted event with no conclusion means the action was interrupted, or its concluding event couldn't be written.
Reads of personal data
Most reads aren't recorded. Settings, agent configurations, counts, and metrics stay out of the log. Reads are recorded only on the endpoints that return personal data: conversations and their messages, topics and inboxes, escalations and handoffs, pending approvals, run records with their traces, inputs, and outputs, participants, chat users and access requests, directory imports, agent memories, knowledge-base documents, imported conversations, test sessions, stored-file downloads, and the audit log itself.
Screens such as the inbox refresh every few seconds, so reads are de-duplicated. Fruxon records a read the first time it sees it and drops identical reads for the next hour. Two reads are identical when they have the same caller (person or service account), token, action, resource and parent resource, and outcome. A list has no single resource, so opening the same list again within the hour counts as a repeat, even with different filters. Each server keeps its own hour, so the same read can occasionally appear more than once an hour. Changes, staff access, and exports are never de-duplicated.
Fruxon staff access
When Fruxon staff act on your workspace through Fruxon's internal admin tools, every request is recorded as Staff access, reads included. This happens on every plan, not only Enterprise. Action names come from the internal endpoint, such as staff.admin_tenant.get_org or staff.admin_license.set_license.
A staff event names its actor as Fruxon staff and leaves out the user ID, token, IP address, and user agent. You learn that Fruxon accessed your workspace, not which employee did. The stored event keeps those details for Fruxon's own investigations. A refused attempt at one of those admin endpoints is recorded as Denied, under the identity of whoever tried.
Below Enterprise, the dashboard shows only the locked preview. An Owner or Admin can still read the workspace's staff-access events through GET …/auditEvents, which returns only those events on other plans.
What isn't recorded
- Running agents and workflows, including test runs from Studio. Each run is recorded on its own execution record instead (see Observability). Reading those records is recorded.
- Draft autosaves. The change is recorded when the draft is published (
agent.draft.publish) and when it's deployed. - Calls that change nothing, such as previews, validations, connection tests, and dry runs.
- Inbound deliveries from webhooks and messaging channels, and callbacks that resume a waiting run. The runs they start record them.
- Actions outside a workspace: signing in, creating a workspace, accepting or declining an invitation, and editing your own profile.
- Unauthenticated requests, and requests from people who aren't members of the workspace. These are refused before they reach it.
What an event contains
| Field | What it holds |
|---|---|
id, createdAt | The event's ID, and when it happened in Unix milliseconds |
principal.type | USER, SERVICE_ACCOUNT, or FRUXON_STAFF. A call made with a personal token is the USER who owns it, because the token is how they called, not who called. |
principal.userId, displayName, email | The person, with their current name and email. Shows Deleted user once their Fruxon account is deleted. |
principal.tokenId, tokenName | The token the call authenticated with, if any. Shows Deleted token once the token is deleted. |
principal.serviceAccountId, serviceAccountName | The service account, on SERVICE_ACCOUNT events |
principal.actor | The tool the caller says it is, from the X-Fruxon-Actor header. It's self-declared, so treat it as a hint. |
action | A dotted name for what was done, such as agent.revision.deploy or conversation.read |
category, outcome, statusCode | See What gets recorded |
resourceType, resourceId, parentResourceId | What the request acted on, for example a revision and the agent it belongs to |
changedFields | For a JSON PUT or PATCH of up to 64 KB, the names of the top-level fields it sent. Names only, never values. |
clientIp, userAgent | Where the request came from. The user agent is cut at 256 characters. |
traceId | Ties the event to Fruxon's logs and trace for that request |
attemptEventId | On the event that concludes a fail-closed action, the ID of its Attempted event |
An event stores IDs, not names or email addresses, so that nothing in it has to be edited when a person's data is erased. Names are looked up each time you read the log.
Who can read it
Reading and exporting the log needs the audit:read scope, and only the Owner and Admin roles hold it. Every member sees the Audit log tab, but anyone else sees Only workspace owners and admins can read the audit log.
Among token presets, only Admin includes audit:read. Observer through Maintainer leave it out because the log is a record about people, including their IP addresses and what each one looked at. You can add the scope on its own to a narrower token, such as one that feeds your SIEM. Nobody can grant a scope they don't hold, so only an Owner or Admin can mint one.
Browse and filter
The table lists events newest first, with Time, Who, Action, Resource, Outcome, and IP columns, and loads older events as you scroll. To narrow it:
- Search actions… takes an exact action name, or a prefix ending in
.*such assecret.*. It isn't a substring search. - The time range is Last 90 days by default.
- The category chips (Changes, Reads, Staff access, Exports) and outcome chips (Succeeded, Denied, Failed, Attempted) match any of the chips selected in their group.
- Click a name under Who for that actor's events, or the token chip beside it for that token's calls only. Click a Resource for everything that happened to it. Each appears as a removable chip next to Showing only.
Click a row to see every field of the event, with a button that copies it as JSON.
Query the API
All paths are under /v1/tenants/{tenant}.
| Endpoint | What it does |
|---|---|
GET …/auditEvents | Lists events, newest first |
GET …/auditEvents/{auditEvent} | Gets one event. Returns 404 for an event your plan doesn't show. |
POST …/auditEvents:export | Exports events as CSV or NDJSON |
The list takes these query parameters. Each one narrows the result.
| Parameter | Meaning |
|---|---|
from, to | The window in Unix milliseconds, both inclusive. to defaults to now and from to 90 days before to, so every query is bounded. |
action | An exact action, or a prefix ending in .* |
category, outcome | Repeat to match any of several, for example category=READ&category=EXPORT |
principalType | USER, SERVICE_ACCOUNT, or FRUXON_STAFF |
userId, tokenId, serviceAccountId | One person, token, or service account |
resourceType, resourceId | One kind of resource, or one resource |
pageSize, pageToken | Up to 100 events a page, 50 by default. Pass the response's nextPageToken as pageToken to get the next page. |
Export
Export in the dashboard and POST …/auditEvents:export both download the matching events right away, as audit-log.csv or audit-log.ndjson. Nothing runs in the background and nothing is emailed. The request body is {"filter": {...}, "format": "NDJSON"}. filter takes the list's query parameters except pageSize and pageToken, and format is CSV (the default) or NDJSON.
- Up to 50,000 events, newest first. When more match, the response carries
X-Fruxon-Export-Truncated: trueand the dashboard says the export stopped at 50,000 rows. Narrow the time range and export the rest separately. - CSV has one row per event, with ISO 8601 UTC timestamps, the actor's name and email resolved, and
changed_fieldsseparated by semicolons. A cell that starts with=,+,-, or@gets a leading apostrophe, so a spreadsheet won't run it as a formula. - NDJSON has one JSON object per line, in the shape the API returns, with empty fields left out.
Every export is itself recorded as audit_log.export, and it's fail-closed: if that event can't be written, the export is refused. Viewing the log is recorded too, as audit_log.list and audit_log.read.
Retention
- Kept for 730 days (two years) on Enterprise. You can't change this from the workspace. If you need a different period, talk to your account team: Fruxon sets it on your workspace's license.
- Separate from data retention. Your workspace's data-retention window doesn't shorten the audit log. A daily job deletes events past their retention, and records each purge, with its cutoff and the number of events removed, in your workspace's data-retention history.
- Append-only. No dashboard action or API endpoint edits or deletes an event. Only retention expiry removes one.
- Events outlive what they describe. Deleting an agent or removing a member leaves its events in place. A deleted workspace's events are kept for 730 days, then expired.
Staff-access events on other plans are kept for the same 730 days.
How it relates to other audit trails
The audit log is the one workspace-wide index. Several features also keep their own detailed history, and these don't need Enterprise:
| Trail | What it adds |
|---|---|
| Credential audit (Settings → Credential audit) | Every decrypt, sign, or encrypt of a stored credential, including when an agent's tool call uses it at run time. That never goes through the API, so it never appears in the audit log. How strictly it's recorded depends on the credential's sensitivity tier. |
| Approval auditing | Every human-approval request, decision, cancellation, and expiry, including replies from messaging channels, with the exact arguments put up for approval |
| Token and service-account history | Lifecycle detail and request activity for one token or service account |
The API requests behind those trails also appear in the audit log, for example rotating a secret, revoking a token, or answering an approval from the dashboard (agent.pending_approval.respond). The two records aren't linked to each other yet, so match them by time, actor, and resource.
Related
- Security: credential protection and how to build secure agents
- Team & Roles: who holds Owner and Admin
- Tokens: scopes, presets, and minting a token with
audit:read - Service Accounts: workload identities that appear as
SERVICE_ACCOUNT - Observability: run records and traces, where agent runs are recorded
Sign-in & SSO
Verify your domains, connect a SAML identity provider, restrict how members sign in, and confirm it's you before sensitive changes
Hosting & Data Residency
Where Fruxon runs, where your workspace's data lives, how far its prompts may travel, and the deployment models available for regulated and enterprise teams