Dashboard
The `dash()` plugin connects your Better Auth instance to Better Auth Infrastructure, enabling analytics tracking, activity monitoring, event logging, and admin dashboard APIs.
The Dashboard plugin is the core connection between your Better Auth instance and Better Auth Infrastructure. It powers the web dashboard with real-time data, tracks user activity, and enables admin APIs.
What the Dashboard Plugin Enables
Once dash() is active, the Better Auth Infrastructure dashboard gives you:
- User management — view, search, ban, and delete users
- Session monitoring — see active sessions and revoke them
- Organization overview — manage organizations and members
- Analytics — track sign-ups, sign-ins, and active users over time
- Audit logs — query event history (learn more)
Installation
import { betterAuth } from "better-auth";
import { dash } from "@better-auth/infra";
export const auth = betterAuth({
plugins: [
dash(),
],
});Compatibility
@better-auth/infra requires Better Auth 1.4 or later. Actively supported @better-auth/infra releases start at 0.3.
@better-auth/infra | Better Auth 1.4 | 1.5 | 1.6 | 1.7 |
|---|---|---|---|---|
| 0.3.x | ✓ | ✓ | ✓ | ✓ |
| 0.4.x | ✓ | ✓ | ✓ | ✓ |
Use the latest 0.4.x release with the latest stable Better Auth 1.7.x.
Managed directory sync (Better Auth 1.7+) requires @better-auth/infra
0.4.x.
Configuration Options
DashOptions
| Option | Type | Description |
|---|---|---|
apiUrl | string | Better Auth Infrastructure API URL. Default: https://dash.better-auth.com |
kvUrl | string | KV store URL. Default: https://kv.better-auth.com |
apiKey | string | Your API key for authentication. Falls back to BETTER_AUTH_API_KEY in env. |
apiOptions | object | Dash API HTTP client options. Accepts timeout?: number (ms, default 3000) and headers?: Record<string, string>. |
kvOptions | object | KV HTTP client options. Accepts timeout?: number (ms, default 1000), retry?: { attempts?: number; baseDelay?: number; maxDelay?: number } (defaults 2 / 400 / 600), and headers?: Record<string, string>. |
apiTimeout | number | Deprecated alias for apiOptions.timeout. |
kvTimeout | number | Deprecated alias for kvOptions.timeout. |
activityTracking | object | Activity tracking configuration. |
managedDirectorySync | object | Managed directory-sync control-plane options. |
Activity Tracking
Track when users were last active in your application. When enabled, a lastActiveAt field is automatically updated on user activity.
dash({
apiKey: process.env.BETTER_AUTH_API_KEY,
activityTracking: {
enabled: true,
updateInterval: 300000, // Update interval in ms (default: 5 minutes)
},
}),Schema Changes
When activity tracking is enabled, the plugin adds a field to your user schema:
user: {
fields: {
lastActiveAt: {
type: "date",
},
},
}Enabling activity tracking requires a database migration for the lastActiveAt user field. Run the migration step before relying on activity data.
npx auth@latest migrateIf your app manages schema generation separately, run npx auth@latest generate and apply the generated migration with your preferred tool.
Managed Directory Sync
Managed directory sync is the dashboard-side companion to the SCIM plugin-managed connections. Use it when each organization (tenant) should get a directory connection from the dashboard — without hard-coding every tenant in application config.
In Better Auth 1.7, SCIM supports three connection modes:
- static code-defined connections
- application-owned runtime verification
- plugin-managed runtime connections via
managedConnections
Managed directory sync is built for that third mode. Responsibilities split cleanly:
| Layer | Owns |
|---|---|
scim({ managedConnections }) | SCIM protocol, credential catalog, user/group provisioning |
dash({ managedDirectorySync }) | Per-organization connection lifecycle, dashboard APIs, and projection into your app |
Once the control plane is on, you can layer optional behaviors: project users into organization memberships and pair the directory with SSO for sign-in, map SCIM attributes onto custom fields.
Enable managed directory sync
You need the organization, SCIM, and dash plugins. SCIM must use managedConnections so Infrastructure can reserve and issue per-tenant credentials.
import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
import { sso } from "@better-auth/sso";
import { scim } from "@better-auth/scim";
import { dash } from "@better-auth/infra";
export const auth = betterAuth({
plugins: [
organization(),
sso({}),
scim({
connections: [],
managedConnections: {
credentialHashSecret: process.env.SCIM_CREDENTIAL_HASH_SECRET!,
},
}),
dash({
apiKey: process.env.BETTER_AUTH_API_KEY,
managedDirectorySync: {
enabled: true,
},
}),
],
});Enabling managedDirectorySync adds reservation tables. Run a migration before creating directories from the dashboard.
npx auth@latest migrateIf your app manages schema generation separately, run npx auth@latest generate and apply the generated migration with your preferred tool.
After setup, create and manage directories in the Infrastructure dashboard (or via the directory sync endpoints).
Membership projection
Membership projection is the usual next step after a directory is connected: when SCIM provisions or deactivates a user, dash reconciles that user into the organization that owns the directory.
It is enabled by default whenever managed directory sync is on.
dash({
apiKey: process.env.BETTER_AUTH_API_KEY,
managedDirectorySync: {
enabled: true,
membershipProjection: {
enabled: true,
role: "member", // role only when projection creates the membership
},
},
})| Option | Type | Description |
|---|---|---|
membershipProjection.enabled | boolean | Installs SCIM projection.reconcileUser for org membership. Default: true. |
membershipProjection.role | string | Role assigned when projection creates a membership. Default: "member". |
Behavior:
- Active directory users are added to the organization (or linked if they are already members).
- Deactivated users have directory-owned memberships removed.
- Provenance tracks whether the membership was created by the directory or only observed (already existed). Projection only mutates memberships it owns.
Turn it off only when SCIM should provision users without touching organization membership:
membershipProjection: {
enabled: false,
}SSO pairing
SSO pairing links a managed directory to an SSO provider so a provisioned user can sign in with the same identity the directory manages.
It is enabled by default. You only need it when directories are created as paired with SSO.
plugins: [
sso({}),
dash({
apiKey: process.env.BETTER_AUTH_API_KEY,
managedDirectorySync: {
enabled: true,
ssoPairing: true,
},
}),
]| Option | Type | Description |
|---|---|---|
ssoPairing | boolean | Installs SSO pairing hooks. Default: true. |
Notes:
- Paired sign-in resolves the Better Auth user from the SCIM external id configured on the directory.
- Set
ssoPairing: falsewhen you only need provisioning and never create paired directories.
Field projection
Field projection maps SCIM User attributes onto Better Auth fields during directory-sync reconcile. Mappings are configured per directory connection in the Infrastructure dashboard (or via the field-mapping endpoints).
It is opt-in and adds its own tables — enable it, migrate, then configure mappings.
import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
import { scim } from "@better-auth/scim";
import { dash } from "@better-auth/infra";
export const auth = betterAuth({
user: {
additionalFields: {
employeeId: { type: "string", required: false },
department: { type: "string", required: false },
},
},
plugins: [
organization({
schema: {
member: {
additionalFields: {
title: { type: "string", required: false },
costCenter: { type: "string", required: false },
},
},
},
}),
scim({
connections: [],
managedConnections: {
credentialHashSecret: process.env.SCIM_CREDENTIAL_HASH_SECRET!,
},
}),
dash({
apiKey: process.env.BETTER_AUTH_API_KEY,
managedDirectorySync: {
enabled: true,
fieldProjection: {
enabled: true,
},
},
}),
],
});- Declare the
user/memberfields you want to fill (as above). - Run migrations for the field-mapping tables.
- In the Infrastructure dashboard, open the directory connection and map SCIM paths → target fields.
| Option | Type | Description |
|---|---|---|
fieldProjection.enabled | boolean | Adds field-mapping schema and projects fields on SCIM reconcile. Default: false. |
Projectable fields
| Entity | Projectable targets | Not projectable |
|---|---|---|
user | Writable user.additionalFields, plus allowlisted core field image | Identity fields managed by SCIM (email, name); sensitive keys (role, password, ban fields, 2FA secrets); input: false or reference fields |
member | Writable organization.schema.member.additionalFields only | Membership-owned keys (role, user/org ids). Member maps require membership projection (default on) |
Only directory-created memberships (ownership: "created") receive member field projection. Observed memberships are left unchanged.
SCIM attribute catalog
Mappings read from a curated SCIM User attribute catalog:
| Path | Typical use |
|---|---|
userName | Login / username |
primaryEmail / emails.primary | Email-shaped additional fields |
displayName | Display name |
externalId | IdP stable id |
name.formatted / name.givenName / name.familyName | Name parts |
title | Job title |
userType | User classification |
preferredLanguage / locale / timezone | Locale preferences |
photos.primary | Avatar URL → often mapped to user.image |
enterprise.employeeNumber | Employee id |
enterprise.costCenter / enterprise.organization / enterprise.division / enterprise.department | Enterprise extension attributes |
Values are resolved as strings from the persisted SCIM user row, then coerced to the Better Auth field type (string, number, boolean, or date).
Projection modes
Each connection stores a mode per entity (user and member). Default mode is create-only.
| Mode | Behavior |
|---|---|
create-only | Fills empty targets (and values that still match a static schema default) on first provision. Once every productive mapped target is set, projection freezes for that row so later operator edits are preserved. Delayed SCIM attributes can still land until freeze. |
reconcile | Rewrites mapped fields on every SCIM reconcile while the directory owns the profile / membership. Use when the IdP should remain the source of truth for those fields. |
Options reference
Full managedDirectorySync shape:
| Option | Type | Description |
|---|---|---|
enabled | boolean | Enables the control plane and reservation tables / APIs. Default: false. |
ssoPairing | boolean | SSO pairing hooks for paired directories. Default: true. |
membershipProjection | object | SCIM → organization membership projection. |
membershipProjection.enabled | boolean | Default: true. |
membershipProjection.role | string | Role when projection creates a membership. Default: "member". |
fieldProjection | object | Opt-in SCIM → custom field projection. |
fieldProjection.enabled | boolean | Default: false. |
Database schema
When managedDirectorySync.enabled is true, the dash plugin adds the models below. Better Auth supplies the primary id field for each model. Some tables are only installed when an opt-in feature is enabled.
directorySyncConnection
Always present when managed directory sync is enabled. Stores the managed directory's organization, SCIM connection, SSO pairing, lifecycle, and decommission state.
| Column | Type | Constraints | Description |
|---|---|---|---|
organizationId | string | Required, indexed | Organization that owns the directory. |
providerId | string | Required | SSO provider identifier. |
aliasKey | string | Required, unique, hidden | Internal directory alias. |
provisioningDomainId | string | Required, unique | SCIM provisioning domain. |
activeOrganizationKey | string | Required, unique, hidden | Active organization key for reconciliation. |
connectionId | string | Optional, unique | Managed SCIM connection identifier. |
creationRequestId | string | Required, unique, hidden | Immutable ownership correlation value. |
status | string | Required | Current directory lifecycle status. |
revision | number | Required, default 0, hidden | Mutation revision used for concurrency control. |
createdAt | date | Required | Creation timestamp. |
createdByActorId | string | Required | Actor that created the directory. |
updatedAt | date | Required | Last update timestamp. |
lastActorId | string | Required | Actor responsible for the latest mutation. |
ssoProviderId | string | Optional | Paired SSO provider ID. |
ssoProviderRecordId | string | Optional, indexed | Paired SSO provider record. |
activeSsoProviderKey | string | Required, unique, hidden | Active SSO provider key. |
serializedSsoPairing | string | Optional, hidden | Serialized SSO pairing metadata. |
pairingEnforced | boolean | Required, default false | Whether the SSO pairing requirement is enforced. |
unpairedAt | date | Optional | Time at which the directory was unpaired. |
unpairedBy | string | Optional | Actor that removed the pairing. |
decommissionStartedAt | date | Optional | Time decommissioning started. |
decommissionedAt | date | Optional | Time decommissioning completed. |
lastError | string | Optional, hidden | Most recent reconciliation error. |
directorySyncMembershipProvenance
Always present when managed directory sync is enabled. Tracks organization memberships created or managed by membership projection.
| Column | Type | Constraints | Description |
|---|---|---|---|
membershipKey | string | Required, unique, hidden | Stable key for the projected membership. |
organizationId | string | Required, indexed | Organization containing the membership. |
userId | string | Required, indexed | Better Auth user receiving the membership. |
memberId | string | Required, unique | Organization member record identifier. |
ownership | string | Required, hidden | created or observed. |
provisioningDomainId | string | Required, indexed | SCIM provisioning domain that produced it. |
createdAt | date | Required | Creation timestamp. |
updatedAt | date | Required | Last update timestamp. |
directorySyncFieldMapping
Only when fieldProjection.enabled is true. Per-connection mapping from SCIM attributes (and/or static defaults) onto Better Auth fields.
| Column | Type | Constraints | Description |
|---|---|---|---|
mappingKey | string | Required, unique, hidden | Stable key for the mapping row. |
provisioningDomainId | string | Required, indexed | SCIM provisioning domain. |
organizationId | string | Required, indexed | Organization that owns the directory. |
entity | string | Required | Target entity (user or member). |
targetField | string | Required | Better Auth field name on that entity. |
scimSource | string | Optional | SCIM resource for scimPath (defaults from entity). |
scimPath | string | Optional | Allowlisted SCIM attribute path. |
defaultValue | string | Optional | Fallback when SCIM value is empty. |
enabled | boolean | Required, default true | Whether the mapping is applied at runtime. |
createdAt | date | Required | Creation timestamp. |
updatedAt | date | Required | Last update timestamp. |
createdByActorId | string | Required | Actor that created the mapping. |
lastActorId | string | Required | Actor responsible for the latest mutation. |
directorySyncFieldProjectionMode
Only when fieldProjection.enabled is true. Per-connection, per-entity write cadence (create-only or reconcile).
| Column | Type | Constraints | Description |
|---|---|---|---|
modeKey | string | Required, unique, hidden | Stable key for the mode row. |
provisioningDomainId | string | Required, indexed | SCIM provisioning domain. |
organizationId | string | Required, indexed | Organization that owns the directory. |
entity | string | Required | Entity the mode applies to. |
mode | string | Required, default create-only | Projection mode. |
createdAt | date | Required | Creation timestamp. |
updatedAt | date | Required | Last update timestamp. |
lastActorId | string | Required | Actor responsible for the latest mutation. |
directorySyncFieldProvenance
Only when fieldProjection.enabled is true. Marks that create-only fields were applied for a provisioning domain + entity + target row.
| Column | Type | Constraints | Description |
|---|---|---|---|
provenanceKey | string | Required, unique, hidden | Stable key for the provenance row. |
provisioningDomainId | string | Required, indexed | SCIM provisioning domain. |
entity | string | Required | Entity that was projected. |
targetId | string | Required, indexed | Primary key of the projected row (userId, memberId, …). |
appliedAt | date | Required | When create-only fields were frozen. |
createdAt | date | Required | Creation timestamp. |
updatedAt | date | Required | Last update timestamp. |
For the full SCIM model and migration guidance, see the SCIM plugin reference and the 1.7 upgrade guide.
Event Tracking
The dash plugin automatically tracks the following events:
User Events
| Event | Trigger |
|---|---|
user_created | New user registration |
profile_updated | User updates their profile |
profile_image_updated | User changes their avatar |
email_verified | Email verification completed |
email_changed | User email address changed |
user_banned | User is banned |
user_unbanned | User is unbanned |
user_role_updated | App-level user role changed |
user_deleted | User account deleted |
anonymous_user_converted | Anonymous guest linked to a permanent account |
two_factor_enabled | Two-factor authentication enabled |
two_factor_disabled | Two-factor authentication disabled |
two_factor_verified | Two-factor verification succeeded |
Session Events
| Event | Trigger |
|---|---|
user_signed_in | Successful sign-in |
user_signed_out | User signs out |
user_sign_in_failed | Failed sign-in attempt |
session_created | New session created |
session_revoked | Single session revoked |
all_sessions_revoked | All sessions revoked |
user_impersonated | Admin starts impersonating user |
user_impersonated_stopped | Admin stops impersonating |
Account Events
| Event | Trigger |
|---|---|
account_linked | Social account linked |
account_unlinked | Social account unlinked |
password_changed | Password updated |
Verification Events
| Event | Trigger |
|---|---|
password_reset_requested | Password reset initiated |
password_reset_completed | Password reset finished |
email_verification_sent | Verification email sent |
Organization Events
If you're using the organization plugin, these events are also tracked:
| Event | Trigger |
|---|---|
organization_created | New organization created |
organization_updated | Organization settings changed |
organization_deleted | Organization deleted |
organization_member_added | Member added to organization |
organization_member_removed | Member removed from organization |
organization_member_role_updated | Member role changed |
organization_member_invited | Invitation sent |
organization_member_invite_accepted | Invitation accepted |
organization_member_invite_rejected | Invitation rejected |
organization_member_invite_canceled | Invitation cancelled |
organization_team_created | Team created |
organization_team_updated | Team updated |
organization_team_deleted | Team deleted |
organization_team_member_added | Member added to team |
organization_team_member_removed | Member removed from team |
Dashboard Endpoints
The dash plugin registers numerous admin endpoints for the dashboard:
Config
| Endpoint | Method | Description |
|---|---|---|
/dash/config | GET | Auth config and plugin insights |
/dash/validate | GET | Validate dashboard connectivity |
User Management
| Endpoint | Method | Description |
|---|---|---|
/dash/list-users | GET | List users with pagination |
/dash/export-users | GET | Export users |
/dash/user | GET | Get user details |
/dash/user-organizations | GET | List organizations for a user |
/dash/create-user | POST | Create a user |
/dash/update-user | POST | Update user |
/dash/delete-user | POST | Delete user |
/dash/delete-many-users | POST | Delete many users |
/dash/ban-user | POST | Ban user |
/dash/ban-many-users | POST | Ban many users |
/dash/unban-user | POST | Unban user |
/dash/set-user-role | POST | Set app-level user.role |
/dash/set-password | POST | Set user password |
/dash/unlink-account | POST | Unlink account |
/dash/impersonate-user | GET | Impersonate user |
/dash/send-verification-email | POST | Send verification email |
/dash/send-many-verification-emails | POST | Send verification emails bulk |
/dash/send-reset-password-email | POST | Send password reset email |
Session Management
| Endpoint | Method | Description |
|---|---|---|
/dash/sessions/revoke | POST | Revoke single session |
/dash/sessions/revoke-all | POST | Revoke all user sessions |
/dash/sessions/revoke-many | POST | Revoke many sessions |
Organization Management
| Endpoint | Method | Description |
|---|---|---|
/dash/list-organizations | GET | List organizations |
/dash/export-organizations | GET | Export organizations |
/dash/organization/options | GET | Organization plugin options |
/dash/organization/:id | GET | Get organization details |
/dash/organization/create | POST | Create organization |
/dash/organization/update | POST | Update organization |
/dash/organization/delete | POST | Delete organization |
/dash/organization/delete-many | POST | Delete many organizations |
/dash/organization/:id/members | GET | List members |
/dash/organization/add-member | POST | Add member |
/dash/organization/remove-member | POST | Remove member |
/dash/organization/update-member-role | POST | Update member role only |
/dash/organization/update-member | POST | Update member role and extra fields |
Team Management
| Endpoint | Method | Description |
|---|---|---|
/dash/organization/:id/teams | GET | List teams |
/dash/organization/create-team | POST | Create team |
/dash/organization/update-team | POST | Update team |
/dash/organization/delete-team | POST | Delete team |
/dash/organization/:orgId/teams/:teamId/members | GET | List team members |
/dash/organization/add-team-member | POST | Add team member |
/dash/organization/remove-team-member | POST | Remove team member |
Invitation Management
| Endpoint | Method | Description |
|---|---|---|
/dash/organization/:id/invitations | GET | List invitations |
/dash/organization/invite-member | POST | Send invitation |
/dash/organization/cancel-invitation | POST | Cancel invitation |
/dash/organization/resend-invitation | POST | Resend invitation |
/dash/organization/check-user-by-email | POST | Check user by email |
/dash/accept-invitation | GET | Accept invitation |
/dash/complete-invitation | POST | Complete invitation |
/dash/complete-invitation-handoff | GET | Invitation handoff |
/dash/complete-invitation-social | GET | Social invitation |
/dash/check-user-exists | POST | Check if user exists |
SSO Management
| Endpoint | Method | Description |
|---|---|---|
/dash/sso/connection-count | GET | Project-wide SSO connection count |
/dash/organization/:id/sso-providers | GET | List SSO providers |
/dash/organization/:id/sso-provider/create | POST | Create SSO provider |
/dash/organization/:id/sso-provider/update | POST | Update SSO provider |
/dash/organization/:id/sso-provider/delete | POST | Delete SSO provider |
/dash/organization/:id/sso-provider/request-verification-token | POST | Request domain verification token |
/dash/organization/:id/sso-provider/verify-domain | POST | Verify domain |
/dash/organization/:id/sso-provider/mark-domain-verified | POST | Mark domain verified |
Directory Sync
| Endpoint | Method | Description |
|---|---|---|
/dash/directory-sync/connection-count | GET | Project-wide directory connection count |
/dash/organization/:id/directories | GET | List directories |
/dash/organization/directory/create | POST | Create legacy directory |
/dash/organization/directory/delete | POST | Delete legacy directory |
/dash/organization/directory/regenerate-token | POST | Regenerate legacy SCIM token |
/dash/organization/:id/directories | POST | Create managed directory |
/dash/organization/:id/directories/:providerId | GET | Get managed directory |
/dash/organization/:id/directories/:providerId/credentials/rotate | POST | Rotate managed directory credential |
/dash/organization/:id/directories/:providerId/credentials/:credentialId/revoke | POST | Revoke managed directory credential |
/dash/organization/:id/directories/:providerId/events | GET | List managed directory events |
/dash/organization/:id/directories/:providerId/decommission | POST | Decommission managed directory |
/dash/organization/:id/directories/:providerId/unpair | POST | Unpair managed directory from SSO |
/dash/organization/:id/directory-field-mapping-options | GET | Field-mapping catalog |
/dash/organization/:id/directories/:providerId/field-mappings | GET | Get field mappings and modes |
/dash/organization/:id/directories/:providerId/field-mappings | PUT | Replace field mappings and modes |
Events & Audit Logs
| Endpoint | Method | Description |
|---|---|---|
/events/list | GET | Current user's events |
/events/audit-logs | GET | Current user's audit logs (getAuditLogs) |
/events/all-audit-logs | GET | Org-admin audit logs (getAllAuditLogs) |
/events/types | GET | List known event types |
Analytics
| Endpoint | Method | Description |
|---|---|---|
/dash/user-stats | GET | Get user statistics |
/dash/user-graph-data | GET | Get graph data |
/dash/user-retention-data | GET | Get retention data |
Two-Factor Management
| Endpoint | Method | Description |
|---|---|---|
/dash/enable-two-factor | POST | Enable 2FA for user |
/dash/complete-two-factor-setup | POST | Complete 2FA setup |
/dash/disable-two-factor | POST | Disable 2FA for user |
/dash/view-two-factor-totp-uri | POST | Get TOTP URI |
/dash/view-backup-codes | POST | View backup codes |
/dash/generate-backup-codes | POST | Generate new backup codes |
Client Integration
dashClient()
The client plugin provides access to audit log queries:
import { createAuthClient } from "better-auth/client";
import { dashClient } from "@better-auth/infra/client";
export const authClient = createAuthClient({
plugins: [dashClient()],
});Note: For Expo or React Native, import dashClient from @better-auth/infra/native (same API) and pair it with sentinelNativeClient as described in Sentinel — Expo and React Native.
Configuration
dashClient({
resolveUserId: ({ userId, user, session }) => {
return userId || user?.id || session?.user?.id;
},
}),Get the current user's audit logs
Returns audit events for the current user, or organization-scoped events when you pass organizationId as a member.
Basic query
const session = await authClient.getSession();
const logs = await authClient.dash.getAuditLogs({
session: session.data,
limit: 50,
offset: 0,
});
// Access the data
console.log(logs.data?.events); // Array of audit log events
console.log(logs.data?.total); // Total count
console.log(logs.data?.limit); // Page size
console.log(logs.data?.offset); // Current offsetSee Get current user's audit logs for more information.
Get all audit logs
Returns all audit events for organizations the current user has admin or owner access to. Requires the organization plugin for role checks.
Basic query
const session = await authClient.getSession();
const activity = await authClient.dash.getAllAuditLogs({
session: session.data,
limit: 50,
offset: 0,
});
console.log(activity.data?.events);
console.log(activity.data?.total);See Get all audit logs for more information.
Best Practices
-
Always set an API key — without it, the plugin cannot communicate with the infrastructure API.
-
Use activity tracking wisely — the update interval affects database writes. For high-traffic apps, consider a longer interval.
-
Monitor audit log retention — different plans have different retention periods. Check your plan limits.
-
Secure your endpoints — dashboard endpoints require authentication. Make sure your dashboard users have appropriate permissions.