chat module powers direct, group, and space conversations — sending and
editing messages (with file attachments), managing members, reacting, and tracking
read state. All actions are performed as the logged-in user.
Two list endpoints use cursor (keyset) pagination, not
page/limit:
listConversations and listMessages.
Their return shapes differ from the standard PaginatedResponse — see each
below.listConversations
Lists the user’s conversations, newest activity first, with keyset pagination.Comma-separated conversation types to include, e.g.
"direct,group,space".Keyset cursor — the
lastMessageAt (ISO datetime) of the last item from the
previous page.Tie-breaker cursor — the
createdAt (ISO datetime) of the last item from the
previous page.Page size. Defaults to
20, max 50.Promise<{ conversations: ConversationPreview[]; hasMore: boolean }>.
Each ConversationPreview includes otherMembers — up to 5 active members other than the current user (id, name, username, avatar) for direct/group conversations, so a DM/group can render the counterparty without a separate members fetch. Capped at 5 (use memberCount for the group total); empty for space conversations.
createDirectConversation
Creates (or returns the existing) 1:1 direct conversation with another user.The other participant’s Sublay user ID.
Promise<Conversation>
createGroupConversation
Creates a group conversation.Group name.
Group description.
Sublay user IDs to add to the group. Defaults to an empty list.
Arbitrary key-value data attached to the conversation.
Promise<Conversation>
getConversation
Fetches a single conversation by ID.The conversation ID.
Promise<Conversation>
updateConversation
Updates a conversation’s settings.The conversation ID.
New name.
New description.
File ID for the conversation avatar, or
null to clear it.Space conversations only: who may post.
Promise<Conversation>
deleteConversation
Deletes a conversation.The conversation ID.
Promise<{ message: string }>
getUnreadCount
Returns the user’s total unread message count and unread-conversation count. Takes no arguments.Promise<{ totalUnread: number; unreadConversationCount: number }>
listMembers
Lists the members of a conversation (standard page-based pagination).The conversation ID.
Page number (1-indexed).
Results per page.
Filter members by role.
Promise<PaginatedResponse<ConversationMember>>
addMember
Adds a user as a member of a conversation.The conversation ID.
The user to add (the target member).
Promise<ConversationMember>
removeMember
Removes a member from a conversation.The conversation ID.
The member to remove (the target).
Promise<{ message: string }>
changeMemberRole
Changes a member’s role within a conversation.The conversation ID.
The member whose role to change (the target).
The new role.
Promise<ConversationMember>
leaveConversation
The logged-in user leaves a conversation.The conversation ID.
Promise<{ message: string }>
listMessages
Lists messages in a conversation with keyset (before/after) pagination.The conversation ID.
Restrict to replies of this message (thread view).
Keyset cursor (ISO timestamp) — return messages created before this. Mutually
exclusive with
after.Keyset cursor (ISO timestamp) — return messages created after this. Mutually
exclusive with
before.Page size. Defaults to
50, max 100.Sort direction by creation time.
Comma-separated associations to populate, e.g.
"files".Optional filters.
filters.hasReplies (boolean): when true, returns only
messages that have thread replies (threadReplyCount > 0); when false, only
messages with none. Filters by thread replies, not quotings.Threads are one level deep, so hasReplies: true together with parentId
always returns an empty list — the response’s notice field explains why.Promise<{ messages: ChatMessage[]; hasMore: boolean; oldestCreatedAt: string | null; newestCreatedAt: string | null }>.
sendMessage
Sends a message to a conversation, optionally with file attachments. Whenfiles
is provided the request is sent as multipart/form-data (pass browser File /
Blob objects); otherwise it is a plain JSON body.
The conversation ID.
Message text.
An attached GIF, or
null.User mentions embedded in the message.
The message this is a threaded reply to.
A message being quoted.
Arbitrary key-value data attached to the message.
A client-generated ID echoed back on the created message (for optimistic UI);
not stored.
Up to 10 file attachments, as browser
File / Blob objects. Triggers a
multipart/form-data upload.Promise<ChatMessage>
getMessage
Fetches a single message by ID.The conversation ID.
The message ID.
Promise<ChatMessage>
editMessage
Edits an existing message.The conversation ID.
The message ID.
New message text.
A GIF URL, or
null to clear it.Updated mentions.
Updated metadata, or
null to clear it.Promise<ChatMessage>
deleteMessage
Deletes a message in a conversation.The conversation ID.
The message ID.
Promise<{ message: string; userDeletedAt?: string }> (userDeletedAt
is set when the author soft-deletes their own message).
reportMessage
Reports a message for moderation.The conversation ID.
The message ID.
Why the message is being reported.
Additional detail.
Promise<{ message: string; code: string }>
toggleReaction
Toggles (adds or removes) an emoji reaction on a message for the logged-in user.The conversation ID.
The message ID.
The reaction emoji (1–10 characters).
Promise<{ reactionCounts: Record<string, number>; userReactions: string[]; delta: 1 | -1 }>
listReactions
Lists the users who reacted to a message with a given emoji.The conversation ID.
The message ID.
The reaction emoji to list reactors for.
Page number. Defaults to
1.Results per page. Defaults to
50, max 100.Promise<{ data: MessageReaction[]; pagination: { page: number; limit: number; total: number; hasMore: boolean } }>,
where MessageReaction is { user: User; emoji: string; createdAt: Date }.
markAsRead
Marks a conversation as read up to a given message.The conversation ID.
The message up to which the conversation is marked read.
Promise<{ message: string }>
