3.2 KiB
Notifications
Real-time notification infrastructure with WebSocket delivery and optional email transport.
Auth: All endpoints require authentication (JWT via sb_token
cookie or Authorization: Bearer header).
CRUD
GET /notifications → paginated list
GET /notifications/unread-count → { "count": 5 }
PATCH /notifications/:id/read → mark one as read
POST /notifications/mark-all-read → mark all as read
DELETE /notifications/:id
GET /notifications — paginated list for the authenticated user.
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
limit |
int | 20 | 1–100, clamped |
offset |
int | 0 | Pagination offset |
unread_only |
bool | false | Filter to unread only |
Response:
{
"data": [ ... ],
"total": 42,
"limit": 20,
"offset": 0
}
Notification object:
{
"id": "uuid",
"user_id": "uuid",
"type": "role.fallback",
"title": "Role Fallback Triggered",
"body": "Primary model unavailable, using fallback",
"resource_type": "channel",
"resource_id": "uuid",
"is_read": false,
"created_at": "2025-01-15T12:00:00Z"
}
resource_type and resource_id are optional — used for
click-to-navigate. The resource may be deleted (no FK constraint).
Preferences
Users control per-type delivery:
GET /notifications/preferences → { "data": [...] }
PUT /notifications/preferences/:type ← { "in_app": true, "email": false }
DELETE /notifications/preferences/:type → reset to default
GET /notifications/preferences returns all preferences set by
the user. Empty array if none are configured.
PUT /notifications/preferences/:type creates or updates a
preference. Both in_app and email fields are optional (merges
with existing values if set).
DELETE /notifications/preferences/:type removes the preference,
falling back to the next level in the resolution chain. Idempotent —
deleting a non-existent preference returns 200.
Resolution: specific type pref → user wildcard * pref → system
default (in_app=true, email=false).
Returns 503 if the preference store is not available (unmanaged mode).
Admin
POST /admin/notifications/test-email → send test email to requesting admin
Requires admin role. Loads SMTP config from platform settings, sends a test message to the admin's registered email address.
WebSocket Events
| Event | Payload | Description |
|---|---|---|
notification.new |
Full notification object | New notification created |
notification.read |
{"id": "uuid"} |
Single notification marked read |
notification.read |
{"action": "mark_all_read"} |
All notifications marked read |
These are targeted via Hub.SendToUser — no room subscription
required. Used for badge sync across tabs.
Notification Types
See enums.md for the canonical list.
Types are free-form strings (domain.action convention) — new types
don't require migration.
Retention
Background cleanup prunes notifications older than 90 days (default,
configurable via WithRetention). Runs daily after a 5-minute
startup delay.