Skip to main content
Version: 0.9.0 (Latest)

🛣️ Chat Routes

Chat routes provide pre-configured HTTP endpoints for chat management operations in Nodeblocks applications. These routes combine handlers, validators, and middleware to create complete API endpoints with proper authentication, authorization, and error handling.


🎯 Overview

Chat routes are designed to:

  • Provide complete API endpoints for chat management operations
  • Combine handlers with validators for secure operations
  • Include authentication and authorization checks
  • Support functional composition patterns
  • Handle logging and error management automatically

📋 Route Structure

Each chat route follows a consistent pattern:

  • HTTP Method: Defines the operation type (GET, POST, PATCH, DELETE)
  • Path: Specifies the endpoint URL with parameters
  • Handler: Composed function chain for business logic
  • Validators: Authentication and authorization checks

🔧 Available Chat Routes

Channel Routes

createChatChannelRoute

Creates a new channel and returns the created resource.

Purpose: Handles channel creation with full resource retrieval

Route Details:

  • Method: POST
  • Path: /channels
  • Authentication: Required (Bearer token)

Handlers: createChatChannel, getChatChannelById, createChatChannelTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'ownerId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.createChatChannelRoute);

findChatChannelsRoute

Retrieves all channels with normalized list format.

Purpose: Lists channels with pagination

Route Details:

  • Method: GET
  • Path: /channels
  • Authentication: Required (Bearer token)

Handlers: findChatChannels, normalizeChatChannelsListTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), isSelf(['params', 'requestQuery', 'ownerId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.findChatChannelsRoute);

getChatChannelRoute

Retrieves a specific channel by ID.

Purpose: Fetches channel data

Route Details:

  • Method: GET
  • Path: /channels/:channelId
  • Authentication: Required (Bearer token)

Handlers: getChatChannelById, normalizeChatChannelTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']), hasSubscription(['params', 'requestParams', 'channelId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChatChannelRoute);

updateChatChannelRoute

Updates an existing channel and returns the updated resource.

Purpose: Modifies channel data with access control

Route Details:

  • Method: PATCH
  • Path: /channels/:channelId
  • Authentication: Required (Bearer token)

Handlers: updateChatChannel, getChatChannelById, normalizeChatChannelTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.updateChatChannelRoute);

deleteChatChannelRoute

Deletes a channel by ID.

Purpose: Removes channel with access control

Route Details:

  • Method: DELETE
  • Path: /channels/:channelId
  • Authentication: Required (Bearer token)

Handlers: deleteChatChannel, deleteChatChannelTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.deleteChatChannelRoute);

getChannelMessagesRoute

Retrieves all chat messages for a specific channel via GET /channels/:channelId/messages.

Purpose: Fetches all messages belonging to a specific channel with pagination support

Route Details:

  • Method: GET
  • Path: /channels/:channelId/messages
  • Authentication: Required (Bearer token)

Blocks: getChannelMessagesByChannelId

Terminators: Built-in success/error mapping via orThrow with 200 status code

Validators:

Response (200 OK): Array of message objects

Error Responses:

  • 401: User is not authenticated
  • 403: User is not subscribed to the channel
  • 404: Channel does not exist
  • 500: Database operation failed

Handler Process:

  1. Validates user authentication and channel subscription
  2. Retrieves all messages for the specified channel
  3. Applies pagination if query parameters provided
  4. Returns array of messages with 200 status

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChannelMessagesRoute);

// Client usage:
const response = await fetch('/api/channels/channel-123/messages', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});

if (response.ok) {
const messages = await response.json();
console.log('Channel messages:', messages);
}

getChatChannelIconUploadUrlRoute

Generates signed upload URL for chat channel icon via GET /channels/:channelId/icon-upload-url.

Purpose: Provides pre-signed URL for uploading chat channel icon images with proper authentication and authorization.

Route Details:

  • Method: GET
  • Path: /channels/:channelId/icon-upload-url
  • Authentication: Required (Bearer token)

