> ## Documentation Index
> Fetch the complete documentation index at: https://docs.braintrust.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Audit logging

> Track and review administrative actions in your Braintrust organization, such as permission changes, member management, and API key creation

The [** Audit log**](https://www.braintrust.dev/app/~/configuration/audit-log) records administrative actions in your Braintrust organization, such as creating projects, changing settings, granting permissions, managing members, and creating API keys. Reads of your data can also be logged as an optional add-on.

> [!NOTE]
>
> Audit logging is only available on the [Enterprise plan](https://docs.braintrust.dev/plans-and-limits.md#plans).

Audit logs are only recorded while your organization is on an Enterprise plan. If you upgrade from Pro to Enterprise, audit logs are recorded from the time of the upgrade.

> [!NOTE]
>
> Self-hosted deployments require [data plane v2.6.0](https://docs.braintrust.dev/data-plane-changelog.md) or later for audit logging. On earlier versions, administrative events are recorded but aren't queryable.

## Grant access

Members of the [**Owners**](https://docs.braintrust.dev/admin/access-control.md#built-in-permission-groups) permission group can read organization audit logs by default. To let anyone else read them, grant the organization-level **Read audit logs** permission in ** Settings** > [** Permissions**](https://www.braintrust.dev/app/~/configuration/permissions/organization).

> [!NOTE]
>
> The **Read audit logs** permission grants read access to audit log entries for the organization. It does not grant access to modify the audited resources.

## View the audit log

To view recent organization activity, go to ** Settings** > [** Audit log**](https://www.braintrust.dev/app/~/configuration/audit-log). The table lists actions performed by members of your organization, with the most recent events first.

Use the controls above the table to customize the view:

* **Time range**: Select **Last 24 hours**, **Last 7 days**, or **Last 30 days**. The default is **Last 7 days**.
* **Filters**: Narrow results by fields such as actor, event type, or resource.
* **Columns**: Show or hide columns. ID, details, and before and after change columns are hidden by default.

To run more complex queries or download results, select  **Open in Query**. See [Audit data reads and modifications](#audit-data-reads-and-modifications) and the [SQL reference](https://docs.braintrust.dev/reference/sql.md) for query details.

## Query the audit log

Users with the **Read audit logs** permission can query audit logs with [SQL](https://docs.braintrust.dev/reference/sql.md) using the `audit_logs()` data source, identified by your organization's ID (for example, `audit_logs('my-org-id')`). No additional configuration is required to query them.

Run a query from the [** Query**](https://www.braintrust.dev/app/~/sql) page, the [`bt sql`](https://docs.braintrust.dev/reference/cli/sql) CLI, or the [API](https://docs.braintrust.dev/reference/sql.md#api).

**Examples:**

```sql Recent activity across the organization theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
SELECT created, actor_id, event_type, resource_type, resource_name
FROM audit_logs('<org_id>') -- Replace with your organization ID
WHERE created > NOW() - INTERVAL 1 DAY
ORDER BY created DESC
LIMIT 100
```

```sql All actions taken by a specific member theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
SELECT created, event_type, resource_type, resource_name
FROM audit_logs('<org_id>') -- Replace with your organization ID
WHERE actor_id = '<user_id>' -- Replace with the member's user ID
ORDER BY created DESC
```

```sql Permission and access control changes in the last 30 days theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
SELECT created, actor_id, event_type, resource_name, after_changes
FROM audit_logs('<org_id>') -- Replace with your organization ID
WHERE created > NOW() - INTERVAL 30 DAY
  AND (event_type LIKE 'acl.%' OR event_type LIKE 'group%' OR event_type LIKE 'role%')
ORDER BY created DESC
```

To log reads of your data in the audit trail, see [Audit data reads and modifications](#audit-data-reads-and-modifications).

## What gets logged

Each audit log entry records a single event: what happened, who performed it, and what changed.

### Fields

Each organization audit log entry includes:

| Field | Description |
| - | - |
| `created` | Event timestamp. |
| `org_id` | Organization where the event occurred. |
| `project_id` | Project associated with the event, when applicable. |
| `actor_id` | User or service account that performed the action. |
| `event_type` | Event name in `<resource>.<action>` form, such as `project.updated`. |
| `event_details` | Additional event-specific metadata. |
| `resource_type` | Type of resource that changed. |
| `resource_id` | ID of the resource that changed. |
| `resource_name` | Human-readable resource name. |
| `actor_details` | Request metadata, including IP address, user agent, request ID, and authentication token details. |
| `before_changes` | Relevant resource fields before the event. Populated for update and delete events. |
| `after_changes` | Relevant resource fields after the event. Populated for create and update events. |

For create events, `before_changes` is `null`. For delete events, `after_changes` is `null`. For update events, both fields contain the changed resource values. Readonly events contain neither.

### Events

Braintrust records organization audit log events for these resource categories:

| Resource category | Resource types | Event types |
| - | - | - |
| Organizations | `organization` | `organization.created`, `organization.updated`, `organization.native_typesafe_jev_access.updated` (recorded alongside `organization.updated` when [built-in Jev](https://docs.braintrust.dev/admin/ai-providers.md#enable-or-disable-built-in-models) is enabled or disabled) |
| Projects | `project` | `project.created`, `project.updated`, `project.deleted` |
| Project groups | `project_group` | `project_group.created`, `project_group.updated`, `project_group.deleted` |
| Project group membership | `project_group_project` | `project_group_project.created`, `project_group_project.deleted` |
| Experiments | `experiment` | `experiment.created`, `experiment.updated`, `experiment.deleted` |
| Datasets | `dataset` | `dataset.created`, `dataset.updated`, `dataset.deleted` |
| Project automations | `project_automation` | `project_automation.created`, `project_automation.updated`, `project_automation.deleted` (configuration changes only, not automation runs). [Async query](#async-queries-and-applied-scorers) changes are recorded only with row-level audit logging. |
| Project scores | `project_score` | `project_score.created`, `project_score.updated`, `project_score.deleted` (configuration changes only, not scoring runs or human review score reordering). [Scorers applied to experiments](#async-queries-and-applied-scorers) are recorded only with row-level audit logging. |
| Organization automations | `org_automation` | `org_automation.created`, `org_automation.updated`, `org_automation.deleted` (configuration changes only, not automation runs) |
| Token budgets | `token_budget_config` | `token_budget_config.created`, `token_budget_config.updated`, `token_budget_config.deleted` (`scope_type`, `user_id`, `api_key_id`, and `config` fields) |
| Organization AI providers and secrets | `ai_secret` | `ai_secret.created`, `ai_secret.updated`, `ai_secret.deleted` |
| API keys | `api_key` | `api_key.created`, `api_key.deleted` |
| Data plane manager service tokens | `service_token` | `data_plane_service_token.created`, `data_plane_service_token.replaced` |
| Permission groups | `group` | `group.created`, `group.updated`, `group.deleted` |
| Permission group membership | `group_member` | `group_member.created`, `group_member.deleted` |
| Roles | `role` | `role.created`, `role.updated`, `role.deleted` |
| Role membership | `role_member` | `role_member.created`, `role_member.deleted` |
| Role permissions | `role_permission` | `role_permission.created`, `role_permission.deleted` |
| Organization members | `org_member` | `org_member.created`, `org_member.deleted` |
| Access grants | `acl` | `acl.created`, `acl.deleted` |

Some operations emit multiple audit log entries. For example, inviting a user can create an organization member entry, permission group membership entries, access grants, and an API key entry. Bulk operations create one audit log entry per changed resource.

> [!NOTE]
>
> Audit logs can take a few minutes to show up after an action occurs.

### Sensitive values

Braintrust excludes or redacts sensitive values in audit logs:

* API key hashes and raw keys are not included. Audit entries include the API key preview name when available.
* AI provider secrets are redacted. Audit entries include a secret preview and omit encrypted secret material and key names.
* Webhook action URLs (`config.action.url`) in project automation configurations are redacted. When a webhook URL changes, `event_details.redacted_fields_changed` lists `config.action.url`.
* String values in `query.read` queries are masked. See [Recorded queries](#recorded-queries).
* Resource IDs, organization IDs, project IDs, creation timestamps, update timestamps, and deletion timestamps are omitted from `before_changes` and `after_changes` when they would add noise to the change diff.

## Audit data reads and modifications

Administrative actions are logged automatically with no setup. Row-level auditing of data reads and modifications is different: these events can be high volume, so Braintrust records them only when you opt in.

`query.read` events are particularly high volume. When enabled, `query.read` covers both SQL queries run manually and ones run implicitly by the Braintrust UI when you browse logs, experiments, and traces.

Braintrust records the following events for data rows:

| Resource category | Resource types | Event types |
| - | - | - |
| SQL queries | `query` | `query.read` |
| Logs and spans | `project_log` | `project_log.deleted` |
| Experiment rows | `experiment_log` | `experiment_log.deleted` |
| Dataset rows | `dataset_log` | `dataset_log.deleted` |

How you enable row-level audit logging depends on your deployment.

> [!NOTE]
>
> Enabling `query.read` audit logging counts toward your processed data usage. Because these events can be high volume, this may result in additional charges.

For Braintrust-hosted and BYOC deployments, contact [Braintrust support](mailto:support@braintrust.dev).

For self-hosted deployments, enable `query.read` auditing per organization through Terraform or Helm. See [Enable read auditing](https://docs.braintrust.dev/admin/self-hosting/configure/security.md#enable-read-auditing) for the strict and best-effort modes and the variables to set.

### Recorded queries

Requires data plane v2.20.0+ (Self-hosted customers must upgrade to use this feature.)

Each `query.read` event records the parsed query in `event_details.query`, with string values masked:

* Letters and digits in string values are replaced by `*`, so `'secret123'` becomes `'*********'`. This includes strings inside arrays and objects, and object keys. Numbers aren't masked.
* Object IDs passed to table functions such as `project_logs('<project-id>')` stay visible.
* Queries that can't be parsed are recorded as `<Failed to parse query>`.

`event_details.query_hash` is a SHA-256 hash of the original query, so you can match repeated runs of the same query.

On self-hosted deployments running data plane versions earlier than v2.20.0, SQL queries are recorded as `<Failed to parse query>`, and string values in some clauses, such as `span_filter` and `custom_columns`, aren't masked.

### Async queries and applied scorers

Requires data plane v2.18.0+ (Self-hosted customers must upgrade to use this feature.)

Row-level audit logging also records changes to [async queries](https://docs.braintrust.dev/api-reference/query.md#async-queries) and to scorers applied to an experiment with [**Apply scorers**](https://docs.braintrust.dev/evaluate/interpret-results.md#apply-scorers-to-all-traces). These events use the `project_automation` and `project_score` event types:

* Submitting an async query records `project_automation.created`, with a SHA-256 hash of the query in `event_details.query_hash`. Canceling an async query records `project_automation.updated`, with `config.status` changing to `paused`.
* Fetching async query results records `query.read` with `query_source` set to `async_query`. Its `query_hash` matches the one in `project_automation.created`, so you can link result downloads to the query that produced them.
* Applying scorers to an experiment records `project_score.created`, with the scorers and scope in `after_changes.config.online`. Pausing or resuming them records `project_score.updated`, with the previous and new status in `config.online.status`.

A failed audit write for these changes is logged and doesn't fail the request.

## Retention

Audit logs are retained indefinitely for the lifetime of your organization's Enterprise subscription, giving you a permanent record of administrative activity for compliance and regulatory requirements. Unlike logs, experiments, and datasets, they aren't subject to your [plan's retention window](https://docs.braintrust.dev/admin/data-management/retention.md) or to retention automations.

If your organization leaves the Enterprise plan, Braintrust stops recording new audit log events.

## Next steps

* [Access control](https://docs.braintrust.dev/admin/access-control.md) to learn how organization permissions work.
* [Manage permissions](https://docs.braintrust.dev/admin/access-control/manage-permissions.md) to grant **Read audit logs** to a permission group.
* [SQL reference](https://docs.braintrust.dev/reference/sql.md) to learn about how to query audit logs with SQL.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.