Skip to main content
Version: 🚧 Canary

💬 Chat Service

Testing Status

The Chat Service provides a comprehensive solution for managing real-time communication features including channels, subscriptions, and messaging capabilities. This unified service combines channel management and subscription handling into a single, cohesive API.


🚀 Quickstart

import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';

const { nodeBlocksErrorMiddleware } = middlewares;
const { chatService } = services;
const { withMongo, createFileStorageDriver } = drivers;

const connectToDatabase = withMongo('mongodb://localhost:27017', 'dev', 'user', 'password');
const fileStorageDriver = createFileStorageDriver('your-project-id', 'your-bucket-name');

express()
.use(
chatService(
{
...(await connectToDatabase('identities')),
...(await connectToDatabase('chatChannels')),
...(await connectToDatabase('chatMessages')),
...(await connectToDatabase('chatChannelReadStates')),
...(await connectToDatabase('subscriptions')),
...(await connectToDatabase('organizations')), // optional
...(await connectToDatabase('chatMessageTemplates')), // optional
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
organization: {
roles: {
admin: 'admin',
member: 'member',
owner: 'owner',
},
},
},
{
fileStorageDriver, // Required for message attachment upload URLs
}
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));

📋 Endpoint Summary

Channel Operations

MethodPathDescription
POST/channelsCreate a new channel
GET/channelsList all channels
GET/channels/:channelIdGet a specific channel
GET/channels/:channelId/icon-upload-urlGenerate signed URL for channel icon upload
PATCH/channels/:channelIdUpdate a channel
DELETE/channels/:channelIdDelete a channel

Subscription Operations

MethodPathDescription
POST/subscriptionsCreate a new subscription
GET/subscriptionsList all subscriptions
GET/subscriptions/:subscriptionIdGet a specific subscription
DELETE/subscriptions/:subscriptionIdDelete a subscription

Message Operations

MethodPathDescription
POST/messagesCreate a new message
GET/messages?channelId=:channelIdList messages in a channel
GET/channels/:channelId/messagesGet all messages for a specific channel
GET/messages/:messageIdGet a specific message
GET/messages/:messageId/attachment-upload-urlGenerate signed URL for message attachment upload
POST/messages/:messageId/attachmentsCreate a new attachment for an existing message
DELETE/messages/:messageId/attachments/:attachmentIdDelete an attachment from a message
PATCH/messages/:messageIdUpdate a message
DELETE/messages/:messageIdDelete a message

Message Template Operations

MethodPathDescription
POST/message-templatesCreate a new message template
GET/message-templatesList all message templates (admin only)
GET/organizations/:organizationId/message-templatesList message templates for organization (org members)
GET/message-templates/:templateIdGet a specific message template
PATCH/message-templates/:templateIdUpdate an existing message template
DELETE/message-templates/:templateIdDelete an existing message template

Channel Read State Operations

MethodPathDescription
PUT/channels/:channelId/read-stateUpsert (create or update) a channel read state

🗄️ Entity Schemas

Channel Entity