Blocks: generateChatChannelIconUploadUrl Terminators: Built-in success/error mapping via orThrow with 200 status code

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsChannel(['params', 'requestParams', 'channelId']))

Response (200 OK):

{
"objectId": "string",
"url": "string"
}

Query Parameters:

  • contentType: string - MIME type of the file to be uploaded (e.g., 'image/png')
  • contentLength: number - Size of the file in bytes (max 10MB)

Error Responses:

  • 400 Bad Request: Invalid query parameters (file size too large, invalid content type)
  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: User lacks admin privileges and doesn't own the channel
  • 500 Internal Server Error: File storage service error

Handler Process:

  1. Validates authentication and authorization (admin or channel owner)
  2. Validates query parameters (contentType, contentLength)
  3. Generates UUID objectId with file extension
  4. Creates signed upload URL using file storage driver
  5. Returns objectId and signed URL for upload

Authorization Notes:

  • Requires authentication
  • Accessible by admins or channel owners
  • Uses some validator to allow either admin access or channel ownership

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChatChannelIconUploadUrlRoute);

// Client usage:
const response = await fetch('/api/channels/channel-123/icon-upload-url?contentType=image/png&contentLength=1024000', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});

if (response.ok) {
const { objectId, url } = await response.json();
// Use url to upload the file
// Store objectId for later reference
}

Subscription Routes

createChatSubscriptionRoute

Creates a new subscription and returns the created resource.

Purpose: Handles subscription creation with full resource retrieval

Route Details:

  • Method: POST
  • Path: /subscriptions
  • Authentication: Required (Bearer token)

