Skip to content

Notifications API

All endpoints require authentication. No specific tool permission required — users can only access their own notifications.

List notifications for the current user, paginated.

Query params:

  • filterall (default), unread, or archived
  • limit — 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
}

Returns the number of unread, non-archived notifications. Polled every 60 seconds by the frontend.

Response: { "unread_count": 5 }

Mark a single notification as read.

Response: { "success": true }

Mark all unread notifications as read.

Response: { "success": true }

Soft-archive a notification (no hard deletes).

Response: { "success": true }

Archive all read notifications.

Response: { "success": true }


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
}
]
}

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 }

List the notification types catalog (admin reference).

Response: { "types": [{ "id": "task_assigned", "category": "tasks", "label": "Task Assigned", ... }] }


Returns the VAPID public key for Web Push registration. Returns 503 if push is not configured.

Response: { "vapidPublicKey": "BMO-g9PU..." }

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 }

Remove a push subscription.

Body: { "endpoint": "https://fcm.googleapis.com/fcm/send/..." }

Response: { "success": true }

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 endpoints use X-Portal-User-Id header for authentication. Only notification types with supports_portal = 1 are available.

GET /api/portal/notifications/unread-count

Section titled “GET /api/portal/notifications/unread-count”

Same behaviour as the main notification endpoints, scoped to portal users. Preferences only expose In-App and Email channels.


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.


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.

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.