{
"name": "string",
"ownerId": "string",
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

Field Details:

FieldTypeAuto-GeneratedRequiredDescription
namestringChannel name/title
ownerIdstringID of the identity who owns this channel
createdAtdatetimeCreation timestamp
idstringUnique identifier (UUID)
updatedAtdatetimeLast modification timestamp

Subscription Entity

{
"approved": "boolean",
"channelId": "string",
"permissions": ["string"],
"subscribedAt": "string (datetime)",
"subscribedId": "string",
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

Field Details:

FieldTypeAuto-GeneratedRequiredDescription
approvedbooleanWhether the subscription is approved
channelIdstringID of the channel being subscribed to
permissionsarrayArray of permission strings (e.g., ["read", "write"])
subscribedAtdatetimeTimestamp when subscription was created
subscribedIdstringID of the identity subscribing
createdAtdatetimeCreation timestamp
idstringUnique identifier (UUID)
updatedAtdatetimeLast modification timestamp

Message Entity

{
"channelId": "string",
"content": "string",
"senderId": "string",
"title": "string",
"attachments": [
{
"objectId": "string (UUID)",
"type": "string",
"id": "string (UUID)",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
],
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

Field Details:

FieldTypeAuto-GeneratedRequiredDescription
channelIdstringID of the channel where message is sent
contentstringMessage content/text
senderIdstringID of the identity sending the message
titlestringOptional message title
attachmentsarrayArray of file attachments (can be empty [])
attachments[].objectIdstring (UUID)UUID reference to the uploaded file in storage
attachments[].typestringMIME type or file category
attachments[].idstring (UUID)Unique identifier for the attachment entity
attachments[].createdAtdatetimeAttachment creation timestamp
attachments[].updatedAtdatetimeAttachment last modification timestamp
createdAtdatetimeMessage creation timestamp
idstringUnique identifier (UUID)
updatedAtdatetimeMessage last modification timestamp

📝 Note: Auto-generated fields are set by the service and should not be included in create/update requests. Each attachment in the attachments array automatically receives base entity fields (id, createdAt, updatedAt) upon message creation. Schema enforces additionalProperties: false - only defined fields are allowed.


Channel Read State Entity

{
"channelId": "string",
"identityId": "string",
"lastReadMessageId": "string",
"lastReadMessageCreatedAt": "string (datetime)",
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

Field Details:

FieldTypeAuto-GeneratedRequiredDescription
channelIdstringID of the channel being tracked
identityIdstringID of the identity whose read state is being tracked
lastReadMessageIdstringID of the last message read by the identity
lastReadMessageCreatedAtdatetimeTimestamp when the last read message was created
createdAtdatetimeCreation timestamp
idstringUnique identifier (UUID)
updatedAtdatetimeLast modification timestamp

📝 Note: Auto-generated fields are set by the service and should not be included in upsert requests. Schema enforces additionalProperties: false - only defined fields are allowed.


🔐 Authentication Headers

For protected endpoints, include the following headers:

Authorization: Bearer <access_token>
x-nb-fingerprint: <device_fingerprint>

⚠️ Important: The x-nb-fingerprint header is required for all authenticated requests if fingerprint was specified during authorization. Without it, requests will return 401 Unauthorized.


🔧 API Endpoints

📺 Channel Operations

1. Create Channel

Creates a new chat channel with the provided information.

Request:

  • Method: POST
  • Path: /channels
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Enforced automatically (name and ownerId required; no additional properties)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or self (ownerId matches authenticated user)

Request Body:

FieldTypeRequiredDescription
namestringChannel name/title
ownerIdstringID of the user who owns this channel
iconobject | nullChannel icon object with objectId (UUID) and type (string), or null

Response Body:

FieldTypeDescription
namestringChannel name/title
ownerIdstringID of the user who owns this channel
iconobject | nullChannel icon object with type (string) and url (string), or null
createdAtstringCreation timestamp
idstringUnique channel identifier
updatedAtstringLast update timestamp

Example Request:

curl -X POST http://localhost:8089/channels \
-H "Content-Type: application/json" \
-d '{
"name": "Project Updates",
"ownerId": "user-456"
}'

Success Response:

HTTP/1.1 201 Created
Content-Type: application/json

{
"name": "Project Updates",
"ownerId": "user-456",
"icon": null,
"createdAt": "2025-06-24T08:33:40.146Z",
"id": "af62eac3-06aa-481a-8c44-a029e96de2ed",
"updatedAt": "2025-06-24T08:33:40.146Z"
}

Validation Error Examples:

Missing Required Field:

{
"error": {
"message": "must have ownerId when creating a new channel"
}
}

Schema Validation Error:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'ownerId'"
]
}
}

Additional Properties Error:

{
"error": {
"message": "Validation Error",
"data": [
"request body must NOT have additional properties"
]
}
}
{
"error": {
"message": "Validation Error",
"data": [
"request body must NOT have additional properties",
"request body must NOT have additional properties"
]
}
}

2. List Channels

Retrieves all channels with optional filtering and pagination.

Request:

  • Method: GET
  • Path: /channels
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Query parameter validation for name, ownerId, and pagination (page, limit)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or self (when requesting own channels)

Query Parameters:

ParameterTypeRequiredDescription
namestringFilter by channel name
ownerIdstringFilter by owner ID
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body: Paginated response with channels array and metadata.

Response Structure:

{
"data": [
{
"id": "string",
"name": "string",
"ownerId": "string",
"icon": {
"type": "string",
"url": "string"
} | null,
"createdAt": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number,
"hasNext": boolean,
"hasPrev": boolean
}
}
}

Example Request:

curl "http://localhost:8089/channels?page=1&limit=10" \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"name": "Project Updates",
"ownerId": "user-456",
"icon": null,
"createdAt": "2025-06-24T08:33:40.146Z",
"id": "af62eac3-06aa-481a-8c44-a029e96de2ed",
"updatedAt": "2025-06-24T08:33:40.146Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

3. Get Channel

Retrieves a specific channel by ID.

Request:

  • Method: GET
  • Path: /channels/:channelId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Path parameter validation for channel ID
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role, channel owner, or active subscription to the channel

Response Body:

FieldTypeDescription
namestringChannel name/title
ownerIdstringID of the user who owns this channel
iconobject | nullChannel icon object with type (string) and url (string), or null
createdAtstringCreation timestamp
idstringUnique channel identifier
updatedAtstringLast update timestamp

Example Request:

curl http://localhost:8089/channels/af62eac3-06aa-481a-8c44-a029e96de2ed \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"name": "Project Updates",
"ownerId": "user-456",
"icon": null,
"createdAt": "2025-06-24T08:33:40.146Z",
"id": "af62eac3-06aa-481a-8c44-a029e96de2ed",
"updatedAt": "2025-06-24T08:33:40.146Z"
}