Handlers: createChatSubscription, getChatSubscriptionById, createChatSubscriptionTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), isSelf(['params', 'requestBody', 'subscribedId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.createChatSubscriptionRoute);

findChatSubscriptionsRoute

Retrieves all subscriptions with normalized list format.

Purpose: Lists subscriptions with pagination

Route Details:

  • Method: GET
  • Path: /subscriptions
  • Authentication: Required (Bearer token)

Handlers: findChatSubscriptions, normalizeChatSubscriptionsListTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), ownsChannel(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'subscribedId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.findChatSubscriptionsRoute);

getChatSubscriptionRoute

Retrieves a specific subscription by ID.

Purpose: Fetches subscription data

Route Details:

  • Method: GET
  • Path: /subscriptions/:subscriptionId
  • Authentication: Required (Bearer token)

Handlers: getChatSubscriptionById, normalizeChatSubscriptionTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChatSubscriptionRoute);

deleteChatSubscriptionRoute

Deletes a subscription by ID.

Purpose: Removes subscription

Route Details:

  • Method: DELETE
  • Path: /subscriptions/:subscriptionId
  • Authentication: Required (Bearer token)

Handlers: deleteChatSubscription, deleteChatSubscriptionTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsSubscription(['params', 'requestParams', 'subscriptionId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.deleteChatSubscriptionRoute);

Message Routes

createChatMessageRoute

Creates a new message and returns the created resource.

Purpose: Handles message creation with full resource retrieval

Route Details:

  • Method: POST
  • Path: /messages
  • Authentication: Required (Bearer token)

Handlers: createChatMessage, getChatMessageById, createChatMessageTerminator

Validators: isAuthenticated, isSelf(['params', 'requestBody', 'senderId']), hasSubscription(['params', 'requestBody', 'channelId'])

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.createChatMessageRoute);

findChatMessagesRoute

Retrieves all messages with normalized list format.

Purpose: Lists messages with pagination

Route Details:

  • Method: GET
  • Path: /messages
  • Authentication: Required (Bearer token)

Handlers: findChatMessages, normalizeChatMessagesListTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), hasSubscription(['params', 'requestQuery', 'channelId']), isSelf(['params', 'requestQuery', 'senderId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.findChatMessagesRoute);

getChatMessageRoute

Retrieves a specific message by ID.

Purpose: Fetches message data

Route Details:

  • Method: GET
  • Path: /messages/:messageId
  • Authentication: Required (Bearer token)

Handlers: getChatMessageById, normalizeChatMessageTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChatMessageRoute);

updateChatMessageRoute

Updates an existing message and returns the updated resource.

Purpose: Modifies message data with owner-only access control

Route Details:

  • Method: PATCH
  • Path: /messages/:messageId
  • Authentication: Required (Bearer token)

Handlers: updateChatMessage, getChatMessageById, normalizeChatMessageTerminator

Validators: isAuthenticated, ownsMessage(['params', 'requestParams', 'messageId'])

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.updateChatMessageRoute);

deleteChatMessageRoute

Deletes a message by ID.

Purpose: Removes message with access control

Route Details:

  • Method: DELETE
  • Path: /messages/:messageId
  • Authentication: Required (Bearer token)

Handlers: deleteChatMessage, deleteChatMessageTerminator

Validators: isAuthenticated, some(checkIdentityType(['admin']), ownsMessage(['params', 'requestParams', 'messageId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.deleteChatMessageRoute);

getChatMessageAttachmentUploadUrlRoute

Generates file upload URL for chat message attachments via GET /messages/:messageId/attachment-upload-url.

Purpose: Provides secure, time-limited URLs for uploading attachments to chat messages

Route Details:

  • Method: GET
  • Path: /messages/:messageId/attachment-upload-url
  • Authentication: Required (Bearer token)

Blocks: generateChatMessageAttachmentUploadUrl

Terminators: orThrow

Validators: isAuthenticated, ownsMessage

Query Parameters:

  • contentType: string (required) - MIME type of the file to upload (validated against safe types)
  • contentLength: integer (required) - Size of the file in bytes (max 10MB)

Response: Object with objectId and signed upload URL

Response Structure:

{
objectId: string; // Unique identifier for the uploaded file
url: string; // Pre-signed URL for uploading the file
}

Error Responses:

  • 400 - Invalid content type or file size exceeds limit
  • 401 - Not authenticated
  • 403 - Not authorized to upload to this message
  • 500 - FileStorageServiceError or ChatMessageBlockError

Handler Process:

  1. Validates authentication and message ownership
  2. Validates content type and size via schema
  3. Generates unique object ID
  4. Creates signed upload URL with proper file extension
  5. Returns objectId and URL to client

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChatMessageAttachmentUploadUrlRoute);

// Client-side request:
const messageId = 'message123';
const response = await fetch(
`/api/messages/${messageId}/attachment-upload-url?contentType=image/png&contentLength=1000000`,
{
headers: {
'Authorization': 'Bearer <token>'
}
}
);

const { objectId, url } = await response.json();

// Upload file to signed URL
await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'image/png'
},
body: fileData
});

// Store objectId with message for later retrieval

Security Features:

  • Excludes dangerous MIME types (executables, scripts, archives)
  • Enforces file size limits (10MB max)
  • Requires message ownership validation
  • Time-limited signed URLs

createChatMessageAttachmentRoute

Creates a new chat message attachment via POST /messages/:messageId/attachments.

Purpose: Adds a file attachment to an existing message with validation and automatic entity generation

Route Details:

  • Method: POST
  • Path: /messages/:messageId/attachments
  • Authentication: Required (Bearer token)

Blocks: createChatMessageAttachment, getChatMessageAttachmentById

Terminators: orThrow

Validators: isAuthenticated, ownsMessage

Request Body:

{
"objectId": "550e8400-e29b-41d4-a716-446655440000",
"type": "image/png"
}

Response: Created attachment with base entity fields (status 201)

Response Structure:

{
objectId: string; // UUID reference to uploaded file
type: string; // MIME type
id: string; // Generated attachment ID
createdAt: string; // ISO datetime
updatedAt: string; // ISO datetime
}

