Skip to main content

Notifications

The notification system provides multi-channel notifications (push, in-app, email, SMS, chat) powered by Novu. The service acts as a thin multi-tenant proxy to Novu's REST API — payloads and responses are passed through as opaque JSON where possible.

All notification endpoints are available through the KrakenD API gateway.

Concepts

TermDescription
WorkflowA Novu notification template defining content, channels, and delivery steps. You trigger workflows by their workflow_id.
ChannelDelivery method: push, in-app, email, SMS, chat
SubscriberA user registered to receive notifications (1:1 with user ID)
TopicA named group of subscribers for fan-out delivery
DigestBatching behavior configured in a Novu workflow step — groups events before delivery
ProviderExternal service for delivery (FCM, APNS, SendGrid, Twilio, etc.)

Architecture

Notifications architecture — client apps send POST requests through KrakenD, which injects auth headers and forwards them via NotificationGatewayService to the NotificationService, which proxies calls to Novu over REST with circuit-breaker protection

The NotificationGatewayService extracts authentication context from request headers and forwards to the NotificationService, which owns the Novu integration with circuit breaker protection and per-tenant credential resolution.

Endpoint Paths

User-facing endpoints use /api/v1/notifications/, while admin/management endpoints use /api/v1/notifications/manage/.

Protojson Encoding

All responses use protobuf JSON encoding. Fields with default values (false, 0, "") are omitted from the response. Your decoder must treat missing fields as their default value.

Push Device Registration

Register a device to receive push notifications via FCM.

Register a Device

POST /api/v1/notifications/register-push-device
{
"fcmToken": "firebase-cloud-messaging-token",
"platform": "PLATFORM_IOS",
"deviceId": "device-unique-id"
}

Response:

{
"subscriberId": "user_123",
"success": true
}

Unregister a Device

POST /api/v1/notifications/unregister-push-device
{
"fcmToken": "firebase-cloud-messaging-token"
}

Response:

{
"subscriberId": "user_123"
}

remainingCredentialCount appears when > 0 (other devices still registered).

Get Registered Channels

Check which notification channels are available for the current user.

POST /api/v1/notifications/get-registered-channels
{}

Response:

{
"channels": [
{"channel": "CHANNEL_IN_APP", "registered": true, "credentialCount": 1},
{"channel": "CHANNEL_PUSH"},
{"channel": "CHANNEL_EMAIL", "registered": true, "credentialCount": 1},
{"channel": "CHANNEL_SMS"}
]
}

Channels without credentials omit registered and credentialCount.

Sending Notifications

All send endpoints use workflow_id to specify which Novu workflow to trigger. Call ListWorkflows first to discover available workflow IDs.

Send to a User

POST /api/v1/notifications/manage/send-notification
{
"workflowId": "push-notification",
"userId": "recipient-user-id",
"payload": {
"title": "New Message",
"body": "You have a new coaching update",
"deep_link": "socayo://conversation/conv_abc"
},
"transactionId": "optional-idempotency-key"
}

Response:

{
"acknowledged": true,
"status": "processed",
"transactionId": "txn_abc123"
}
FieldTypeDescription
workflowIdstringNovu workflow identifier (required)
userIdstringRecipient user ID (required)
payloadobjectArbitrary JSON passed to the workflow template
overridesobjectNovu provider overrides (e.g., FCM data payload)
transactionIdstringOptional idempotency/tracking key

Send Bulk

Trigger workflows for multiple recipients in a single call.

POST /api/v1/notifications/manage/send-bulk-notification
{
"events": [
{
"workflowId": "push-notification",
"userId": "user-1",
"payload": {"title": "Update", "body": "New feature available"}
},
{
"workflowId": "push-notification",
"userId": "user-2",
"payload": {"title": "Update", "body": "New feature available"}
}
]
}

Response:

{
"results": [
{"acknowledged": true, "status": "processed", "transactionId": "txn_1"},
{"acknowledged": true, "status": "processed", "transactionId": "txn_2"}
]
}

Cancel a Notification

Cancel a pending notification by transaction ID.

POST /api/v1/notifications/manage/cancel-notification
{
"transactionId": "txn_abc123"
}

Response:

{
"cancelled": true,
"message": "Event cancelled successfully"
}

In-App Inbox

Get Inbox Session

Get a Novu session token and WebSocket URL for real-time inbox updates.

POST /api/v1/notifications/get-inbox-session
{}

Response:

{
"token": "eyJhbGciOiJIUzI1NiIs...",
"socketUrl": "wss://novu-ws.yocaso.dev",
"expiresIn": "1296000"
}
FieldTypeDescription
tokenstringJWT for WebSocket auth
socketUrlstringNovu WebSocket URL
expiresInstringToken validity in seconds (~15 days). String type (int64 protojson convention).

Get Inbox Feed

POST /api/v1/notifications/get-inbox-feed
{
"page": 1,
"pageSize": 20
}