4. Get Channel Icon Upload URL

Generates a pre-signed URL for securely uploading a channel icon image. Returns an object ID and a temporary signed URL.

Request:

  • Method: GET
  • Path: /channels/:channelId/icon-upload-url
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

URL Parameters:

ParameterTypeRequiredDescription
channelIdstringTarget channel ID

Query Parameters:

ParameterTypeRequiredDescription
contentTypestringImage MIME type (e.g., image/png, image/jpeg)
contentLengthnumberFile size in bytes (max 10MB)

Response Body:

FieldTypeDescription
objectIdstringGenerated storage object ID for the icon
urlstringPre-signed URL for uploading the file

Validation:

  • Schema Validation: Uses image upload schema (content type and size constraints)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or channel owner

Example Request:

curl "http://localhost:8089/channels/af62eac3-06aa-481a-8c44-a029e96de2ed/icon-upload-url?contentType=image/jpeg&contentLength=524288" \
-H "Authorization: Bearer <token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"objectId": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"url": "https://storage.googleapis.com/bucket/channels/icons/...&X-Goog-Expires=900&X-Goog-Signature=..."
}

Usage Flow:

  1. Call this endpoint with contentType and contentLength query parameters to get a signed upload URL
  2. Use the returned url to upload the icon file directly to cloud storage (PUT request with the file binary)
  3. Store the returned objectId to reference the uploaded icon

Error Responses:

Missing Query Parameters:

{
"error": {
"message": "Validation Error",
"data": [
"contentType is required",
"contentLength is required"
]
}
}

Invalid Content Type:

{
"error": {
"message": "Invalid content type - must be an image"
}
}

File Too Large:

{
"error": {
"message": "File size exceeds maximum allowed (10MB)"
}
}

Channel Not Found:

{
"error": {
"message": "Channel not found"
}
}

Unauthorized:

{
"error": {
"message": "Unauthorized - must be channel owner or admin"
}
}

5. Update Channel

Updates an existing channel's properties.

Request:

  • Method: PATCH
  • Path: /channels/:channelId
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Partial update schema (all fields optional; no additional properties)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or channel owner

Request Body:

FieldTypeRequiredDescription
namestringNew channel name/title
iconobject | nullChannel icon object with objectId (UUID) and type (string), or null to remove icon

Response Body:

FieldTypeDescription
namestringUpdated channel name/title
ownerIdstringID of the user who owns this channel
iconobject | nullChannel icon object or null
createdAtstringCreation timestamp
idstringUnique channel identifier
updatedAtstringLast update timestamp

Example Request:

curl -X PATCH http://localhost:8089/channels/af62eac3-06aa-481a-8c44-a029e96de2ed \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{
"name": "Updated Project Updates"
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"name": "Updated Project Updates",
"ownerId": "user-456",
"icon": null,
"createdAt": "2025-06-24T08:33:40.146Z",
"id": "af62eac3-06aa-481a-8c44-a029e96de2ed",
"updatedAt": "2025-06-24T09:15:22.123Z"
}

6. Delete Channel

Removes a channel and all associated data.

Request:

  • Method: DELETE
  • Path: /channels/:channelId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Path parameter validation for channel ID
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or channel owner

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Example Request:

curl -X DELETE http://localhost:8089/channels/af62eac3-06aa-481a-8c44-a029e96de2ed

Success Response:

  • Status: 204 No Content
  • Body: (empty)

Not Found Error Example:

{
"error": {
"message": "Channel not found"
}
}

📋 Subscription Operations

7. Create Subscription

Creates a new subscription to a channel.

Request:

  • Method: POST
  • Path: /subscriptions
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Enforced automatically (channelId and subscribedId required; no additional properties)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or self (subscriber is the authenticated user)