Error Responses:

  • 400 - Invalid request body (missing objectId or type)
  • 401 - Not authenticated
  • 403 - Not authorized to modify this message
  • 404 - Message not found or attachment not found
  • 500 - ChatMessageUnexpectedDBError or ChatMessageBlockError

Handler Process:

  1. Validates authentication and message ownership
  2. Validates objectId (UUID) and type via schema
  3. Creates attachment with base entity fields
  4. Pushes attachment to message's attachments array
  5. Retrieves and returns created attachment

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.createChatMessageAttachmentRoute);

// Client-side request:
const response = await fetch(`/api/messages/${messageId}/attachments`, {
method: 'POST',
headers: {
'Authorization': 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
objectId: '550e8400-e29b-41d4-a716-446655440000',
type: 'image/png'
})
});

const attachment = await response.json();
// attachment has id, createdAt, updatedAt fields

Key Features:

  • Automatic base entity field generation for attachments
  • Message ownership validation
  • Atomic MongoDB $push operation
  • Returns complete attachment with generated fields
  • Full error handling for all failure scenarios

deleteChatMessageAttachmentRoute

Deletes a chat message attachment via DELETE /messages/:messageId/attachments/:attachmentId.

Purpose: Removes a file attachment from an existing message and deletes it from storage

Route Details:

  • Method: DELETE
  • Path: /messages/:messageId/attachments/:attachmentId
  • Authentication: Required (Bearer token)

Blocks: deleteChatMessageAttachment

Terminators: orThrow

Validators: isAuthenticated, some (checks checkIdentityType for admin OR ownsMessage)

Response: No content (status 204) on success

Error Responses:

  • 401 - Not authenticated
  • 403 - Not authorized to modify this message (not admin or owner)
  • 404 - Message not found or attachment not found
  • 500 - ChatMessageUnexpectedDBError, ChatMessageBlockError, or FileStorageServiceError

Handler Process:

  1. Validates authentication and authorization (admin or message owner)
  2. Validates messageId and attachmentId via schema
  3. Removes attachment from message's attachments array using $pull
  4. Updates message updatedAt timestamp
  5. Deletes physical file from storage
  6. Returns 204 No Content on success

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.deleteChatMessageAttachmentRoute);

// Client-side request:
const response = await fetch(`/api/messages/${messageId}/attachments/${attachmentId}`, {
method: 'DELETE',
headers: {
'Authorization': 'Bearer <token>'
}
});

// response.status === 204 on success

Key Features:

  • Atomic MongoDB $pull operation
  • Returns document before update to retrieve attachment details
  • Deletes physical file from storage using objectId and type
  • Automatic message timestamp update
  • Admin or owner authorization check
  • Full error handling for all failure scenarios

streamChatMessagesRoute

Streams chat messages in real-time via WebSocket at /messages/listen.

Purpose: Enables real-time message streaming to clients using WebSocket and MongoDB change streams

Route Details:

  • Method: WebSocket (implicit)
  • Path: /messages/listen
  • Protocol: ws
  • Authentication: Currently disabled (TODO: enable when WebSocket IP address format is fixed)

Handlers: streamChatMessages, normalizeChatMessageStream

Validators: Currently commented out due to WebSocket IP address format issues:

  • isAuthenticated() - Will validate Bearer token authentication
  • hasSubscription(['params', 'requestQuery', 'channelId']) - Will verify user is subscribed to channel

Query Parameters:

  • channelId: string (required) - Channel ID to stream messages from

Response: Stream of normalized chat messages as they are created

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.streamChatMessagesRoute);

// Client-side WebSocket connection:
const ws = new WebSocket('ws://localhost:3000/api/messages/listen?channelId=channel123');

ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('New message:', message);
};

ws.onerror = (error) => {
console.error('WebSocket error:', error);
};

ws.onclose = () => {
console.log('WebSocket connection closed');
};

