Notifications & Alerts
Stay informed about critical events with in-app notifications, configurable preferences, and automated reminders.
Overview
Axiomatic's notification system keeps you informed about important events without requiring you to constantly check the app. Notifications appear in real-time via the bell icon in the top navigation bar, and can be configured per type and delivery channel.
Notification Types
| Type | Trigger | Example |
|---|---|---|
approval_pending | A journal entry requires your approval | "Journal entry JE-042 is awaiting your approval" |
approval_resolved | A journal entry you submitted was approved or rejected | "Your journal entry JE-042 was approved" |
sync_completed | A bank or integration sync finished successfully | "Plaid sync completed: 47 new transactions imported" |
sync_failed | A sync encountered an error | "Mercury sync failed: authentication expired" |
close_deadline | An accounting period's close date is approaching | "Period 2025-Q2 closes in 3 days" |
usage_threshold | Your tenant credit balance is low or exhausted | "Your credit balance is $4.50 — add credits to avoid interruption" |
team_invite | You were added to an entity's team | "You were added to Acme Corp by matt@example.com" |
comment_added | Someone commented on a record you're involved with | "Sarah commented on journal entry JE-042" |
mention | Someone @mentioned you in a comment | "@matt mentioned you: 'Can you review this entry?'" |
system | System-level alerts | "Scheduled maintenance window: Sunday 2am-4am UTC" |
crm_lead_assigned | CRM lead assigned to you | "Lead assigned: Acme expansion" |
crm_lead_won | CRM lead marked won | "Lead won: Acme expansion" |
crm_task_due | CRM task due or overdue | "CRM task: Follow up with Acme" |
invoice_overdue | Customer invoice past due | "Invoice INV-1042 is overdue" |
invoice_paid | Customer paid an invoice | "Payment received for INV-1042" |
expense_submitted | Expense report submitted | "Expense report submitted for review" |
expense_approved | Expense report decision | "Your expense report was approved" |
purchase_order_approved | PO approved | "Purchase order PO-88 approved" |
sales_quote_approved | Sales quote accepted | "Quote Q-12 accepted" |
helpdesk_ticket_assigned | New helpdesk ticket | "New ticket HD-441 opened" |
governance_filing_due | Corporate filing deadline | "Annual report due in 7 days" |
bi_report_ready | Scheduled report ready | "Trial balance report is ready" |
Additional module types (inventory, HR leave, routes, maintenance, manufacturing, marketing, documents) are listed in Settings → Notifications.
Viewing Notifications
Click the bell icon in the top navigation bar to open the notification panel. Unread notifications show a badge count. From the panel you can:
- View all recent notifications
- Click a notification to navigate to the relevant record
- Mark individual notifications as read
- Mark all notifications as read
Notification Preferences
Configure which notification types you receive and through which channels. Navigate to Settings → Notifications to manage your preferences.
Each notification type can be independently enabled or disabled per delivery channel:
| Channel | Description |
|---|---|
in_app | Notifications appear in the bell icon panel |
email | Notifications are sent to your email address |
Automated Reminders
Close Deadline Reminders
A background cron job checks for open accounting periods with approaching close dates. When a period's end date is within the configured reminder window, all entity administrators receive a close_deadline notification.
This ensures no one misses a period close — even if they haven't logged in recently.
Usage Threshold Alerts
When a tenant's prepaid credit balance drops to $5 or below (or reaches $0), billing owners receive usage_threshold notifications (in-app and email, if enabled). This replaces the old subscription-tier quota model.
Delivery API (server-side)
Producers should use the unified delivery helpers in @/lib/notifications/deliver:
notifyUser(userId, payload)— single recipient; honorsin_appandemailprefsnotifyUsers(userIds, payload)— batch fan-outnotifyEntityMembers({ entityId, rbacKeys?, ...payload })— RBAC-filtered recipientsnotifyEntityAdminsWithPrefs(entityId, payload)— finance-close admins
Pass an optional email: { send: (to) => ... } callback to send transactional mail when the user has email enabled for that type. Defaults to enabled when no preference row exists.
Real-Time Events (Pusher)
In addition to persisted notifications, the system broadcasts real-time events via Pusher WebSockets for features that require instant UI updates without polling.
Channels
| Channel | Pattern | Used By |
|---|---|---|
| Entity events | entity-{entityId} | Sync status, proposals, transaction imports |
| Chat updates | chat-{chatId} | AI assistant streaming |
| User notifications | user-{userId} | New in-app notification (notification:created) |
The notification bell subscribes to user-{userId} for instant badge updates, with a 30-second poll fallback when Pusher is unavailable.
Sync Events
The following events are broadcast on entity-{entityId} during integration syncs:
| Event | Description | Payload |
|---|---|---|
sync:started | A connection sync has begun | connectionId, provider |
sync:progress | Incremental sync progress | connectionId, transactionsCreated, accountsSynced |
sync:completed | Sync finished successfully | connectionId, transactionsCreated, duplicatesSkipped, quarantined, errors[] |
sync:failed | Sync encountered an error | connectionId, error |
Other Real-Time Events
| Event | Description | Payload |
|---|---|---|
proposal:created | AI generated a new proposal | entityId |
proposal:updated | A proposal was approved/rejected | entityId, proposalId, status |
transaction:imported | Transactions were imported | entityId, count |
Subscribing in the app (Realtime)
Use the useRealtimeChannel hook to subscribe to entity events:
useRealtimeChannel(`entity-${entityId}`, {
"sync:completed": (data) => { /* refresh UI */ },
"sync:failed": (data) => { /* show error */ },
});The Import & Sync page and dashboard automatically subscribe to these events for live status updates.
API Reference
List Notifications
GET /api/notifications?limit=20&offset=0&unreadOnly=falseReturns a paginated list of notifications for the authenticated user, along with the current unread count.
Response:
{
"notifications": [
{
"id": "notif-uuid",
"type": "approval_pending",
"title": "Approval Required",
"body": "Journal entry JE-042 is awaiting your approval",
"actionUrl": "/accounting/journal?id=je-042",
"read": false,
"createdAt": "2025-06-15T10:30:00Z"
}
],
"unreadCount": 3
}Mark Notification as Read
PATCH /api/notifications/:idMarks a single notification as read and sets the readAt timestamp.
Mark All as Read
POST /api/notifications
{
"action": "mark_all_read"
}Marks all unread notifications for the authenticated user as read.
Get Notification Preferences
GET /api/notification-preferencesReturns the user's notification preferences for all types and channels.
Update Notification Preference
PUT /api/notification-preferences
{
"type": "sync_completed",
"channel": "email",
"enabled": false
}Enable or disable a specific notification type for a given channel.