Request Body:

FieldTypeRequiredDescription
channelIdstringID of the channel to subscribe to
subscribedIdstringID of the user subscribing
approvedbooleanWhether the subscription is approved
permissionsstring[]Array of permission strings
subscribedAtstring (date-time)Timestamp when subscription was created

Response Body:

FieldTypeDescription
channelIdstringID of the channel being subscribed to
subscribedIdstringID of the user subscribing
approvedbooleanWhether the subscription is approved
permissionsarrayArray of permission strings
subscribedAtstringTimestamp when subscription was created
createdAtstringCreation timestamp
idstringUnique subscription identifier
updatedAtstringLast update timestamp

Example Request:

curl -X POST http://localhost:8089/subscriptions \
-H "Content-Type: application/json" \
-d '{
"channelId": "af62eac3-06aa-481a-8c44-a029e96de2ed",
"subscribedId": "user-456",
"approved": true,
"permissions": ["read", "write"]
}'

Success Response:

HTTP/1.1 201 Created
Content-Type: application/json

{
"channelId": "af62eac3-06aa-481a-8c44-a029e96de2ed",
"subscribedId": "user-456",
"approved": true,
"permissions": ["read", "write"],
"createdAt": "2025-06-27T02:16:07.916Z",
"id": "b17501d6-2576-4a18-86f5-3545da75e678",
"updatedAt": "2025-06-27T02:16:07.916Z"
}

Validation Error Example:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'channelId'",
"request body must have required property 'subscribedId'",
]
}
}
{
"error": {
"message": "Validation Error",
"data": [
"request body must NOT have additional properties",
]
}
}

8. List Subscriptions

Retrieves all subscriptions with optional filtering and pagination.

Request:

  • Method: GET
  • Path: /subscriptions
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Query parameter validation for approved, channelId, subscribedAt, subscribedId, and pagination (page, limit)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role, active subscription to the channel, channel owner, or self (subscriber)

Query Parameters:

ParameterTypeRequiredDescription
approvedbooleanFilter by approval status
channelIdstringFilter by channel ID
subscribedIdstringFilter by subscriber ID
subscribedAtstring (date-time)Filter by subscription date
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body: Paginated response with subscriptions array and metadata.

Response Structure:

{
"data": [
{
"id": "string",
"channelId": "string",
"subscribedId": "string",
"approved": boolean,
"permissions": ["string"],
"subscribedAt": "string",
"createdAt": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number,
"hasNext": boolean,
"hasPrev": boolean
}
}
}

Example Request:

curl "http://localhost:8089/subscriptions?page=1&limit=10" \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"channelId": "channel-123",
"subscribedId": "user-456",
"approved": true,
"permissions": ["read", "write"],
"subscribedAt": "2025-06-24T08:33:40.146Z",
"createdAt": "2025-06-24T08:33:40.146Z",
"id": "sub-789",
"updatedAt": "2025-06-24T08:33:40.146Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

9. Get Subscription

Retrieves a specific subscription by ID.

Request:

  • Method: GET
  • Path: /subscriptions/:subscriptionId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Path parameter validation for subscription ID
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or subscription owner

Example Request:

curl http://localhost:8089/subscriptions/b17501d6-2576-4a18-86f5-3545da75e678

10. Delete Subscription

Removes a subscription (unsubscribe from channel).

Request:

  • Method: DELETE
  • Path: /subscriptions/:subscriptionId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Path parameter validation for subscription ID
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or subscription owner

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Example Request:

curl -X DELETE http://localhost:8089/subscriptions/b17501d6-2576-4a18-86f5-3545da75e678

Success Response:

  • Status: 204 No Content
  • Body: (empty)

Not Found Error Example:

{
"error": {
"message": "Subscription not found"
}
}

💬 Message Operations

11. Create Message

Sends a new message to a channel.

Request:

  • Method: POST
  • Path: /messages
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Enforced automatically (content, senderId, and channelId required; no additional properties)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require self as sender
    • Require active subscription to the channel

Request Body:

FieldTypeRequiredDescription
channelIdstringID of the channel where message is sent
contentstringMessage content/text
senderIdstringID of the user sending the message
titlestringOptional message title

Response Body:

FieldTypeDescription
channelIdstringID of the channel where message is sent
contentstringMessage content/text
senderIdstringID of the user sending the message
titlestringOptional message title
createdAtstringCreation timestamp
idstringUnique message identifier
updatedAtstringLast update timestamp

Example Request:

curl -X POST http://localhost:8089/messages \
-H "Content-Type: application/json" \
-d '{"channelId": "test-channel-123", "content": "Hello world!", "senderId": "user-456"}'

Success Response:

{
"channelId": "test-channel-123",
"content": "Hello world!",
"senderId": "user-456",
"createdAt": "2025-07-01T03:22:06.178Z",
"id": "2b43d66c-9cab-434b-9cb7-18de8d3ec9c9",
"updatedAt": "2025-07-01T03:22:06.178Z"
}

Validation Error Example:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'senderId'",
"request body must have required property 'channelId'"
]
}
}

12. List Messages

Retrieves messages in a specific channel.

Request:

  • Method: GET
  • Path: /messages?channelId=:channelId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Query parameter validation for channelId (required), optional content, senderId, title, and pagination (page, limit)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role, active subscription to the channel, or self as sender

Query Parameters:

ParameterTypeRequiredDescription
channelIdstringID of the channel to get messages from
contentstringFilter by message content
senderIdstringFilter by sender ID
titlestringFilter by message title
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body: Paginated response with messages array and metadata.

Response Structure:

{
"data": [
{
"id": "string",
"channelId": "string",
"content": "string",
"senderId": "string",
"title": "string",
"attachments": [
{
"id": "string",
"objectId": "string",
"type": "string",
"url": "string",
"createdAt": "string",
"updatedAt": "string"
}
],
"createdAt": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number,
"hasNext": boolean,
"hasPrev": boolean
}
}
}

Example Request:

curl "http://localhost:8089/messages?channelId=test-channel-123&page=1&limit=10" \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"channelId": "test-channel-123",
"content": "Updated message content",
"senderId": "user-456",
"createdAt": "2025-07-01T03:22:06.178Z",
"id": "2b43d66c-9cab-434b-9cb7-18de8d3ec9c9",
"updatedAt": "2025-07-01T03:22:34.413Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

Validation Error Example:

{
"error": {
"message": "Validation Error",
"data": [
"query parameter 'channelId' is required"
]
}
}

13. Get Message by ID

Retrieves a specific message by ID.

Request:

  • Method: GET
  • Path: /messages/:messageId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Path parameter validation for message ID
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or message owner

Example Request:

curl http://localhost:8089/messages/2b43d66c-9cab-434b-9cb7-18de8d3ec9c9

Success Response:

{
"channelId": "test-channel-123",
"content": "Updated message content",
"senderId": "user-456",
"createdAt": "2025-07-01T03:22:06.178Z",
"id": "2b43d66c-9cab-434b-9cb7-18de8d3ec9c9",
"updatedAt": "2025-07-01T03:22:34.413Z"
}

Not Found Error Example:

{
"error": {
"message": "Message not found"
}
}

14. Update Message

Updates an existing message's content.

Request:

  • Method: PATCH
  • Path: /messages/:messageId
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Partial update schema (all fields optional; path parameter validation for message ID; no additional properties)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or message owner

Request Body:

FieldTypeRequiredDescription
contentstringUpdated message content
senderIdstringUpdated sender ID (typically not changed)
titlestringUpdated message title

Response Body:

FieldTypeDescription
channelIdstringID of the channel where message is sent
contentstringUpdated message content
senderIdstringID of the user sending the message
titlestringUpdated message title
createdAtstringCreation timestamp
idstringUnique message identifier
updatedAtstringLast update timestamp

Example Request:

curl -X PATCH http://localhost:8089/messages/2b43d66c-9cab-434b-9cb7-18de8d3ec9c9 \
-H "Content-Type: application/json" \
-d '{"content": "Updated message content"}'

Success Response:

{
"channelId": "test-channel-123",
"content": "Updated message content",
"senderId": "user-456",
"createdAt": "2025-07-01T03:22:06.178Z",
"id": "2b43d66c-9cab-434b-9cb7-18de8d3ec9c9",
"updatedAt": "2025-07-01T03:22:34.413Z"
}

Not Found Error Example:

{
"error": {
"message": "Chat message not found"
}
}

15. Delete Message

Removes a message from a channel.

Request:

  • Method: DELETE
  • Path: /messages/:messageId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Validation:

  • Schema Validation: Path parameter validation for message ID
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or message owner

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Example Request:

curl -X DELETE http://localhost:8089/messages/81950444-5223-47c8-8a8c-0604c2955f15

Success Response:

  • Status: 204 No Content
  • Body: (empty)

Not Found Error Example:

{
"error": {
"message": "Chat message not found"
}
}


📝 Message Template Operations

