Skip to main content
The chat module is the server-side client for Sublay’s messaging: direct and group conversations, messages (with GIFs, mentions, threads, quotes, and file attachments), membership, reactions, read state, and reporting.

Acting on behalf of a user

Your service key has no implicit session user, so every chat call takes the user it acts as. Most functions take that user as userId; the few where userId already names a target take the actor as actingUserId instead (createDirectConversation, addMember, removeMember, changeMemberRole).
Membership is enforced against the acting user (resolve-then-check). Sublay resolves the named user first, then runs the normal conversation checks against that user. So you can only act as a user who is genuinely a member of the conversation, and admin-only actions (delete/update conversation, add/remove members, change roles) require that user to be a group admin. A service key cannot post into a conversation as a user who isn’t in it.
Naming a user other than the caller’s own is gated to service/master keys. With a service key, omitting the acting user returns 400 chat/missing-user-id.

Conversations

listConversations

Lists the acting user’s conversations, newest activity first. Uses cursor (keyset) pagination — pass the last item’s lastMessageAt as cursor and its createdAt as cursorCreatedAt to get the next page.
userId
string
required
The user whose conversations are listed.
types
string
Comma-separated filter: any of direct, group, space.
cursor
string
Keyset cursor — the lastMessageAt of the last item from the previous page.
cursorCreatedAt
string
Tie-breaker cursor — the createdAt of the last item from the previous page.
limit
number
Page size, 1–50. Defaults to 20.
ReturnsPromise<{ conversations: ConversationPreview[]; hasMore: boolean }> Each ConversationPreview includes otherMembers — up to 5 active members other than the acting 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) one-to-one conversation between the acting user and a target user.
userId
string
required
The other participant (the target).
actingUserId
string
required
The user initiating the DM.
ReturnsPromise<Conversation>

createGroupConversation

Creates a group conversation; the acting user becomes its admin.
userId
string
required
The acting user (becomes the group admin).
name
string
Group name.
description
string
Group description.
memberIds
string[]
Initial members to add.
metadata
object
Custom key-value data.
ReturnsPromise<Conversation>

getConversation

Fetches a single conversation the acting user is a member of.
conversationId
string
required
userId
string
required
The acting user (must be a member).
ReturnsPromise<Conversation>

updateConversation

Updates a group conversation. Requires the acting user to be a group admin.
conversationId
string
required
userId
string
required
The acting user (must be a group admin).
name
string
description
string
avatarFileId
string | null
File id for the avatar, or null to clear it.
postingPermission
"members" | "admins"
Space conversations only.
ReturnsPromise<Conversation>

deleteConversation

Deletes a group conversation. Requires the acting user to be a group admin.
conversationId
string
required
userId
string
required
The acting user (must be a group admin).
ReturnsPromise<void>

getUnreadCount

Returns the acting user’s unread totals across all conversations.
userId
string
required
ReturnsPromise<{ totalUnread: number; unreadConversationCount: number }>

Members

listMembers

conversationId
string
required
userId
string
required
The acting user (must be a member).
page
number
Defaults to 1.
limit
number
1–100, defaults to 50.
role
"admin" | "member"
Filter by role.
ReturnsPromise<PaginatedResponse<ConversationMember>>

addMember

Adds a member to a group. Requires the acting caller to be a group admin.
conversationId
string
required
userId
string
required
The member to add (the target).
actingUserId
string
required
The caller (must be a group admin).
ReturnsPromise<ConversationMember>

removeMember

Removes a member from a group. Requires the acting caller to be a group admin.
conversationId
string
required
userId
string
required
The member to remove (the target).
actingUserId
string
required
The caller (must be a group admin).
ReturnsPromise<void>

changeMemberRole

Promotes or demotes a member. Requires the acting caller to be a group admin.
conversationId
string
required
userId
string
required
The member whose role changes (the target).
role
"admin" | "member"
required
actingUserId
string
required
The caller (must be a group admin).
ReturnsPromise<ConversationMember>

leaveConversation

conversationId
string
required
userId
string
required
The user leaving.
ReturnsPromise<void>

Messages

listMessages

Lists messages in a conversation. Uses cursor pagination — pass before (an ISO timestamp) to page backwards, or after to page forwards (before/after are mutually exclusive).
conversationId
string
required
userId
string
required
The acting user (must be a member).
parentId
string
Restrict to replies of this message (thread view).
before
string
ISO timestamp — messages created before this. Mutually exclusive with after.
after
string
ISO timestamp — messages created after this. Mutually exclusive with before.
limit
number
1–100, defaults to 50.
sort
"asc" | "desc"
include
string
Comma-separated associations to populate, e.g. "files".
filters
MessageFilters
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.
ReturnsPromise<{ messages: ChatMessage[]; hasMore: boolean; oldestCreatedAt: string | null; newestCreatedAt: string | null }>

sendMessage

