Notifications API
Endpoints
Section titled “Endpoints”All endpoints require authentication. No specific tool permission required — users can only access their own notifications.
GET /api/notifications
Section titled “GET /api/notifications”List notifications for the current user, paginated.
Query params:
filter—all(default),unread, orarchivedlimit— max results (default 50, max 100)offset— pagination offset
Response:
{ "notifications": [ { "id": "uuid", "user_id": "uuid", "type": "task_assigned", "title": "John assigned you a task", "body": "Fix login bug", "icon": "CheckSquare", "resource_type": "task", "resource_id": "uuid", "action_url": "/tasks?taskId=uuid", "actor_id": "uuid", "actor_name": "John Smith", "actor_picture": "https://...", "is_read": 0, "read_at": null, "archived": 0, "archived_at": null, "created_at": "2026-03-20T10:00:00" } ], "total": 42, "limit": 50, "offset": 0}GET /api/notifications/unread-count
Section titled “GET /api/notifications/unread-count”Returns the number of unread, non-archived notifications. Polled every 60 seconds by the frontend.
Response: { "unread_count": 5 }
POST /api/notifications/:id/read
Section titled “POST /api/notifications/:id/read”Mark a single notification as read.
Response: { "success": true }
POST /api/notifications/read-all
Section titled “POST /api/notifications/read-all”Mark all unread notifications as read.
Response: { "success": true }
POST /api/notifications/:id/archive
Section titled “POST /api/notifications/:id/archive”Soft-archive a notification (no hard deletes).
Response: { "success": true }
POST /api/notifications/archive-all
Section titled “POST /api/notifications/archive-all”Archive all read notifications.
Response: { "success": true }
Preferences
Section titled “Preferences”GET /api/notifications/preferences
Section titled “GET /api/notifications/preferences”Returns all notification types merged with the user’s custom preferences. Each entry includes the effective channel settings (user override or system default).
Response:
{ "preferences": [ { "notification_type": "task_assigned", "category": "tasks", "label": "Task Assigned", "description": "When a task is assigned to you", "channel_in_app": 1, "channel_email": 0, "channel_slack": 0, "channel_push": 0, "is_customized": false } ]}PUT /api/notifications/preferences
Section titled “PUT /api/notifications/preferences”Update notification preferences. Send an array of type/channel pairs.
Body:
{ "preferences": [ { "notification_type": "task_assigned", "channel_in_app": 1, "channel_email": 1, "channel_slack": 0, "channel_push": 1 } ]}Response: { "success": true }
GET /api/notifications/types
Section titled “GET /api/notifications/types”List the notification types catalog (admin reference).
Response: { "types": [{ "id": "task_assigned", "category": "tasks", "label": "Task Assigned", ... }] }
Push Subscriptions
Section titled “Push Subscriptions”GET /api/notifications/push/vapid-key
Section titled “GET /api/notifications/push/vapid-key”Returns the VAPID public key for Web Push registration. Returns 503 if push is not configured.
Response: { "vapidPublicKey": "BMO-g9PU..." }
POST /api/notifications/push/subscribe
Section titled “POST /api/notifications/push/subscribe”Register a push subscription for the current user.
Body:
{ "endpoint": "https://fcm.googleapis.com/fcm/send/...", "keys": { "p256dh": "base64url-encoded", "auth": "base64url-encoded" }}Response: { "success": true }
POST /api/notifications/push/unsubscribe
Section titled “POST /api/notifications/push/unsubscribe”Remove a push subscription.
Body: { "endpoint": "https://fcm.googleapis.com/fcm/send/..." }
Response: { "success": true }
GET /api/notifications/push/subscriptions
Section titled “GET /api/notifications/push/subscriptions”List the current user’s push subscriptions.
Response: { "subscriptions": [{ "id": "uuid", "endpoint": "...", "user_agent": "...", "created_at": "..." }] }
Squad Notification Config (Executive Only)
Section titled “Squad Notification Config (Executive Only)”GET /api/notifications/squads/:squadId/config
Section titled “GET /api/notifications/squads/:squadId/config”Get notification channel config for a squad, merged with the notification types catalog.
Response:
{ "config": [ { "notification_type": "task_assigned", "category": "tasks", "label": "Task Assigned", "slack_channel_id": "C08XXXXXXXX", "email_group": "design@example.com", "enabled": 1 } ]}PUT /api/notifications/squads/:squadId/config
Section titled “PUT /api/notifications/squads/:squadId/config”Update per-type notification config for a squad.
Body:
{ "config": [ { "notification_type": "task_assigned", "slack_channel_id": "C08XXXXXXXX", "email_group": null, "enabled": 1 } ]}Portal Notifications
Section titled “Portal Notifications”Portal endpoints use X-Portal-User-Id header for authentication. Only notification types with supports_portal = 1 are available.
GET /api/portal/notifications
Section titled “GET /api/portal/notifications”GET /api/portal/notifications/unread-count
Section titled “GET /api/portal/notifications/unread-count”POST /api/portal/notifications/:id/read
Section titled “POST /api/portal/notifications/:id/read”POST /api/portal/notifications/read-all
Section titled “POST /api/portal/notifications/read-all”GET /api/portal/notifications/preferences
Section titled “GET /api/portal/notifications/preferences”PUT /api/portal/notifications/preferences
Section titled “PUT /api/portal/notifications/preferences”Same behaviour as the main notification endpoints, scoped to portal users. Preferences only expose In-App and Email channels.
Notification Analytics (Executive Only)
Section titled “Notification Analytics (Executive Only)”GET /api/usage/notifications/summary?days=7
Section titled “GET /api/usage/notifications/summary?days=7”Response: { "total_sent": 150, "total_read": 120, "unique_recipients": 12, "total_deliveries": 45, "read_rate": 80 }
GET /api/usage/notifications/by-type?days=7
Section titled “GET /api/usage/notifications/by-type?days=7”Notification counts by type from Analytics Engine.
GET /api/usage/notifications/daily-trend?days=7
Section titled “GET /api/usage/notifications/daily-trend?days=7”Daily sent volume.
GET /api/usage/notifications/channel-distribution?days=7
Section titled “GET /api/usage/notifications/channel-distribution?days=7”Delivery counts by channel (email, slack, push) and status.
GET /api/usage/notifications/read-rates?days=7
Section titled “GET /api/usage/notifications/read-rates?days=7”Read rate percentage by notification type.
Internal Helper
Section titled “Internal Helper”createNotification(params)
Section titled “createNotification(params)”Creates an in-app notification and triggers delivery to email/Slack/push based on user preferences. Called via c.executionCtx.waitUntil() from route handlers.
Deduplication: Skips if the same (user, type, resource) combination was created within the last 5 minutes.
createSquadNotification(params)
Section titled “createSquadNotification(params)”Notifies all members of a squad and posts to the squad’s configured Slack channel. Accepts an audience parameter ("squad", "leads", or "managers") to select the channel.