16. Create Message Template

Creates a new chat message template for reusable messaging content with proper validation and error handling.

Request:

  • Method: POST
  • Path: /message-templates
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Request Body:

FieldTypeRequiredDescription
contentstringTemplate message content
titlestringTemplate title/description
organizationIdstringOrganization identifier for template scope

Validation:

  • Schema Validation: Enforced automatically (content and title required)
  • Route Validators: Require authenticated request (bearer token)

Example Request:

curl -X POST {{host}}/message-templates \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-H "x-nb-fingerprint: <device-fingerprint>" \
-d '{
"content": "Welcome to our community! Please follow our guidelines.",
"title": "Welcome Message",
"organizationId": "org-123"
}'

Success Response:

HTTP/1.1 201 Created
Content-Type: application/json

{
"id": "template-uuid-here"
}

Validation Error Example:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'content'"
]
}
}

17. Get Message Template by ID

Retrieves a specific chat message template by its unique identifier for reuse in messaging applications.

Request:

  • Method: GET
  • Path: /message-templates/:templateId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Path Parameters:

  • templateId: string (required) - Unique identifier of the message template

Request Body:

FieldTypeRequiredDescription
No request body-No body required

Validation:

  • Schema Validation: Path parameter validation for template ID
  • Route Validators: Require authenticated request (bearer token)

Example Request:

curl -X GET {{host}}/message-templates/template-123 \
-H "Authorization: Bearer <token>" \
-H "x-nb-fingerprint: <device-fingerprint>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"content": "Welcome to our community! Please follow our guidelines.",
"createdAt": "2025-01-20T10:30:00.000Z",
"id": "template-123",
"organizationId": "org-123",
"title": "Welcome Message",
"updatedAt": "2025-01-20T10:30:00.000Z"
}

Not Found Error Example:

{
"error": {
"message": "Chat message template not found"
}
}

18. Update Message Template

Updates an existing chat message template with partial data support, allowing administrators or organization owners to modify template content and titles.

Request:

  • Method: PATCH
  • Path: /message-templates/:templateId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required (admin or organization owner/admin)

Path Parameters:

  • templateId: string (required) - Unique identifier of the message template to update

Request Body:

FieldTypeRequiredDescription
contentstringUpdated message template content
titlestringUpdated message template title

Validation:

  • Schema Validation: Path parameter and partial body validation
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or organization owner/admin access to the template

Example Request:

curl -X PATCH {{host}}/message-templates/template-123 \
-H "Authorization: Bearer <token>" \
-H "x-nb-fingerprint: <device-fingerprint>" \
-H "Content-Type: application/json" \
-d '{
"content": "Updated welcome message content",
"title": "Updated Welcome Message"
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"content": "Updated welcome message content",
"createdAt": "2025-01-20T10:30:00.000Z",
"id": "template-123",
"organizationId": "org-123",
"title": "Updated Welcome Message",
"updatedAt": "2025-01-25T14:20:00.000Z"
}

Error Responses:

Not Found (404):

{
"error": {
"message": "Chat message template not found"
}
}

Unauthorized (401):

{
"error": {
"message": "token could not be verified"
}
}

Forbidden (403):

{
"error": {
"message": "Access denied: insufficient permissions"
}
}

Use Cases:

  • Updating welcome messages for organizational changes
  • Correcting template content or titles
  • Maintaining template relevance over time
  • Administrative template management

19. Delete Message Template

Deletes an existing chat message template with proper authorization checks, allowing administrators or organization owners to remove templates from the database.

Request:

  • Method: DELETE
  • Path: /message-templates/:templateId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required (admin or organization owner/admin)

Path Parameters:

  • templateId: string (required) - Unique identifier of the message template to delete

Validation:

  • Schema Validation: Path parameter validation
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or organization owner/admin access to the template

Example Request:

curl -X DELETE {{host}}/message-templates/template-123 \
-H "Authorization: Bearer <token>" \
-H "x-nb-fingerprint: <device-fingerprint>"

Success Response:

HTTP/1.1 204 No Content

Error Responses:

Not Found (404):

{
"error": {
"message": "Chat message template not found"
}
}

Unauthorized (401):

{
"error": {
"message": "token could not be verified"
}
}

Forbidden (403):

{
"error": {
"message": "Access denied: insufficient permissions"
}
}

Internal Server Error (500):

{
"error": {
"message": "Failed to delete message template"
}
}

Use Cases:

  • Removing outdated or unused templates
  • Cleaning up organizational templates
  • Template lifecycle management
  • Administrative template removal

