Audit Logs
Breeze RMM provides three distinct logging systems that together give you full visibility into platform activity, agent health, and device-level events. Each system serves a different purpose and is stored in its own database table with dedicated API endpoints.
Log Types Overview
Section titled “Log Types Overview”| Log Type | Purpose | Source | Database Table |
|---|---|---|---|
| Platform Audit Logs | Track user, API key, agent, and system actions across the platform | API server | audit_logs |
| Agent Diagnostic Logs | Capture internal agent runtime diagnostics (debug, info, warn, error) | Breeze agent | agent_logs |
| Device Event Logs | Collect OS-level event logs from managed devices (security, hardware, application, system) | Managed devices | device_event_logs |
Platform Audit Logs
Section titled “Platform Audit Logs”Platform audit logs record every significant action taken within your Breeze environment. They are the primary compliance and security trail.
Audit Log Fields
Section titled “Audit Log Fields”Each audit log entry contains the following fields:
| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier for the log entry |
orgId | UUID | Organization the action belongs to (multi-tenant scoping) |
timestamp | Timestamp | When the action occurred (defaults to current time) |
actorType | Enum | Who performed the action: user, api_key, agent, or system |
actorId | UUID | Identifier of the actor (user ID, agent ID, etc.) |
actorEmail | String (255) | Email address of the actor (when available) |
action | String (100) | The action performed (e.g., user.login, device.create, script.execute) |
resourceType | String (50) | Type of resource acted upon (e.g., device, policy, organization) |
resourceId | UUID | Identifier of the affected resource |
resourceName | String (255) | Human-readable name of the affected resource |
details | JSONB | Additional context about the action (before/after values, parameters, etc.) |
ipAddress | String (45) | Client IP address (supports IPv4 and IPv6) |
userAgent | Text | Client user-agent string |
result | Enum | Outcome of the action: success, failure, or denied |
errorMessage | Text | Error details when the result is failure or denied |
checksum | String (128) | Integrity checksum for tamper detection |
Actor Types
Section titled “Actor Types”Breeze tracks four types of actors:
| Actor Type | Description | Example Actions |
|---|---|---|
user | A human user authenticated via JWT | Logging in, updating a device, exporting data |
api_key | An API key (prefix brz_) used for programmatic access | Automated script execution, integrations |
agent | A Breeze agent running on a managed device | Submitting event logs, heartbeat updates |
system | Internal platform operations with no human actor | Scheduled cleanups, automated policy evaluations |
When a non-UUID actor ID is provided (e.g., an agent string identifier), the system stores a zero UUID as the actorId and preserves the original value in the details JSONB field under the key rawActorId. The same treatment applies to non-UUID resourceId values, stored as rawResourceId in details.
Action Categories
Section titled “Action Categories”Actions are classified into categories based on their prefix. This categorization drives the reporting endpoints:
| Category | Action Prefixes | Examples |
|---|---|---|
authentication | user.login, user.logout, user.permission | user.login, user.login.failed, user.permission.change |
device | device. | device.create, device.update, device.delete |
automation | script. | script.execute |
policy | policy., automation.policy. | policy.create, policy.update, policy.evaluate, automation.policy.evaluate |
alert | alert. | alert.create, alert.acknowledge |
compliance | data. | data.access, data.export |
organization | organization. | organization.update |
system | Everything else | System-generated events |
Security Actions
Section titled “Security Actions”The following actions are flagged as security events and appear in the security events report:
user.loginuser.login.faileduser.permission.changepolicy.updatepolicy.createpolicy.evaluateautomation.policy.evaluate
Compliance Actions
Section titled “Compliance Actions”The following actions are tracked for compliance reporting:
data.accessdata.exportdevice.create,device.deletepolicy.update,policy.evaluate,automation.policy.evaluatescript.executeorganization.update
Writing Audit Events
Section titled “Writing Audit Events”Audit events are written asynchronously via createAuditLogAsync, which inserts into the database without blocking the request. If the insert fails, the error is logged to the console (suppressed in test environments).
Two helper functions are available in application code:
writeAuditEvent(c, event)— Low-level function that accepts a request-like context and anAuditEventInputobject. Extracts the client IP fromX-Forwarded-Forand the user-agent from request headers. Events with noorgIdare silently dropped (with a console warning in non-test environments).writeRouteAudit(c, event)— Convenience wrapper for route handlers that automatically extractsactorIdandactorEmailfrom the Hono auth context.
Filtering and Searching
Section titled “Filtering and Searching”The audit log list endpoints support the following query parameters for filtering:
| Parameter | Type | Description |
|---|---|---|
page | String (number) | Page number (default: 1) |
limit | String (number) | Results per page (default: 50, max: 100) |
user | String | Filter by actor email or user name (ILIKE match) |
action | String | Filter by action name (ILIKE match) |
resource | String | Filter by resource type or resource name (ILIKE match) |
from | ISO 8601 datetime | Start of date range |
to | ISO 8601 datetime | End of date range |
The search endpoint (GET /search) adds a q parameter that performs a full-text ILIKE search across action, actor email, resource type, resource name, and the JSON-cast details field. Search conditions are combined with any active filters using AND logic.
Retention Policies
Section titled “Retention Policies”Audit log retention is configured per organization in the audit_retention_policies table:
| Field | Type | Default | Description |
|---|---|---|---|
retentionDays | Integer | 365 | Number of days to retain audit logs |
archiveToS3 | Boolean | false | Whether to archive logs to S3 before deletion |
lastCleanupAt | Timestamp | null | When the last cleanup ran |
Agent Diagnostic Logs
Section titled “Agent Diagnostic Logs”Agent diagnostic logs capture internal runtime information from the Breeze agent running on managed devices. These are useful for troubleshooting agent connectivity, update failures, and component-level issues.
Agent Log Fields
Section titled “Agent Log Fields”| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
deviceId | UUID | The device this agent runs on |
orgId | UUID | Organization scope |
timestamp | Timestamp | When the log entry was generated on the agent |
level | Enum | Severity: debug, info, warn, or error |
component | String (100) | Agent subsystem that generated the log (e.g., updater, heartbeat, ws) |
message | Text | The log message |
fields | JSONB | Structured key-value metadata attached to the log entry |
agentVersion | String (50) | Version of the agent that generated the entry |
createdAt | Timestamp | When the record was inserted into the database |
Database Indexes
Section titled “Database Indexes”The agent_logs table has the following indexes for efficient querying:
agent_logs_device_idx— By device IDagent_logs_org_ts_idx— By organization ID and timestamp (composite)agent_logs_level_component_idx— By level and component (composite)agent_logs_timestamp_idx— By timestamp
Log Ingestion
Section titled “Log Ingestion”Agents submit diagnostic logs via POST /agents/:id/logs with a JSON body containing a logs array (maximum 500 entries per request). Each entry must include:
timestamp(ISO 8601 datetime)level(debug,info,warn,error)component(string, max 100 characters)message(string)fields(optional object with arbitrary key-value pairs)agentVersion(optional string, max 50 characters)
Logs are batch-inserted in groups of 100 rows. The endpoint returns the number of successfully inserted records.
Querying Diagnostic Logs
Section titled “Querying Diagnostic Logs”Diagnostic logs are queried via GET /devices/:id/diagnostic-logs with the following optional parameters:
| Parameter | Type | Description |
|---|---|---|
level | String | Filter by level(s), comma-separated (e.g., warn,error) |
component | String | Filter by component name (exact match) |
since | ISO 8601 datetime | Start of time range |
until | ISO 8601 datetime | End of time range |
search | String | ILIKE search on the message field |
page | String (number) | Page number |
limit | String (number) | Results per page (default max: 1000) |
Results are ordered by timestamp descending and include the total count for pagination.
Device Event Logs
Section titled “Device Event Logs”Device event logs represent OS-level events collected from managed devices. There are two mechanisms for working with device event logs: stored event logs (persisted in the database) and live event log queries (real-time queries sent to the agent).
Stored Event Logs
Section titled “Stored Event Logs”Agents periodically submit event logs that are stored in the device_event_logs table for historical querying.
Stored Event Log Fields
Section titled “Stored Event Log Fields”| Field | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
deviceId | UUID | The device the event came from |
orgId | UUID | Organization scope |
timestamp | Timestamp | When the event occurred on the device |
level | Enum | Severity: info, warning, error, or critical |
category | Enum | Event category: security, hardware, application, or system |
source | String (255) | The source application or component |
eventId | String (100) | OS-specific event identifier |
message | Text | The event message |
details | JSONB | Additional structured event data |
createdAt | Timestamp | When the record was inserted |
Deduplication
Section titled “Deduplication”The device_event_logs table has a unique index on (deviceId, source, eventId) to prevent duplicate events. When an agent submits events that conflict with existing records, the duplicates are silently ignored (ON CONFLICT DO NOTHING).
Database Indexes
Section titled “Database Indexes”device_event_logs_device_idx— By device IDdevice_event_logs_org_ts_idx— By organization ID and timestamp (composite)device_event_logs_cat_level_idx— By category and level (composite)device_event_logs_dedup_idx— Unique index on (device ID, source, event ID)
Event Submission
Section titled “Event Submission”Agents submit event logs via PUT /agents/:id/eventlogs with a JSON body containing an events array. Each event must include:
timestamp(string, required)level(info,warning,error,critical)category(security,hardware,application,system)source(string, required)eventId(string, optional)message(string, required)details(optional object)
Events are batch-inserted in groups of 100. The submission is also recorded as an audit event with action agent.eventlogs.submit.
Querying Stored Event Logs
Section titled “Querying Stored Event Logs”Query stored event logs for a device via GET /devices/:id/eventlogs:
| Parameter | Type | Description |
|---|---|---|
category | Enum | Filter by category: security, hardware, application, system |
level | Enum | Filter by level: info, warning, error, critical |
source | String | Filter by source (exact match) |
startDate | ISO 8601 datetime | Start of time range |
endDate | ISO 8601 datetime | End of time range |
page | String (number) | Page number |
limit | String (number) | Results per page (default max: 500) |
Live Event Log Queries
Section titled “Live Event Log Queries”For real-time inspection, Breeze can query the Windows Event Log (or equivalent) directly on a device by sending commands through the agent. These are available under both the /system-tools/ and /devices/ route namespaces.
List Available Event Logs
Section titled “List Available Event Logs”GET /system-tools/devices/:deviceId/eventlogsReturns the list of event logs available on the device (e.g., Application, Security, System). Each log includes:
| Field | Type | Description |
|---|---|---|
name | String | Internal log name |
displayName | String | Human-readable display name |
recordCount | Number | Number of records in the log |
maxSize | Number | Maximum log size in bytes |
retentionDays | Number | Configured retention period |
lastWriteTime | String | Timestamp of the most recent entry |
Get Event Log Info
Section titled “Get Event Log Info”GET /system-tools/devices/:deviceId/eventlogs/:nameReturns metadata for a specific event log by name (case-insensitive match).
Query Event Log Entries
Section titled “Query Event Log Entries”GET /system-tools/devices/:deviceId/eventlogs/:name/events| Parameter | Type | Description |
|---|---|---|
page | String (number) | Page number |
limit | String (number) | Results per page |
level | Enum | Filter by level: information, warning, error, critical, verbose |
source | String | Filter by source |
startTime | ISO 8601 datetime | Start of time range |
endTime | ISO 8601 datetime | End of time range |
eventId | String (number) | Filter by OS event ID |
Each returned event entry contains:
| Field | Type | Description |
|---|---|---|
recordId | Number | Record identifier within the log |
timeCreated | String | When the event was generated |
level | Enum | information, warning, error, critical, or verbose |
source | String | Source application or component |
eventId | Number | OS-specific event ID |
message | String | Event message text |
category | String | Event category |
user | String or null | User associated with the event |
computer | String | Computer name |
rawXml | String | Raw XML representation (when available) |
Get Single Event Record
Section titled “Get Single Event Record”GET /system-tools/devices/:deviceId/eventlogs/:name/events/:recordIdReturns a single event log entry by its record ID.
API Reference
Section titled “API Reference”Platform Audit Log Endpoints
Section titled “Platform Audit Log Endpoints”All audit log endpoints are mounted at /api/v1/audit-logs and require JWT authentication.
List Audit Logs (Flat Format)
Section titled “List Audit Logs (Flat Format)”GET /audit-logsReturns entries in a flattened format used by the AuditLogViewer UI component. Supports page, limit, user, action, resource, from, and to query parameters.
Response shape:
{ "entries": [ { "id": "uuid", "timestamp": "2026-02-18T12:00:00.000Z", "action": "device.create", "resource": "My Workstation", "resourceType": "device", "details": "{}", "ipAddress": "192.168.1.10", "userAgent": "Mozilla/5.0...", "sessionId": null, "user": { "name": "Jane Admin", "role": "user", "department": "" }, "changes": { "before": {}, "after": {} } } ], "pagination": { "page": 1, "limit": 50, "total": 142, "totalPages": 3 }}List Audit Logs (Full Format)
Section titled “List Audit Logs (Full Format)”GET /audit-logs/logsReturns entries in a detailed format used by RecentActivity and UserActivityReport components. Same query parameters as above.
Response shape:
{ "data": [ { "id": "uuid", "timestamp": "2026-02-18T12:00:00.000Z", "user": { "id": "uuid", "name": "Jane Admin", "role": "user" }, "action": "device.create", "resource": { "type": "device", "id": "uuid", "name": "My Workstation" }, "category": "device", "result": "success", "ipAddress": "192.168.1.10", "userAgent": "Mozilla/5.0...", "details": {} } ], "pagination": { "page": 1, "limit": 50, "total": 142, "totalPages": 3 }}Get Single Audit Log
Section titled “Get Single Audit Log”GET /audit-logs/logs/:idReturns a single audit log entry in full format. Returns 404 if the entry does not exist or belongs to a different organization.
Search Audit Logs
Section titled “Search Audit Logs”GET /audit-logs/search?q=loginFull-text search across action, actor email, resource type, resource name, and details. The q parameter is required (minimum 1 character). All standard filter parameters (user, action, resource, from, to) can be combined with the search query.
Export Audit Logs (POST)
Section titled “Export Audit Logs (POST)”POST /audit-logs/exportRequest body:
{ "format": "csv", "filters": { "user": "jane", "action": "device", "resource": "workstation" }, "dateRange": { "from": "2026-01-01T00:00:00Z", "to": "2026-02-18T23:59:59Z" }}format:"csv"or"json"(default:"json")filters: Optional object withuser,action, andresourcefieldsdateRange: Optional object withfromandtoISO 8601 timestamps- Maximum 10,000 rows per export
When format is "csv", the response is returned with Content-Type: text/csv and a Content-Disposition header for file download. The CSV columns are: id, timestamp, actorId, actorName, actorEmail, action, resourceType, resourceId, resourceName, category, result, ipAddress, userAgent, details.
The export action itself is recorded as an audit event with action audit_logs.export.
Export Audit Logs (GET)
Section titled “Export Audit Logs (GET)”GET /audit-logs/export?userId=<uuid>CSV-only export endpoint used by the AuditLogViewer export button. Optionally filter by a specific user’s actorId. Maximum 10,000 rows.
User Activity Report
Section titled “User Activity Report”GET /audit-logs/reports/user-activity?from=...&to=...Response:
{ "totalUsers": 12, "totalEvents": 1547, "actionsPerUser": [ { "userId": "uuid", "userName": "Jane Admin", "actionCount": 342, "lastActiveAt": "2026-02-18T15:30:00Z" } ], "topUsers": [], "recentActivity": []}Returns a summary of all users sorted by action count (descending), plus the top 5 most active users and the 10 most recent activity entries.
Security Events Report
Section titled “Security Events Report”GET /audit-logs/reports/security-events?from=...&to=...Response:
{ "totalEvents": 89, "loginAttempts": 64, "failedLogins": 3, "permissionChanges": 2, "byAction": [ { "action": "user.login", "count": 61 } ], "recentEvents": []}Filters audit logs to security-related actions only and provides aggregate metrics on login attempts, failures, and permission changes.
Compliance Report
Section titled “Compliance Report”GET /audit-logs/reports/compliance?from=...&to=...Response:
{ "totalEvents": 234, "dataAccess": 5, "dataChanges": 189, "exports": 3, "byAction": [ { "action": "device.create", "count": 87 } ], "recentEvents": []}Summarizes compliance-relevant actions including data access, data changes, and exports.
GET /audit-logs/stats?from=...&to=...Response:
{ "totalEvents": 1547, "byCategory": [ { "category": "device", "count": 892 }, { "category": "authentication", "count": 234 } ], "byUser": [ { "userId": "uuid", "userName": "Jane Admin", "actionCount": 342 } ], "range": { "from": null, "to": null }}Returns high-level statistics grouped by category and by user. All report endpoints accept optional from and to query parameters (ISO 8601 datetime) and are scoped to the caller’s organization. Reports fetch up to 5,000 rows.
Agent Diagnostic Log Endpoints
Section titled “Agent Diagnostic Log Endpoints”Submit Agent Logs
Section titled “Submit Agent Logs”POST /agents/:id/logsRequires agent bearer token authentication. Accepts a JSON body:
{ "logs": [ { "timestamp": "2026-02-18T12:00:00Z", "level": "warn", "component": "updater", "message": "Update check failed: connection timeout", "fields": { "retryCount": 3, "endpoint": "https://updates.example.com" }, "agentVersion": "1.4.2" } ]}Maximum 500 log entries per request. Returns { "received": <count> } with status 201.
Query Diagnostic Logs
Section titled “Query Diagnostic Logs”GET /devices/:id/diagnostic-logsRequires JWT authentication with organization, partner, or system scope.
Example:
curl -H "Authorization: Bearer $TOKEN" \ "https://breeze.example.com/api/v1/devices/<device-id>/diagnostic-logs?level=warn,error&component=updater&since=2026-02-17T00:00:00Z&search=timeout&limit=100"Response:
{ "logs": [ { "id": "uuid", "deviceId": "uuid", "orgId": "uuid", "timestamp": "2026-02-18T12:00:00Z", "level": "warn", "component": "updater", "message": "Update check failed: connection timeout", "fields": { "retryCount": 3 }, "agentVersion": "1.4.2", "createdAt": "2026-02-18T12:00:01Z" } ], "total": 47, "limit": 100, "offset": 0}Device Event Log Endpoints
Section titled “Device Event Log Endpoints”Submit Device Event Logs
Section titled “Submit Device Event Logs”PUT /agents/:id/eventlogsRequires agent bearer token authentication.
{ "events": [ { "timestamp": "2026-02-18T11:45:00Z", "level": "error", "category": "application", "source": "Application Error", "eventId": "1000", "message": "Faulting application name: app.exe", "details": { "faultModule": "ntdll.dll" } } ]}Returns { "success": true, "count": <inserted> }.
Query Stored Event Logs
Section titled “Query Stored Event Logs”GET /devices/:id/eventlogs?category=security&level=error&startDate=2026-02-01T00:00:00ZRequires JWT authentication. Returns paginated results from the device_event_logs table.
List Available Event Logs
Section titled “List Available Event Logs”GET /system-tools/devices/:deviceId/eventlogsSends a command to the agent and returns the list of Windows Event Log channels (or equivalent) on the device.
Get Event Log Metadata
Section titled “Get Event Log Metadata”GET /system-tools/devices/:deviceId/eventlogs/:nameReturns metadata for a specific log (e.g., Application, Security, System).
Query Live Event Entries
Section titled “Query Live Event Entries”GET /system-tools/devices/:deviceId/eventlogs/:name/events?level=error&limit=50Queries event entries directly from the device in real time.
Get Single Event Entry
Section titled “Get Single Event Entry”GET /system-tools/devices/:deviceId/eventlogs/:name/events/:recordIdReturns a single event record by its record ID.
Multi-Tenant Scoping
Section titled “Multi-Tenant Scoping”All audit log queries are automatically scoped to the caller’s organization. The orgCondition from the authenticated user’s context is applied to every database query, ensuring that users can only see audit logs for their own organization. Partner-scoped users may see logs across their managed organizations.
Troubleshooting
Section titled “Troubleshooting”Audit events are not being recorded
Section titled “Audit events are not being recorded”- Verify that the action handler calls
writeAuditEvent()orwriteRouteAudit(). Events are written asynchronously, so failures do not block request handling. - Check the API server console for
[audit] Failed to write audit log:messages, which indicate database insert failures. - Confirm the
orgIdis being passed. Events with a null or undefinedorgIdare silently dropped. Look for[audit] Dropped event (no orgId):warnings in the console. - Ensure the
actorTypevalue is one of the four valid enum values:user,api_key,agent, orsystem.
Agent diagnostic logs are not appearing
Section titled “Agent diagnostic logs are not appearing”- Confirm the agent is shipping logs by checking the response from
POST /agents/:id/logs. A201with{ "received": N }indicates the API accepted the batch. - Verify the agent ID maps to a valid device. The endpoint looks up the device by
agentIdand returns404if no match is found. - Check batch insert errors in the API console:
[AgentLogs] Error batch inserting logs for device <id>. - Ensure each log entry has valid
level,component, andtimestampfields matching the expected schema.
Device event logs return empty results
Section titled “Device event logs return empty results”- For stored events, confirm the agent has submitted events via
PUT /agents/:id/eventlogs. Check thecountin the response. - For live queries, verify the device is online and connected to the WebSocket. Live queries have a 30-second timeout.
- Check that your query filters (category, level, source, date range) are not too restrictive. Try removing filters to get unfiltered results first.
- For deduplication issues, note that the
device_event_logstable has a unique index on(deviceId, source, eventId). If the same event is submitted again, it is silently skipped.
Export returns no data
Section titled “Export returns no data”- Verify your filters and date range are correct. The export endpoints apply the same filtering logic as the list endpoints.
- Check that the organization has audit log entries in the specified time range.
- Note that exports are capped at 10,000 rows. If you need more, narrow the date range or filter criteria and export in batches.
Live event log queries time out
Section titled “Live event log queries time out”- Confirm the target device is online and the agent is connected.
- The command timeout is 30 seconds. Large event logs on the device may exceed this timeout.
- Use the
level,source, andeventIdfilters to narrow the query and reduce response size. - Check the API console for
Failed to parse agent response for eventmessages, which may indicate the agent returned an unexpected format.