Skip to main content

Notifications

Nekzus provides a comprehensive notification system for pushing real-time alerts and messages to connected devices. The system supports both immediate delivery via WebSocket and queued delivery for offline devices.


Overview​

The notifications system enables:

  • Real-time delivery - Instant WebSocket notifications to connected clients
  • Offline queuing - Automatic queueing for devices that are not currently connected
  • Targeted delivery - Send notifications to specific devices or broadcast to all
  • Activity persistence - Activity notifications are stored in the activity log
  • Queue management - Web UI and API for managing pending notifications
  • Retry mechanism - Automatic and manual retry for failed deliveries

Architecture​

Notification Flow​

d2

Components​

ComponentDescription
Webhook EndpointsHTTP endpoints for external integrations
WebSocket ManagerManages real-time connections and message delivery
Notification QueueSQLite-backed queue for offline device notifications
Activity TrackerPersists activity events for the dashboard

Webhook Endpoints​

POST /api/v1/webhooks/activity​

Creates an activity event that is displayed in the activity feed and optionally sent to devices.

Authentication: API Key or JWT

FieldTypeRequiredDescription
messagestringYesThe notification message
iconstringNoIcon name (default: "Bell")
iconClassstringNoIcon style: success, warning, danger, info
detailsstringNoAdditional details
deviceIdsarrayNoTarget device IDs (empty = broadcast to all)
curl -X POST https://localhost:8443/api/v1/webhooks/activity \
-H "X-API-Key: nekzus_abc123..." \
-H "Content-Type: application/json" \
-d '{
"message": "Deployment completed",
"icon": "CheckCircle",
"iconClass": "success",
"details": "Version 2.0.0 deployed to production",
"deviceIds": ["device-abc123"]
}'

Behavior:

  • Creates an ActivityEvent with type webhook.activity
  • Persists the event to the activity tracker (visible in dashboard)
  • Broadcasts via WebSocket to all connected clients (if no deviceIds specified)
  • For targeted delivery, sends only to specified devices
  • Queues notifications for offline devices (30-day TTL, 5 max retries)

POST /api/v1/webhooks/notify​

Sends an arbitrary notification payload via WebSocket without persisting to the activity log.

Authentication: API Key or JWT

FieldTypeRequiredDescription
typestringNoCustom notification type
dataobjectNoArbitrary JSON payload
deviceIdsarrayNoTarget device IDs (empty = broadcast to all)
curl -X POST https://localhost:8443/api/v1/webhooks/notify \
-H "X-API-Key: nekzus_abc123..." \
-H "Content-Type: application/json" \
-d '{
"type": "custom_alert",
"data": {
"alertType": "cpu_usage",
"threshold": 90,
"current": 95,
"message": "CPU usage critical"
},
"deviceIds": ["device-abc123", "device-def456"]
}'

Behavior:

  • Sends the payload directly via WebSocket (not persisted to activity log)
  • Supports broadcast (empty deviceIds) or targeted delivery
  • Queues notifications for offline devices when deviceIds is specified

Notification Queue Management​

The notification queue stores pending notifications for offline devices. These endpoints allow administrators to view, retry, and dismiss queued notifications.

GET /api/v1/notifications​

Lists notifications with optional filtering and pagination.

Authentication: IP-based (local) or JWT

ParameterTypeDefaultDescription
statusquery-Filter: pending, delivered, failed, dismissed
device_idquery-Filter by device ID
typequery-Filter by notification type
limitquery50Max results (max: 200)
offsetquery0Pagination offset
curl "https://localhost:8443/api/v1/notifications?status=pending&limit=10"

GET /api/v1/notifications/stats​

Returns queue statistics.

Authentication: IP-based (local) or JWT

curl https://localhost:8443/api/v1/notifications/stats

GET /api/v1/notifications/stale​

Returns stale notifications grouped by device. A notification is considered stale if it has been pending for more than 24 hours.

Authentication: IP-based (local) or JWT

curl https://localhost:8443/api/v1/notifications/stale

DELETE /api/v1/notifications/{id}​

Dismisses a single notification. The notification is marked as dismissed and will not be delivered.

Authentication: IP-based (local) or JWT

curl -X DELETE https://localhost:8443/api/v1/notifications/123