20. List Message Templates

Retrieves a paginated list of all chat message templates with data normalization and admin-only access control.

Request:

  • Method: GET
  • Path: /message-templates
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required (admin only)

Query Parameters:

ParameterTypeRequiredDescription
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body: Paginated response with message templates array and metadata.

Response Structure:

{
"data": [
{
"id": "string",
"title": "string",
"content": "string",
"organizationId": "string",
"createdAt": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number,
"hasNext": boolean,
"hasPrev": boolean
}
}
}

Validation:

  • Schema Validation: Pagination query parameters
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role (checkIdentityType(['admin']))

Example Request:

curl "http://localhost:8089/message-templates?page=1&limit=10" \
-H "Authorization: Bearer <token>" \
-H "x-nb-fingerprint: <device-fingerprint>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"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"
},
{
"id": "template-789",
"title": "Support Response",
"content": "Thank you for contacting support. We'll get back to you soon.",
"organizationId": "org-456",
"createdAt": "2024-01-02T00:00:00.000Z",
"updatedAt": "2024-01-02T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 2,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

Error Responses:

Unauthorized (401):

{
"error": {
"message": "token could not be verified"
}
}

Forbidden (403):

{
"error": {
"message": "Identity is not authorized to access this resource"
}
}

Internal Server Error (500):

{
"error": {
"message": "Failed to find message templates"
}
}

Use Cases:

  • Administrative template management
  • Template inventory and oversight
  • Bulk template operations
  • Template analytics and reporting
  • System administration interfaces

21. List Message Templates for Organization

Retrieves a paginated list of chat message templates scoped to a specific organization, with automatic access control based on organization membership and role permissions.

Request:

  • Method: GET
  • Path: /organizations/:organizationId/message-templates
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required (organization member with owner/admin role)

Path Parameters:

  • organizationId: string (required) - Unique identifier of the organization to retrieve templates for

Query Parameters:

  • page: number (optional, default: 1) - Page number for pagination
  • limit: number (optional, default: 10) - Number of templates per page

Validation:

  • Schema Validation: Organization ID path parameter and pagination query parameters
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require organization membership with owner or admin role

Example Request:

curl "http://localhost:8089/organizations/org-123/message-templates?page=1&limit=10" \
-H "Authorization: Bearer <token>" \
-H "x-nb-fingerprint: <device-fingerprint>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"id": "template-456",
"title": "Organization Welcome",
"content": "Welcome to our organization chat!",
"organizationId": "org-123",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
{
"id": "template-789",
"title": "Project Update",
"content": "Here's the latest update on our project.",
"organizationId": "org-123",
"createdAt": "2024-01-02T00:00:00.000Z",
"updatedAt": "2024-01-02T00:00:00.000Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 2,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

Error Responses:

Unauthorized (401):

{
"error": {
"message": "token could not be verified"
}
}

Forbidden (403):

{
"error": {
"message": "Identity is not a member of the organization"
}
}

Internal Server Error (500):

{
"error": {
"message": "Failed to find message templates"
}
}

Use Cases:

  • Organization-specific template management
  • Team collaboration tools
  • Department-specific messaging templates
  • Organization-wide communication standards
  • Role-based template access control

⚙️ Configuration Options

Service Data Store

interface ChatServiceDataStore {
identities: Collection; // Required - User identities collection
chatChannels: Collection; // Required - Chat channels collection
organizations?: Collection; // Optional - Organizations collection
subscriptions?: Collection; // Optional - Channel subscriptions collection
chatMessages: Collection; // Required - Chat messages collection
chatMessageTemplates?: Collection; // Optional - Message templates collection
}

Service Configuration

interface ChatServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
organization?: {
roles?: {
admin: string; // Admin organization role identifier
member: string; // Member organization role identifier
owner: string; // Owner organization role identifier
};
};
}

Configuration Details

The chat service configuration is organized into logical groups for security and user type management.

🔐 Security Settings

authSecrets - JWT token security secrets

  • Type: { authEncSecret: string; authSignSecret: string }
  • Description: Secret keys for JWT encryption and signing (used for token validation)
  • Required: Yes (for production)
  • Child Properties:
    • authEncSecret: Secret key for JWT payload encryption
    • authSignSecret: Secret key for JWT signature verification

👥 User Type Settings

identity.typeIds - User type identifier configuration

  • Type: { admin?: string; guest?: string; regular?: string }
  • Description: Custom user type identifiers for role-based access control
  • Default: undefined (uses default type validation)
  • Child Properties:
    • admin: Admin user type identifier
      • Type: string
      • Description: Custom identifier for admin users
      • Use Case: Role-based access control for administrative operations
      • Example: "admin", "administrator", "superuser"
    • guest: Guest user type identifier
      • Type: string
      • Description: Custom identifier for guest users
      • Use Case: Limited access for unauthenticated or temporary users
      • Example: "guest", "visitor", "anonymous"
    • regular: Regular user type identifier
      • Type: string
      • Description: Custom identifier for regular users
      • Use Case: Standard user access permissions
      • Example: "user", "member", "customer"

🏢 Organization Settings

organization.roles - Organization role identifier configuration

  • Type: { admin?: string; member?: string; owner?: string }
  • Description: Custom organization role identifiers for role-based access control
  • Default: undefined (uses default role validation)
  • Child Properties:
    • admin: Admin organization role identifier
      • Type: string
      • Description: Custom identifier for organization admin role
      • Use Case: Organization-level administrative operations
      • Example: "admin", "administrator", "org-admin"
    • member: Member organization role identifier
      • Type: string
      • Description: Custom identifier for organization member role
      • Use Case: Standard organization membership permissions
      • Example: "member", "user", "participant"
    • owner: Owner organization role identifier
      • Type: string
      • Description: Custom identifier for organization owner role
      • Use Case: Full organization ownership permissions
      • Example: "owner", "founder", "org-owner"

Example Configuration

const chatConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: 'administrator',
guest: 'visitor',
regular: 'member'
}
},
organization: {
roles: {
admin: 'admin',
member: 'member',
owner: 'owner'
}
}
};