Sends a message as the acting user. A message must have content, a GIF, or at least one file. When files are attached the request is sent as multipart/form-data; otherwise it’s a JSON body.
conversationId
string
required
userId
string
required
The message author (must be a member).
content
string
Up to 4000 characters.
gif
GifData | null
An attached GIF object.
mentions
Mention[]
User/space mentions.
parentMessageId
string
Reply within a thread.
quotedMessageId
string
Quote another message.
metadata
object
Custom key-value data.
localId
string
Client-generated id echoed back on the created message (not stored).
files
ChatMessageFile[]
Attachments: { file: Uint8Array | Blob; filename?: string; mimeType?: string }[], up to 10.
ReturnsPromise<ChatMessage>

getMessage

conversationId
string
required
messageId
string
required
userId
string
required
The acting user (must be a member).
ReturnsPromise<ChatMessage>

editMessage

Edits a message. Requires the acting user to be the message author.
conversationId
string
required
messageId
string
required
userId
string
required
The acting user (must be the message author).
content
string
gif
string | null
A GIF URL, or null to clear it.
mentions
Mention[]
metadata
object | null
ReturnsPromise<ChatMessage>

deleteMessage

Soft-deletes a message. Requires the acting user to be the author or a group admin.
conversationId
string
required
messageId
string
required
userId
string
required
The acting user (author or group admin).
ReturnsPromise<void>

reportMessage

Reports a message for moderation.
conversationId
string
required
messageId
string
required
userId
string
required
The reporting user (must be a member).
reason
string
required
Up to 200 characters.
details
string
Up to 1000 characters.
ReturnsPromise<{ message: string; code: string }>

Reactions

toggleReaction

Adds or removes the acting user’s emoji reaction on a message.
conversationId
string
required
messageId
string
required
emoji
string
required
userId
string
required
The reacting user (must be a member).
ReturnsPromise<{ reactionCounts: Record<string, number>; userReactions: string[]; delta: 1 | -1 }> (delta is 1 if the reaction was added, -1 if removed).

listReactions

Lists the users who reacted with a given emoji.
conversationId
string
required
messageId
string
required
emoji
string
required
The emoji to list reactors for.
userId
string
required
The acting user (must be a member).
page
number
Defaults to 1.
limit
number
1–100, defaults to 50.
ReturnsPromise<{ data: MessageReaction[]; pagination: { page; limit; total; hasMore } }>

Read state

markAsRead

Marks the conversation read up to a given message.
conversationId
string
required
messageId
string
required
The message up to which the conversation is marked read.
userId
string
required
The acting user (must be a member).
ReturnsPromise<void>

muteConversation

Sets or clears a user’s mute on a conversation. Muting suppresses the message push for this conversation only; the message is still delivered. See Notification Preferences & Mute.
Like every other chat call, the Node SDK names the acting user with userId (the service key acts on that user’s behalf). The user must be a member of the conversation, and the returned currentMember is that user’s own row. End-user-token clients (the React hooks, the browser JS SDK) act on the signed-in user and omit userId.
conversationId
string
required
duration
"8h" | "24h" | "1w" | "forever" | null
required
The mute duration choice, or null to clear the mute. Send the choice, never a raw timestamp.
userId
string
required
The user whose mute is set (must be a member).
ReturnsPromise<{ currentMember: ConversationMember }> — that user’s own member row.
“Forever” is an explicit signal. A forever mute returns mutedForever: true with mutedUntil: null. A timed mute returns mutedForever: false with a real ISO mutedUntil. Read the boolean — never string-match a far-future date.

Space conversations

Each space has a single built-in conversation. These three live on client.spaces (they’re /spaces/... routes), not on client.chat.

spaces.getSpaceConversation

Fetches-or-creates a space’s conversation and joins the acting user to it. The acting user must be a non-banned member of the space.
spaceId
string
required
userId
string
required
The acting user (must be a space member).
ReturnsPromise<Conversation>

spaces.moderateSpaceChatMessage

Removes a message in a space conversation.
Unlike the conversation-scoped chat calls, the two space-chat moderation routes are service-key god-mode — your service key passes the space-moderator check automatically. actingUserId here is attribution only (who moderated); omit it for a backend/system action.
spaceId
string
required
messageId
string
required
moderationStatus
"removed"
required
moderationReason
string
actingUserId
string
Acting moderator, for attribution.
ReturnsPromise<{ message: string; moderationStatus: string }>

spaces.handleSpaceChatReport

Resolves a report against a space-conversation message: remove the message, ban the user, and/or dismiss.
spaceId
string
required
reportId
string
required
actions
("remove-message" | "ban-user" | "dismiss")[]
required
dismiss cannot be combined with the other actions.
messageId
string
Required when actions include remove-message.
userId
string
The user to ban (target); required when actions include ban-user.
reason
string
summary
string
Stored as the report’s resolution note.
actingUserId
string
Acting moderator, for attribution.
ReturnsPromise<{ message: string; code: string }>