💬 Chat Service
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
| Method | Path | Description |
|---|---|---|
POST | /channels | Create a new channel |
GET | /channels | List all channels |
GET | /channels/:channelId | Get a specific channel |
GET | /channels/:channelId/icon-upload-url | Generate signed URL for channel icon upload |
PATCH | /channels/:channelId | Update a channel |
DELETE | /channels/:channelId | Delete a channel |
Subscription Operations
| Method | Path | Description |
|---|---|---|
POST | /subscriptions | Create a new subscription |
GET | /subscriptions | List all subscriptions |
GET | /subscriptions/:subscriptionId | Get a specific subscription |
DELETE | /subscriptions/:subscriptionId | Delete a subscription |
Message Operations
| Method | Path | Description |
|---|---|---|
POST | /messages | Create a new message |
GET | /messages?channelId=:channelId | List messages in a channel |
GET | /channels/:channelId/messages | Get all messages for a specific channel |
GET | /messages/:messageId | Get a specific message |
GET | /messages/:messageId/attachment-upload-url | Generate signed URL for message attachment upload |
POST | /messages/:messageId/attachments | Create a new attachment for an existing message |
DELETE | /messages/:messageId/attachments/:attachmentId | Delete an attachment from a message |
PATCH | /messages/:messageId | Update a message |
DELETE | /messages/:messageId | Delete a message |
Message Template Operations
| Method | Path | Description |
|---|---|---|
POST | /message-templates | Create a new message template |
GET | /message-templates | List all message templates (admin only) |
GET | /organizations/:organizationId/message-templates | List message templates for organization (org members) |
GET | /message-templates/:templateId | Get a specific message template |
PATCH | /message-templates/:templateId | Update an existing message template |
DELETE | /message-templates/:templateId | Delete an existing message template |
Channel Read State Operations
| Method | Path | Description |
|---|---|---|
PUT | /channels/:channelId/read-state | Upsert (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:
| Field | Type | Auto-Generated | Required | Description |
|---|---|---|---|---|
name | string | ❌ | ✅ | Channel name/title |
ownerId | string | ❌ | ✅ | ID of the identity who owns this channel |
createdAt | datetime | ✅ | ✅ | Creation timestamp |
id | string | ✅ | ✅ | Unique identifier (UUID) |
updatedAt | datetime | ✅ | ✅ | Last 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:
| Field | Type | Auto-Generated | Required | Description |
|---|---|---|---|---|
approved | boolean | ❌ | ❌ | Whether the subscription is approved |
channelId | string | ❌ | ✅ | ID of the channel being subscribed to |
permissions | array | ❌ | ❌ | Array of permission strings (e.g., ["read", "write"]) |
subscribedAt | datetime | ❌ | ❌ | Timestamp when subscription was created |
subscribedId | string | ❌ | ❌ | ID of the identity subscribing |
createdAt | datetime | ✅ | ✅ | Creation timestamp |
id | string | ✅ | ✅ | Unique identifier (UUID) |
updatedAt | datetime | ✅ | ✅ | Last 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:
| Field | Type | Auto-Generated | Required | Description |
|---|---|---|---|---|
channelId | string | ❌ | ✅ | ID of the channel where message is sent |
content | string | ❌ | ✅ | Message content/text |
senderId | string | ❌ | ✅ | ID of the identity sending the message |
title | string | ❌ | ❌ | Optional message title |
attachments | array | ❌ | ✅ | Array of file attachments (can be empty []) |
attachments[].objectId | string (UUID) | ❌ | ✅ | UUID reference to the uploaded file in storage |
attachments[].type | string | ❌ | ✅ | MIME type or file category |
attachments[].id | string (UUID) | ✅ | ✅ | Unique identifier for the attachment entity |
attachments[].createdAt | datetime | ✅ | ✅ | Attachment creation timestamp |
attachments[].updatedAt | datetime | ✅ | ✅ | Attachment last modification timestamp |
createdAt | datetime | ✅ | ✅ | Message creation timestamp |
id | string | ✅ | ✅ | Unique identifier (UUID) |
updatedAt | datetime | ✅ | ✅ | Message 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
attachmentsarray automatically receives base entity fields (id,createdAt,updatedAt) upon message creation. Schema enforcesadditionalProperties: 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:
| Field | Type | Auto-Generated | Required | Description |
|---|---|---|---|---|
channelId | string | ❌ | ✅ | ID of the channel being tracked |
identityId | string | ❌ | ✅ | ID of the identity whose read state is being tracked |
lastReadMessageId | string | ❌ | ✅ | ID of the last message read by the identity |
lastReadMessageCreatedAt | datetime | ❌ | ✅ | Timestamp when the last read message was created |
createdAt | datetime | ✅ | ✅ | Creation timestamp |
id | string | ✅ | ✅ | Unique identifier (UUID) |
updatedAt | datetime | ✅ | ✅ | Last 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-fingerprintheader 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/jsonAuthorization: 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:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Channel name/title |
ownerId | string | ✅ | ID of the user who owns this channel |
icon | object | null | ❌ | Channel icon object with objectId (UUID) and type (string), or null |
Response Body:
| Field | Type | Description |
|---|---|---|
name | string | Channel name/title |
ownerId | string | ID of the user who owns this channel |
icon | object | null | Channel icon object with type (string) and url (string), or null |
createdAt | string | Creation timestamp |
id | string | Unique channel identifier |
updatedAt | string | Last 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ❌ | Filter by channel name |
ownerId | string | ❌ | Filter by owner ID |
page | number | ❌ | Page number for pagination (1-1000) |
limit | number | ❌ | Number 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:
| Field | Type | Description |
|---|---|---|
name | string | Channel name/title |
ownerId | string | ID of the user who owns this channel |
icon | object | null | Channel icon object with type (string) and url (string), or null |
createdAt | string | Creation timestamp |
id | string | Unique channel identifier |
updatedAt | string | Last 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
channelId | string | ✅ | Target channel ID |
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
contentType | string | ✅ | Image MIME type (e.g., image/png, image/jpeg) |
contentLength | number | ✅ | File size in bytes (max 10MB) |
Response Body:
| Field | Type | Description |
|---|---|---|
objectId | string | Generated storage object ID for the icon |
url | string | Pre-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:
- Call this endpoint with
contentTypeandcontentLengthquery parameters to get a signed upload URL - Use the returned
urlto upload the icon file directly to cloud storage (PUT request with the file binary) - Store the returned
objectIdto 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/jsonAuthorization: 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:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ❌ | New channel name/title |
icon | object | null | ❌ | Channel icon object with objectId (UUID) and type (string), or null to remove icon |
Response Body:
| Field | Type | Description |
|---|---|---|
name | string | Updated channel name/title |
ownerId | string | ID of the user who owns this channel |
icon | object | null | Channel icon object or null |
createdAt | string | Creation timestamp |
id | string | Unique channel identifier |
updatedAt | string | Last 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:
| Field | Type | Description |
|---|---|---|
| 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/jsonAuthorization: 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:
| Field | Type | Required | Description |
|---|---|---|---|
channelId | string | ✅ | ID of the channel to subscribe to |
subscribedId | string | ✅ | ID of the user subscribing |
approved | boolean | ❌ | Whether the subscription is approved |
permissions | string[] | ❌ | Array of permission strings |
subscribedAt | string (date-time) | ❌ | Timestamp when subscription was created |
Response Body:
| Field | Type | Description |
|---|---|---|
channelId | string | ID of the channel being subscribed to |
subscribedId | string | ID of the user subscribing |
approved | boolean | Whether the subscription is approved |
permissions | array | Array of permission strings |
subscribedAt | string | Timestamp when subscription was created |
createdAt | string | Creation timestamp |
id | string | Unique subscription identifier |
updatedAt | string | Last 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
approved | boolean | ❌ | Filter by approval status |
channelId | string | ❌ | Filter by channel ID |
subscribedId | string | ❌ | Filter by subscriber ID |
subscribedAt | string (date-time) | ❌ | Filter by subscription date |
page | number | ❌ | Page number for pagination (1-1000) |
limit | number | ❌ | Number 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:
| Field | Type | Description |
|---|---|---|
| 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/jsonAuthorization: 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:
| Field | Type | Required | Description |
|---|---|---|---|
channelId | string | ✅ | ID of the channel where message is sent |
content | string | ✅ | Message content/text |
senderId | string | ✅ | ID of the user sending the message |
title | string | ❌ | Optional message title |
Response Body:
| Field | Type | Description |
|---|---|---|
channelId | string | ID of the channel where message is sent |
content | string | Message content/text |
senderId | string | ID of the user sending the message |
title | string | Optional message title |
createdAt | string | Creation timestamp |
id | string | Unique message identifier |
updatedAt | string | Last 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
channelId | string | ✅ | ID of the channel to get messages from |
content | string | ❌ | Filter by message content |
senderId | string | ❌ | Filter by sender ID |
title | string | ❌ | Filter by message title |
page | number | ❌ | Page number for pagination (1-1000) |
limit | number | ❌ | Number 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/jsonAuthorization: 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:
| Field | Type | Required | Description |
|---|---|---|---|
content | string | ❌ | Updated message content |
senderId | string | ❌ | Updated sender ID (typically not changed) |
title | string | ❌ | Updated message title |
Response Body:
| Field | Type | Description |
|---|---|---|
channelId | string | ID of the channel where message is sent |
content | string | Updated message content |
senderId | string | ID of the user sending the message |
title | string | Updated message title |
createdAt | string | Creation timestamp |
id | string | Unique message identifier |
updatedAt | string | Last 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:
| Field | Type | Description |
|---|---|---|
| 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/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
content | string | ✅ | Template message content |
title | string | ✅ | Template title/description |
organizationId | string | ❌ | Organization 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:
| Field | Type | Required | Description |
|---|---|---|---|
| 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:
| Field | Type | Required | Description |
|---|---|---|---|
content | string | ❌ | Updated message template content |
title | string | ❌ | Updated 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
page | number | ❌ | Page number for pagination (1-1000) |
limit | number | ❌ | Number 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 paginationlimit: 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 encryptionauthSignSecret: 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"
- Type:
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"
- Type:
regular: Regular user type identifier- Type:
string - Description: Custom identifier for regular users
- Use Case: Standard user access permissions
- Example:
"user","member","customer"
- Type:
🏢 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"
- Type:
member: Member organization role identifier- Type:
string - Description: Custom identifier for organization member role
- Use Case: Standard organization membership permissions
- Example:
"member","user","participant"
- Type:
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"
- Type:
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
| Status | Error Message | Description |
|---|---|---|
| 400 | Validation Error | Invalid request body format or missing required fields |
| 400 | must have ownerId when creating a new channel | Missing ownerId field in request body |
| 400 | request body must have required property 'name' | Missing name field in request body |
| 400 | request body must have required property 'ownerId' | Missing ownerId field in request body |
| 400 | request body must have required property 'channelId' | Missing channelId field in request body |
| 400 | request body must have required property 'subscribedId' | Missing subscribedId field in request body |
| 400 | request body must have required property 'content' | Missing content field in request body |
| 400 | request body must have required property 'senderId' | Missing senderId field in request body |
| 400 | request body must NOT have additional properties | Request contains unsupported fields |
| 400 | query parameter 'channelId' is required | Missing required query parameter |
| 400 | Failed to create channel | Database insert operation failed to return an inserted ID |
| 400 | Failed to update channel | Update operation doesn't modify any data (no changes detected) |
| 400 | Failed to delete channel | Database deletion operation failed |
| 400 | Failed to create subscription | Database insert operation failed to return an inserted ID |
| 400 | Failed to delete subscription | Database deletion operation failed |
| 400 | Failed to create message | Database insert operation failed to return an inserted ID |
| 400 | Failed to update message | Update operation doesn't modify any data (no changes detected) |
| 400 | Failed to delete message | Database deletion operation failed |
| 401 | token could not be verified | Missing or invalid authorization token |
| 401 | Authentication failed | Missing or invalid authentication token |
| 401 | Token fails security check | Token security validation failed |
| 403 | User is not authorized to access this resource | User lacks required permissions (admin access) |
| 404 | Channel not found | Channel doesn't exist for the requested operation |
| 404 | Subscription not found | Subscription doesn't exist for the requested operation |
| 404 | Message not found | Message doesn't exist for the requested operation |
| 404 | Chat message not found | Chat message doesn't exist for the requested operation |
| 500 | Failed to create channel | Database connection issues or unexpected failures during creation |
| 500 | Failed to get channel | Database connection issues or unexpected failures during retrieval |
| 500 | Failed to find channels | Database connection issues, invalid filter syntax, or unexpected failures during listing |
| 500 | Failed to update channel | Database connection issues or unexpected failures during update |
| 500 | Failed to delete channel | Database connection issues or unexpected failures during deletion |
| 500 | Failed to create subscription | Database connection issues or unexpected failures during creation |
| 500 | Failed to get subscription | Database connection issues or unexpected failures during retrieval |
| 500 | Failed to find subscriptions | Database connection issues, invalid filter syntax, or unexpected failures during listing |
| 500 | Failed to delete subscription | Database connection issues or unexpected failures during deletion |
| 500 | Failed to create message | Database connection issues or unexpected failures during creation |
| 500 | Failed to get message | Database connection issues or unexpected failures during retrieval |
| 500 | Failed to find messages | Database connection issues, invalid filter syntax, or unexpected failures during listing |
| 500 | Failed to update message | Database connection issues or unexpected failures during update |
| 500 | Failed to delete message | Database 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'"
]
}
}
🔗 Related Documentation
- User Service - User management for chat participants
- Organization Service - Team-based chat organization
- Authentication Service - Authentication and authorization
- Error Handling - Understanding error patterns
- Schema Component - Data validation concepts
- Custom Service Tutorial - Extend chat functionality