🚨 Error Handling

All chat service errors return JSON format with appropriate HTTP status codes:

Common Error Codes

StatusError MessageDescription
400Validation ErrorInvalid request body format or missing required fields
400must have ownerId when creating a new channelMissing ownerId field in request body
400request body must have required property 'name'Missing name field in request body
400request body must have required property 'ownerId'Missing ownerId field in request body
400request body must have required property 'channelId'Missing channelId field in request body
400request body must have required property 'subscribedId'Missing subscribedId field in request body
400request body must have required property 'content'Missing content field in request body
400request body must have required property 'senderId'Missing senderId field in request body
400request body must NOT have additional propertiesRequest contains unsupported fields
400query parameter 'channelId' is requiredMissing required query parameter
400Failed to create channelDatabase insert operation failed to return an inserted ID
400Failed to update channelUpdate operation doesn't modify any data (no changes detected)
400Failed to delete channelDatabase deletion operation failed
400Failed to create subscriptionDatabase insert operation failed to return an inserted ID
400Failed to delete subscriptionDatabase deletion operation failed
400Failed to create messageDatabase insert operation failed to return an inserted ID
400Failed to update messageUpdate operation doesn't modify any data (no changes detected)
400Failed to delete messageDatabase deletion operation failed
401token could not be verifiedMissing or invalid authorization token
401Authentication failedMissing or invalid authentication token
401Token fails security checkToken security validation failed
403User is not authorized to access this resourceUser lacks required permissions (admin access)
404Channel not foundChannel doesn't exist for the requested operation
404Subscription not foundSubscription doesn't exist for the requested operation
404Message not foundMessage doesn't exist for the requested operation
404Chat message not foundChat message doesn't exist for the requested operation
500Failed to create channelDatabase connection issues or unexpected failures during creation
500Failed to get channelDatabase connection issues or unexpected failures during retrieval
500Failed to find channelsDatabase connection issues, invalid filter syntax, or unexpected failures during listing
500Failed to update channelDatabase connection issues or unexpected failures during update
500Failed to delete channelDatabase connection issues or unexpected failures during deletion
500Failed to create subscriptionDatabase connection issues or unexpected failures during creation
500Failed to get subscriptionDatabase connection issues or unexpected failures during retrieval
500Failed to find subscriptionsDatabase connection issues, invalid filter syntax, or unexpected failures during listing
500Failed to delete subscriptionDatabase connection issues or unexpected failures during deletion
500Failed to create messageDatabase connection issues or unexpected failures during creation
500Failed to get messageDatabase connection issues or unexpected failures during retrieval
500Failed to find messagesDatabase connection issues, invalid filter syntax, or unexpected failures during listing
500Failed to update messageDatabase connection issues or unexpected failures during update
500Failed to delete messageDatabase connection issues or unexpected failures during deletion

Error Response Format

{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}

Validation Errors include additional details:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'name'",
"request body must have required property 'ownerId'"
]
}
}