WebSocket Flow:

  1. Client establishes WebSocket connection with channelId query parameter
  2. Server validates channelId presence (schema validation)
  3. Server creates MongoDB change stream for the specified channel
  4. Server normalizes each new message (removes _id field)
  5. Server streams normalized messages to client in real-time
  6. Connection remains open until client disconnects or error occurs

Error Handling:

  • 400: Missing or invalid channelId parameter
  • 500: Failed to create MongoDB change stream

Notes:

  • Only streams new messages (insert operations)
  • Messages are normalized before transmission (MongoDB _id field removed)
  • Authentication validators are currently disabled pending WebSocket IP format fix

Message Template Routes

createChatMessageTemplateRoute

Creates a new chat message template and returns the created resource.

Purpose: Handles message template creation with full resource retrieval

Route Details:

  • Method: POST
  • Path: /message-templates
  • Authentication: Required (Bearer token)

Handlers: createChatMessageTemplate, getChatMessageTemplateById, orThrow

Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrgRole(['owner','admin'], ['params','requestBody','organizationId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.createChatMessageTemplateRoute);

getChatMessageTemplateRoute

Retrieves a chat message template by ID.

Purpose: Fetches template data with organization access control

Route Details:

  • Method: GET
  • Path: /message-templates/:messageTemplateId
  • Authentication: Required (Bearer token)

Handlers: getChatMessageTemplateById, orThrow

Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate(['owner','admin'], ['params','requestParams','messageTemplateId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.getChatMessageTemplateRoute);

updateChatMessageTemplateRoute

Updates an existing chat message template via PATCH /message-templates/:messageTemplateId.

Purpose: Modifies existing message templates with organization access control and validation

Route Details:

  • Method: PATCH
  • Path: /message-templates/:messageTemplateId
  • Authentication: Required (Bearer token)

Handlers: updateChatMessageTemplate, getChatMessageTemplateById, orThrow

Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate(['owner','admin'], ['params','requestParams','messageTemplateId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.updateChatMessageTemplateRoute);

deleteChatMessageTemplateRoute

Deletes a chat message template via DELETE /message-templates/:messageTemplateId.

Purpose: Removes existing message templates with organization access control and validation.

Route Details:

  • Method: DELETE
  • Path: /message-templates/:messageTemplateId
  • Authentication: Required (Bearer token)

Handlers: deleteChatMessageTemplate, orThrow

Validators: isAuthenticated, some(checkIdentityType(['admin']), hasOrganizationAccessToMessageTemplate(['owner','admin'], ['params','requestParams','messageTemplateId']))

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.deleteChatMessageTemplateRoute);

Response (204 No Content):

{}

Error Responses:

  • 401: Unauthorized - Invalid or missing authentication token
  • 403: Forbidden - User lacks permission to delete this message template
  • 404: Not Found - Message template does not exist
  • 500: Internal Server Error - Database operation failed

Key Features:

  • Authorization Control: Restricts access to template owners, organization admins, or system admins
  • Safe Deletion: Validates template existence before deletion
  • Atomic Operations: Uses MongoDB atomic delete operations
  • Comprehensive Error Handling: Specific error responses for different failure scenarios

findChatMessageTemplatesRoute

Lists chat message templates via GET /message-templates.

Purpose: Retrieves paginated chat message templates with data normalization and admin-only access control

Route Details:

  • Method: GET
  • Path: /message-templates
  • Authentication: Required (Bearer token)
  • Authorization: Admin only (checkIdentityType(['admin']))

Handlers: findChatMessageTemplates, normalizeDocuments, orThrow

Validators: isAuthenticated, checkIdentityType(['admin'])

Query Parameters:

ParameterTypeRequiredDefaultDescription
pagenumber1Page number for pagination
limitnumber10Number of templates per page

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.findChatMessageTemplatesRoute);

Response (200 - Success):

{
"data": [
{
"id": "template-123",
"title": "Welcome Message",
"content": "Hello, welcome to our chat!",
"organizationId": "org-456",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"hasNext": false,
"hasPrev": false,
"limit": 10,
"page": 1,
"total": 1,
"totalPages": 1
}
}
}

Error Responses:

  • 401: Unauthorized - Invalid or missing authentication token
  • 403: Forbidden - User is not an admin
  • 404: Not Found - No templates found (returns empty array)
  • 500: Internal Server Error - Database or normalization error

Key Features:

  • Pagination Support: Full pagination with metadata
  • Data Normalization: Automatic document normalization via normalizeDocuments
  • Admin Access Control: Restricted to admin users only
  • Flexible Filtering: Supports MongoDB-style query filters
  • Comprehensive Error Handling: Specific error responses for different scenarios

findChatMessageTemplatesForOrganizationRoute

Retrieves chat message templates for a specific organization via GET /organizations/:organizationId/message-templates.

Purpose: Provides organization-scoped access to message templates with proper authorization controls and data normalization

Route Details:

  • Method: GET
  • Path: /organizations/:organizationId/message-templates
  • Authentication: Required (Bearer token)
  • Authorization: Organization role-based (hasOrgRole(['owner', 'admin']))

Handlers: buildFilterToGetChatMessageTemplatesByOrganizationId, findChatMessageTemplates, normalizeDocuments, orThrow

Validators: isAuthenticated, hasOrgRole(['owner', 'admin'], ['params', 'requestParams', 'organizationId'])

Query Parameters:

ParameterTypeRequiredDefaultDescription
pagenumber1Page number for pagination
limitnumber10Number of templates per page

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.findChatMessageTemplatesForOrganizationRoute);

Response (200 - Success):

{
"data": [
{
"id": "template-123",
"title": "Welcome Message",
"content": "Hello, welcome to our organization!",
"organizationId": "org-456",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"hasNext": false,
"hasPrev": false,
"limit": 10,
"page": 1,
"total": 1,
"totalPages": 1
}
}
}

Error Responses:

  • 401: Unauthorized - Invalid or missing authentication token
  • 403: Forbidden - User lacks organization access or insufficient role permissions
  • 404: Not Found - Organization not found or no templates available
  • 500: Internal Server Error - Database or normalization error

Key Features:

  • Organization Scoping: Templates are automatically filtered by organization ID
  • Role-Based Authorization: Access restricted to organization owners and admins
  • Pagination Support: Full pagination with metadata for large template collections
  • Data Normalization: Automatic document normalization for clean API responses
  • Secure Access Control: Multi-layer validation ensuring proper permissions

upsertChatChannelReadStateRoute

Upserts or creates a chat channel read state via PUT /channels/:channelId/read-state.

Purpose: Creates or updates a read state record to track which message a user has last read in a channel

Route Details:

  • Method: PUT
  • Path: /channels/:channelId/read-state
  • Authentication: Required (Bearer token)

Blocks:

Terminators: Built-in success/error mapping via orThrow with 204 status code

Validators:

Request Body:

{
identityId: string; // required - user identity ID
lastReadMessageId: string; // required - last read message ID
}

Response (204 No Content): Empty response body on success

Error Responses:

  • 401: User is not authenticated
  • 403: User is not subscribed to the channel or identityId doesn't match authenticated user
  • 404: Channel does not exist or last read message not found
  • 500: Database operation failed

Handler Process:

  1. Finds existing read state for the channel and identity
  2. Finds the last read message by ID
  3. If read state exists, updates it with new message information
  4. If read state doesn't exist, creates a new one
  5. Returns 204 No Content on success

Usage:

import { routes } from '@nodeblocks/backend-sdk';

// Register route with Express app
app.use('/api', routes.upsertChatChannelReadStateRoute);

// Client usage:
const response = await fetch('/api/channels/channel-123/read-state', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
identityId: 'user-456',
lastReadMessageId: 'message-789'
})
});

if (response.status === 204) {
console.log('Read state upserted successfully');
}