Skip to main content
The audit log at /dashboard/audit-log records every administrative action taken through the dashboard or API. Each entry captures who performed the action, what changed, when it happened, and from which IP address.

What gets logged

The following action types are recorded:
ActionDescription
config.updateA bot configuration key was changed
members.updateA member record was updated
moderation.createA moderation action was applied (warn, ban, timeout, etc.)
moderation.deleteA moderation record was removed
tickets.updateA support ticket was updated
Each entry also stores a target_type and target_id identifying the affected object, and a details JSON blob with the full before/after payload.

Browsing the log

Entries are displayed in a table sorted by most recent first, showing 25 entries per page. The table columns are:
  • Action — a color-coded badge: blue for create, grey for update, red for delete, and outline for all other types
  • User — the Discord user ID of the admin who performed the action
  • Target — the target type and ID in type:id format
  • Date — the local date and time of the action
  • IP — the IP address of the request (visible on wide screens)
Click any row to expand it and view the raw details JSON for that entry.

Filtering entries

The filter bar above the table lets you narrow results across four dimensions:
Type a Discord user ID in the search box. Results update automatically after a 300 ms debounce. Click the X inside the field to clear the filter.
Use the All actions dropdown to select a specific action type such as config.update or moderation.create.
Set a Start date and/or End date using the date pickers. Entries outside the range are excluded. Both filters are optional and can be used independently.
All filters combine — you can filter by action type, user ID, and date range simultaneously. The total entry count updates to reflect the filtered result.

Pagination

When there are more than 25 matching entries, Previous and Next buttons appear at the bottom of the table. The current page and total page count are shown alongside the controls.

Real-time streaming

The audit log supports live updates via a WebSocket connection at /ws/audit-log. When the dashboard is open, new entries appear in the table as they are written without requiring a page refresh. The WebSocket protocol uses HMAC-authenticated tickets:
// Client → Server: authenticate
{ "type": "auth", "ticket": "<nonce>.<expiry>.<guildId>.<hmac>" }

// Server → Client: authentication confirmed
{ "type": "auth_ok" }

// Client → Server: subscribe with optional filters
{ "type": "filter", "guildId": "...", "action": "config.update", "userId": "..." }

// Server → Client: new audit entry
{ "type": "entry", "entry": { ... } }
Clients must authenticate within 10 seconds of connecting or the server closes the connection. The stream supports up to 10 concurrent authenticated clients. A 30-second heartbeat ping/pong keeps idle connections alive.
Real-time streaming is automatically managed by the dashboard. You do not need to configure it manually when using the web UI.

Exporting data

Use the export endpoint to download the full filtered log outside the paginated view.
The CSV file includes all filtered entries up to a maximum of 10,000 rows. The columns match the database schema:
id, guild_id, user_id, action, target_type, target_id, details, ip_address, created_at
The details column is JSON-encoded and quoted according to RFC 4180.
The export endpoint is rate-limited to 10 requests per minute per IP. The standard read endpoint is rate-limited to 30 requests per minute.

Log retention

The number of days audit entries are retained is controlled by the auditLog.retentionDays configuration key. Entries older than the retention window are purged automatically.
Reduce the retention period with care. Once entries are purged they cannot be recovered. Export data before reducing auditLog.retentionDays if you need a historical record.

Refreshing manually

Click Refresh in the page header to reload the current filter view on demand. The button shows a spinner while the request is in flight.

Build docs developers (and LLMs) love