Pagination is 1-based. Optional filter object supports unseenOnly, unreadOnly, feedIds, and categories (plain strings).

Response:

{
"messages": [
{
"messageId": "69c0df5391079c0a4596f7d3",
"notificationId": "69c0df5291079c0a4596f79b",
"title": "Weekly Check-in",
"body": "Time to review your progress.",
"data": {
"title": "Weekly Check-in",
"body": "Time to review your progress.",
"deep_link": "socayo://screen?name=weekly"
},
"deepLink": "socayo://screen?name=weekly",
"status": "MESSAGE_STATUS_UNSEEN",
"createdAt": "2026-03-23T06:36:03.578Z"
}
],
"totalCount": 6,
"page": 1,
"pageSize": 20
}

hasMore only appears when true. Fields like category, deepLink, actions are omitted when empty.

Get Unseen Count

POST /api/v1/notifications/get-inbox-unseen-count

Response:

{
"unseenCount": 3,
"unreadCount": 5
}

Counts are capped at 10. hasMoreUnseen/hasMoreUnread appear when true — display as "9+".

Mark Messages

Mark a single message:

POST /api/v1/notifications/mark-inbox-message
{
"messageId": "msg_123",
"markAs": "MESSAGE_STATUS_READ"
}

Response:

{
"messages": [
{
"messageId": "msg_123",
"channel": "in_app",
"seen": true,
"content": "Time to review your progress.",
"status": "sent",
"createdAt": "2026-03-23T06:36:03.578Z",
"lastSeenDate": "2026-03-23T10:24:35.518Z"
}
]
}

Mark all messages:

POST /api/v1/notifications/mark-all-inbox-messages
{
"markAs": "MESSAGE_STATUS_SEEN"
}

Response: {"updatedCount": 5}

Status options: MESSAGE_STATUS_SEEN, MESSAGE_STATUS_READ, MESSAGE_STATUS_UNSEEN, MESSAGE_STATUS_UNREAD.

Delete Inbox Message

POST /api/v1/notifications/delete-inbox-message
{
"messageId": "msg_123"
}

Response:

{
"status": {
"acknowledged": true,
"status": "deleted"
}
}

Preferences

Preferences are managed per-workflow and per-channel in Novu. The API returns the raw Novu preference structure.

Get Preferences

POST /api/v1/notifications/get-preferences

Response:

{
"preferences": {
"data": {
"global": {
"channels": {
"email": true,
"in_app": true,
"push": false
},
"enabled": true
},
"workflows": [
{
"channels": {"in_app": true, "push": false},
"enabled": true,
"workflow": {
"identifier": "product",
"name": "product"
}
},
{
"channels": {"in_app": true, "push": true},
"enabled": true,
"workflow": {
"identifier": "promotional",
"name": "promotional"
}
}
]
}
}
}

Critical workflows (system, transactional) are hidden from this response by Novu.

Update Preferences

Toggle channel(s) for a specific workflow or globally.

POST /api/v1/notifications/update-preferences
{
"channels": {"push": false},
"workflowId": "promotional"
}

Omit workflowId to apply globally. Response returns the full updated preferences (same structure as GetPreferences).

Topics

Topics enable pub/sub-style fan-out delivery.

Create a Topic

POST /api/v1/notifications/manage/create-topic
{
"topicKey": "weekly-updates",
"name": "Weekly Updates"
}

Add/Remove Subscribers

POST /api/v1/notifications/manage/add-subscribers-to-topic
{
"topicKey": "weekly-updates",
"userIds": ["user-1", "user-2"]
}

Up to 100 subscribers per call.

POST /api/v1/notifications/manage/remove-subscribers-from-topic
{
"topicKey": "weekly-updates",
"userIds": ["user-1"]
}

Send to Topic

POST /api/v1/notifications/manage/send-to-topic
{
"workflowId": "push-notification",
"topicKey": "weekly-updates",
"payload": {
"title": "Weekly Update",
"body": "Your weekly health summary is ready"
},
"excludeUserId": "user-admin"
}

List Topic Subscribers

POST /api/v1/notifications/manage/list-topic-subscribers
{
"topicKey": "weekly-updates",
"page": 1,
"pageSize": 50
}

Check Subscription

POST /api/v1/notifications/manage/check-topic-subscription
{
"topicKey": "weekly-updates",
"userId": "user-1"
}

Digest / Batching

Digest behavior is configured in the Novu workflow itself (digest step). This RPC triggers a workflow that has digest enabled.

POST /api/v1/notifications/manage/send-with-digest
{
"workflowId": "activity-digest",
"userId": "user-1",
"payload": {
"title": "Activity Update",
"body": "New activity in your coaching plan"
},
"transactionId": "digest-event-123"
}

Cancel a digest event:

POST /api/v1/notifications/manage/cancel-digest-event
{
"transactionId": "digest-event-123"
}

Subscriber Management

Create Subscriber