DELETE /api/v1/notifications/device/{deviceId}​

Dismisses all pending notifications for a specific device.

Authentication: IP-based (local) or JWT

curl -X DELETE https://localhost:8443/api/v1/notifications/device/device-abc123

POST /api/v1/notifications/{id}/retry​

Resets a notification status to pending for retry delivery.

Authentication: IP-based (local) or JWT

curl -X POST https://localhost:8443/api/v1/notifications/123/retry

POST /api/v1/notifications/retry​

Bulk retry multiple notifications.

Authentication: IP-based (local) or JWT

curl -X POST https://localhost:8443/api/v1/notifications/retry \
-H "Content-Type: application/json" \
-d '{"ids": [123, 124, 125]}'

DELETE /api/v1/notifications/delivered​

Clears all delivered notifications from the queue. This is useful for cleanup after confirming notifications were received.

Authentication: IP-based (local) or JWT

curl -X DELETE https://localhost:8443/api/v1/notifications/delivered

WebSocket Message Types​

Notifications are delivered via WebSocket using the following message structure:

Activity Notification (from webhook/activity)​

{
"type": "webhook",
"data": {
"id": "webhook-1736949720000000",
"type": "webhook.activity",
"icon": "CheckCircle",
"iconClass": "success",
"message": "Deployment completed",
"details": "Version 2.0.0 deployed",
"timestamp": 1736949720000
},
"timestamp": "2025-01-15T10:30:00Z"
}

Custom Notification (from webhook/notify)​

{
"type": "webhook",
"data": {
"type": "custom_alert",
"data": {
"alertType": "cpu_usage",
"threshold": 90,
"current": 95,
"message": "CPU usage critical"
},
"deviceIds": ["device-abc123"]
},
"timestamp": "2025-01-15T10:30:00Z"
}

Notification Statuses​

StatusDescription
pendingAwaiting delivery to device
deliveredSuccessfully delivered via WebSocket
failedDelivery failed (will retry if retries remain)
dismissedManually dismissed by administrator

Queue Configuration​

Notifications are queued with the following default settings:

SettingValueDescription
TTL30 daysTime-to-live for queued notifications
Max Retries5Maximum delivery attempts
Stale Threshold24 hoursTime after which pending notifications are marked stale

Frontend Integration​

NotificationsTab Component​

The web dashboard includes a NotificationsTab component that provides:

  • Statistics overview - Pending, delivered, and failed counts
  • Stale warning - Alert when devices have notifications pending > 24 hours
  • Status filtering - Filter by pending, delivered, failed, or dismissed
  • Bulk operations - Retry all failed notifications
  • Individual actions - Retry or dismiss specific notifications

Real-time Updates​

The frontend subscribes to WebSocket events to receive notifications in real-time:

// Example: Listening for webhook notifications
websocket.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'webhook') {
// Handle activity event
if (message.data.type === 'webhook.activity') {
showActivityNotification(message.data);
}
// Handle custom notification
else if (message.data.type) {
handleCustomNotification(message.data);
}
}
};

Icon Reference​

The icon field supports icon names from the Lucide icon library:

IconUse Case
BellDefault notifications
CheckCircleSuccess messages
AlertTriangleWarnings
AlertCircleErrors
InfoInformational
TargetTargeted actions
RadioBroadcast messages
DatabaseStorage/data events
RefreshUpdate notifications

Icon Classes​

The iconClass field controls the color styling:

ClassColorUse Case
successGreenSuccessful operations
warningYellow/OrangeWarnings, attention needed
dangerRedErrors, critical alerts
infoBlueInformational messages
(none)DefaultNeutral notifications

Integration Examples​

CI/CD Pipeline Notification​

Send deployment notifications from your CI/CD pipeline:

# In your deployment script
curl -X POST https://nekzus.local:8443/api/v1/webhooks/activity \
-H "X-API-Key: ${NEKZUS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"message": "Deployment to production completed",
"icon": "CheckCircle",
"iconClass": "success",
"details": "Commit: '"${GIT_SHA}"' | Duration: '"${DEPLOY_TIME}"'s"
}'

Monitoring Alert Integration​

Forward alerts from your monitoring system:

# Prometheus Alertmanager webhook receiver
curl -X POST https://nekzus.local:8443/api/v1/webhooks/notify \
-H "X-API-Key: ${NEKZUS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"type": "prometheus_alert",
"data": {
"alertname": "HighCPUUsage",
"severity": "warning",
"instance": "server-01",
"value": 95,
"summary": "CPU usage is above 90%"
}
}'

Backup Completion Notification​

Notify specific devices when backups complete:

# Send to specific admin devices
curl -X POST https://nekzus.local:8443/api/v1/webhooks/activity \
-H "X-API-Key: ${NEKZUS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"message": "Daily backup completed successfully",
"icon": "Database",
"iconClass": "success",
"details": "Size: 2.4GB | Duration: 45s",
"deviceIds": ["admin-device-1", "admin-device-2"]
}'

JavaScript/Node.js Example​

const axios = require('axios');

async function sendNotification(message, options = {}) {
const payload = {
message,
icon: options.icon || 'Bell',
iconClass: options.iconClass || '',
details: options.details || '',
deviceIds: options.deviceIds || []
};

try {
const response = await axios.post(
'https://nekzus.local:8443/api/v1/webhooks/activity',
payload,
{
headers: {
'X-API-Key': process.env.NEKZUS_API_KEY,
'Content-Type': 'application/json'
}
}
);
console.log('Notification sent:', response.data.eventId);
return response.data;
} catch (error) {
console.error('Failed to send notification:', error.message);
throw error;
}
}

// Usage
sendNotification('Build completed', {
icon: 'CheckCircle',
iconClass: 'success',
details: 'Build #1234 finished in 5m 32s'
});

Python Example​

import requests
import os

def send_notification(message, icon='Bell', icon_class='', details='', device_ids=None):
"""Send a notification via Nekzus webhook."""
payload = {
'message': message,
'icon': icon,
'iconClass': icon_class,
'details': details,
'deviceIds': device_ids or []
}

response = requests.post(
'https://nekzus.local:8443/api/v1/webhooks/activity',
json=payload,
headers={
'X-API-Key': os.environ['NEKZUS_API_KEY'],
'Content-Type': 'application/json'
},
verify=False # Set to True in production with proper certs
)

response.raise_for_status()
return response.json()

# Usage
result = send_notification(
message='Task completed',
icon='CheckCircle',
icon_class='success',
details='Processed 1,000 records in 30 seconds'
)
print(f"Event ID: {result['eventId']}")

Go Example​

package main

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)

type ActivityPayload struct {
Message string `json:"message"`
Icon string `json:"icon,omitempty"`
IconClass string `json:"iconClass,omitempty"`
Details string `json:"details,omitempty"`
DeviceIDs []string `json:"deviceIds,omitempty"`
}

func sendNotification(payload ActivityPayload) error {
body, err := json.Marshal(payload)
if err != nil {
return err
}

req, err := http.NewRequest(
"POST",
"https://nekzus.local:8443/api/v1/webhooks/activity",
bytes.NewReader(body),
)
if err != nil {
return err
}

req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("NEKZUS_API_KEY"))

resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

return nil
}

func main() {
err := sendNotification(ActivityPayload{
Message: "Service restarted",
Icon: "Refresh",
IconClass: "info",
Details: "All services are now running",
})
if err != nil {
fmt.Printf("Error: %v\n", err)
}
}

Troubleshooting​

Notifications Not Received​

  1. Check WebSocket connection - Ensure the device is connected via WebSocket
  2. Verify device ID - Confirm the deviceIds array contains valid device IDs
  3. Check queue - Use /api/v1/notifications to see if notification is queued
  4. Review logs - Check server logs for delivery errors

Stale Notifications​

Stale notifications indicate devices that have been offline for extended periods:

  1. Check if the device is actually offline
  2. Consider dismissing notifications for inactive devices
  3. Review device activity in the Devices tab

Queue Growing​

If the notification queue keeps growing:

  1. Identify offline devices with /api/v1/notifications/stale
  2. Dismiss notifications for devices that are no longer active
  3. Consider revoking inactive device access
  4. Review TTL settings if notifications expire too slowly

API Key Authentication Fails​

  1. Verify API key is not revoked
  2. Check key has write:* scope
  3. Ensure key is sent in X-API-Key header
  4. Confirm key format: nekzus_<64-character-hex>