Skip to main content

Overview

The WebSocket notification endpoint enables real-time, bidirectional communication between the client and server for receiving notifications about product expiry and other events. Once connected, the server can push notifications to the client without requiring polling.
WebSocket connections require authentication via the access_token query parameter. The connection will be automatically closed if authentication fails.

Connection URL

ws://your-domain/api/ws/notification?access_token=YOUR_ACCESS_TOKEN

Authentication

access_token
string
required
JWT access token for authenticating the WebSocket connection. Pass this as a query parameter in the connection URL.

Connection Flow

1. Establishing Connection

When you connect to the WebSocket, you’ll receive a confirmation message:
type
string
Message type: CONNECTION_ESTABLISHED
message
string
Confirmation message: “Notification WebSocket connected”
userId
string
The authenticated user’s ID extracted from the access token
Example Connection Response:
{
  "type": "CONNECTION_ESTABLISHED",
  "message": "Notification WebSocket connected",
  "userId": "user-uuid-here"
}

2. Receiving Notifications

Once connected, the server will push notifications to the client in real-time. Notifications follow this structure:
id
string
Unique notification ID
message
string
Human-readable notification message
type
string
Notification type: info, warning, or error
productName
string
Name of the product related to the notification
created_at
string
ISO 8601 timestamp when the notification was created
Example Notification:
{
  "id": "notif-uuid-123",
  "message": "Product expires in 2 days",
  "type": "warning",
  "productName": "Organic Milk",
  "created_at": "2026-03-04T10:30:00"
}

3. Client-to-Server Messages

Clients can send messages to the server for various actions:

Mark Notification as Read

{
  "action": "mark_read",
  "id": "notification-id"
}

Ping (Keep-Alive)

Send the string "PING" to receive a pong response: Response:
{
  "type": "pong"
}
Regular ping messages can help keep the connection alive and detect disconnections.

Error Handling

Authentication Failure

If no access token is provided, the connection will be closed immediately with:
  • Code: 1008 (Policy Violation)
  • Reason: “Access token required”

Disconnection

The WebSocket connection may be closed due to:
  • Network issues
  • Server shutdown
  • Client disconnection
  • Authentication token expiration
The server will automatically clean up the connection and remove the user from the active connections pool.

Example Usage

JavaScript/TypeScript

// Establish WebSocket connection
const accessToken = "your-jwt-token";
const ws = new WebSocket(`ws://localhost:8000/api/ws/notification?access_token=${accessToken}`);

// Connection opened
ws.onopen = (event) => {
  console.log("WebSocket connected");
};

// Listen for messages
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  
  if (data.type === "CONNECTION_ESTABLISHED") {
    console.log("Connected as user:", data.userId);
  } else {
    // Handle notification
    console.log("New notification:", data);
    
    // Mark as read
    ws.send(JSON.stringify({
      action: "mark_read",
      id: data.id
    }));
  }
};

// Handle errors
ws.onerror = (error) => {
  console.error("WebSocket error:", error);
};

// Connection closed
ws.onclose = (event) => {
  console.log("WebSocket closed:", event.code, event.reason);
};

// Keep-alive ping (every 30 seconds)
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send("PING");
  }
}, 30000);

Python

import asyncio
import websockets
import json

async def connect_notifications(access_token):
    uri = f"ws://localhost:8000/api/ws/notification?access_token={access_token}"
    
    async with websockets.connect(uri) as websocket:
        # Receive connection confirmation
        response = await websocket.recv()
        print(f"Connected: {response}")
        
        # Listen for notifications
        async for message in websocket:
            data = json.loads(message)
            print(f"Notification received: {data}")
            
            # Mark as read
            if "id" in data:
                await websocket.send(json.dumps({
                    "action": "mark_read",
                    "id": data["id"]
                }))

# Run the client
asyncio.run(connect_notifications("your-jwt-token"))

Best Practices

  1. Reconnection Logic: Implement automatic reconnection with exponential backoff for production applications
  2. Keep-Alive: Send periodic PING messages to maintain the connection
  3. Error Handling: Always handle connection errors and unexpected disconnections gracefully
  4. Token Refresh: Monitor token expiration and reconnect with a fresh token when needed
  5. Message Acknowledgment: Mark notifications as read to prevent duplicate processing

Build docs developers (and LLMs) love