POST /api/v1/notifications/manage/create-subscriber
{
"subscriberId": "user-1",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@example.com",
"phone": "+1234567890",
"locale": "en-US"
}

Get / Update / Delete Subscriber

Get and delete use empty request bodies (user derived from auth headers):

POST /api/v1/notifications/get-subscriber
POST /api/v1/notifications/delete-subscriber

Update subscriber profile data:

POST /api/v1/notifications/update-subscriber-data
{
"data": {
"email": "jane.updated@example.com",
"locale": "en-GB"
}
}

List Subscribers

POST /api/v1/notifications/manage/list-subscribers
{
"page": 1,
"pageSize": 50
}

Workflow Management

Workflows are managed as opaque Novu JSON objects. The API passes workflow definitions through without interpretation.

Create Workflow

POST /api/v1/notifications/manage/create-workflow
{
"workflow": {
"name": "Welcome Notification",
"description": "Sent when a user completes onboarding",
"__source": "editor",
"steps": [
{
"name": "In-App Step",
"type": "in_app",
"controlValues": {
"body": "Welcome to your health coaching journey!"
}
}
]
}
}

Response: Returns the created workflow object from Novu.

Update / Get / List / Delete Workflow

POST /api/v1/notifications/manage/update-workflow
POST /api/v1/notifications/manage/get-workflow
POST /api/v1/notifications/manage/list-workflows
POST /api/v1/notifications/manage/delete-workflow

All return opaque Novu workflow JSON.

Provider Configuration

Configure external delivery providers (FCM, APNS, SendGrid, etc.).

POST /api/v1/notifications/manage/configure-provider
{
"provider": "PROVIDER_TYPE_FCM",
"credentials": {
"serviceAccount": "{...}"
},
"active": true
}
Upsert Behavior

configure-provider uses upsert semantics: if an active integration already exists for the specified provider type, it updates the existing integration in place (preserving its ID and subscriber linkages). If no active integration exists, a new one is created.

This prevents duplicate integrations and ensures existing device registrations continue to work after credential updates. If multiple active integrations exist for the same provider type, the call returns 409 Conflict — resolve the duplicates manually via the Novu dashboard.

POST /api/v1/notifications/manage/get-providers

Promotion (Dev → Prod)

Manage promotion of notification changes from development to production.

POST /api/v1/notifications/manage/get-pending-changes
POST /api/v1/notifications/manage/promote-change
POST /api/v1/notifications/manage/promote-all-changes

Activity & Delivery Status

Get Delivery Status

Returns the raw Novu activity data for a notification.

POST /api/v1/notifications/manage/get-delivery-status
{
"transactionId": "txn_abc123"
}

Response: Returns {"activity": {...}} with raw Novu data.

Get Notification Activity

Query delivery history with channel and time filtering.

POST /api/v1/notifications/manage/get-notification-activity
{
"page": 1,
"pageSize": 50,
"channels": ["in_app", "push"],
"from": "2026-03-01T00:00:00Z",
"to": "2026-03-23T23:59:59Z"
}

Response: Returns {"entries": [...], "hasMore": true} with raw Novu activity entries.

RPC Summary

User-Facing (11 RPCs)

EndpointDescription
register-push-deviceRegister FCM token
unregister-push-deviceRemove FCM token
get-registered-channelsList available channels
get-inbox-sessionGet Novu session for WebSocket
get-inbox-feedPaginated inbox messages
get-inbox-unseen-countUnseen/unread counts
mark-inbox-messageMark single message status
mark-all-inbox-messagesBulk mark messages
delete-inbox-messageDelete inbox message
get-preferencesGet notification preferences
update-preferencesUpdate notification preferences

Admin/Management (29 RPCs)

EndpointDescription
manage/send-notificationTrigger workflow for a user
manage/send-bulk-notificationTrigger for multiple users
manage/cancel-notificationCancel pending notification
manage/send-to-topicSend to topic subscribers
manage/send-with-digestTrigger digest workflow
manage/cancel-digest-eventCancel digest event
manage/create-topicCreate topic
manage/delete-topicDelete topic
manage/add-subscribers-to-topicAdd subscribers to topic
manage/remove-subscribers-from-topicRemove from topic
manage/list-topic-subscribersList topic subscribers
manage/check-topic-subscriptionCheck subscription
manage/create-subscriberCreate subscriber
manage/get-subscriberGet subscriber details
manage/update-subscriber-dataUpdate subscriber data
manage/delete-subscriberDelete subscriber
manage/list-subscribersList subscribers
manage/create-workflowCreate workflow
manage/update-workflowUpdate workflow
manage/get-workflowGet workflow details
manage/list-workflowsList workflows
manage/delete-workflowDelete workflow
manage/configure-providerConfigure delivery provider
manage/get-providersList active providers
manage/get-pending-changesList pending promotions
manage/promote-changePromote single change
manage/promote-all-changesPromote all changes
manage/get-delivery-statusGet delivery status
manage/get-notification-activityQuery delivery history