Skip to main content
The 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.
const { conversations, hasMore } = await sublay.chat.listConversations({
  types: "direct,group",
  limit: 20,
});

// Next page: pass the last item's lastMessageAt + createdAt as cursors.
const last = conversations[conversations.length - 1];
const next = await sublay.chat.listConversations({
  cursor: last.lastMessageAt,
  cursorCreatedAt: last.createdAt,
});
types
string
Comma-separated conversation types to include, e.g. "direct,group,space".
cursor
string
Keyset cursor — the lastMessageAt (ISO datetime) of the last item from the previous page.
cursorCreatedAt
string
Tie-breaker cursor — the createdAt (ISO datetime) of the last item from the previous page.
limit
number
Page size. Defaults to 20, max 50.
ReturnsPromise<{ 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.
const conversation = await sublay.chat.createDirectConversation({
  userId: "usr_abc123",
});
userId
string
required
The other participant’s Sublay user ID.
ReturnsPromise<Conversation>

createGroupConversation

Creates a group conversation.
const conversation = await sublay.chat.createGroupConversation({
  name: "Design Team",
  memberIds: ["usr_abc123", "usr_def456"],
});
name
string
Group name.
description
string
Group description.
memberIds
string[]
Sublay user IDs to add to the group. Defaults to an empty list.
metadata
object
Arbitrary key-value data attached to the conversation.
ReturnsPromise<Conversation>

getConversation

Fetches a single conversation by ID.
const conversation = await sublay.chat.getConversation({
  conversationId: "cnv_abc123",
});
conversationId
string
required
The conversation ID.
ReturnsPromise<Conversation>

updateConversation

Updates a conversation’s settings.
const conversation = await sublay.chat.updateConversation({
  conversationId: "cnv_abc123",
  name: "Renamed Group",
});
conversationId
string
required
The conversation ID.
name
string
New name.
description
string
New description.
avatarFileId
string | null
File ID for the conversation avatar, or null to clear it.
postingPermission
"members" | "admins"
Space conversations only: who may post.
ReturnsPromise<Conversation>

deleteConversation

Deletes a conversation.
await sublay.chat.deleteConversation({ conversationId: "cnv_abc123" });
conversationId
string
required
The conversation ID.
ReturnsPromise<{ message: string }>

getUnreadCount

Returns the user’s total unread message count and unread-conversation count. Takes no arguments.
const { totalUnread, unreadConversationCount } = await sublay.chat.getUnreadCount();
ReturnsPromise<{ totalUnread: number; unreadConversationCount: number }>

listMembers

Lists the members of a conversation (standard page-based pagination).
const { data, pagination } = await sublay.chat.listMembers({
  conversationId: "cnv_abc123",
  page: 1,
  limit: 50,
});
conversationId
string
required
The conversation ID.
page
number
Page number (1-indexed).
limit
number
Results per page.
role
"admin" | "member"
Filter members by role.
ReturnsPromise<PaginatedResponse<ConversationMember>>

addMember

Adds a user as a member of a conversation.
const member = await sublay.chat.addMember({
  conversationId: "cnv_abc123",
  userId: "usr_def456",
});
conversationId
string
required
The conversation ID.
userId
string
required
The user to add (the target member).
ReturnsPromise<ConversationMember>

removeMember

Removes a member from a conversation.
await sublay.chat.removeMember({
  conversationId: "cnv_abc123",
  userId: "usr_def456",
});
conversationId
string
required
The conversation ID.
userId
string
required
The member to remove (the target).
ReturnsPromise<{ message: string }>

changeMemberRole

Changes a member’s role within a conversation.
const member = await sublay.chat.changeMemberRole({
  conversationId: "cnv_abc123",
  userId: "usr_def456",
  role: "admin",
});
conversationId
string
required
The conversation ID.
userId
string
required
The member whose role to change (the target).
role
"admin" | "member"
required
The new role.
ReturnsPromise<ConversationMember>

leaveConversation

The logged-in user leaves a conversation.
await sublay.chat.leaveConversation({ conversationId: "cnv_abc123" });
conversationId
string
required
The conversation ID.
ReturnsPromise<{ message: string }>

listMessages

Lists messages in a conversation with keyset (before/after) pagination.
const { messages, hasMore, oldestCreatedAt } = await sublay.chat.listMessages({
  conversationId: "cnv_abc123",
  limit: 50,
  sort: "desc",
});

// Older page: pass the oldest message's timestamp as `before`.
const older = await sublay.chat.listMessages({
  conversationId: "cnv_abc123",
  before: oldestCreatedAt,
});

// Only messages that have thread replies.
const withReplies = await sublay.chat.listMessages({
  conversationId: "cnv_abc123",
  filters: { hasReplies: true },
});
conversationId
string
required
The conversation ID.
parentId
string
Restrict to replies of this message (thread view).
before
string
Keyset cursor (ISO timestamp) — return messages created before this. Mutually exclusive with after.
after
string
Keyset cursor (ISO timestamp) — return messages created after this. Mutually exclusive with before.
limit
number
Page size. Defaults to 50, max 100.
sort
"asc" | "desc"
Sort direction by creation time.
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 to a conversation, optionally with file attachments. When files is provided the request is sent as multipart/form-data (pass browser File / Blob objects); otherwise it is a plain JSON body.
const input = document.querySelector('input[type="file"]');

const message = await sublay.chat.sendMessage({
  conversationId: "cnv_abc123",
  content: "Here's the doc 👇",
  files: Array.from(input.files), // up to 10 File/Blob attachments
});
conversationId
string
required
The conversation ID.
content
string
Message text.
gif
GifData | null
An attached GIF, or null.
mentions
Mention[]
User mentions embedded in the message.
parentMessageId
string
The message this is a threaded reply to.
quotedMessageId
string
A message being quoted.
metadata
object
Arbitrary key-value data attached to the message.
localId
string
A client-generated ID echoed back on the created message (for optimistic UI); not stored.
files
(Blob | File)[]
Up to 10 file attachments, as browser File / Blob objects. Triggers a multipart/form-data upload.
ReturnsPromise<ChatMessage>

getMessage

Fetches a single message by ID.
const message = await sublay.chat.getMessage({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
});
conversationId
string
required
The conversation ID.
messageId
string
required
The message ID.
ReturnsPromise<ChatMessage>

editMessage

Edits an existing message.
const message = await sublay.chat.editMessage({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
  content: "Edited text",
});
conversationId
string
required
The conversation ID.
messageId
string
required
The message ID.
content
string
New message text.
gif
string | null
A GIF URL, or null to clear it.
mentions
Mention[]
Updated mentions.
metadata
object | null
Updated metadata, or null to clear it.
ReturnsPromise<ChatMessage>

deleteMessage

Deletes a message in a conversation.
await sublay.chat.deleteMessage({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
});
conversationId
string
required
The conversation ID.
messageId
string
required
The message ID.
ReturnsPromise<{ message: string; userDeletedAt?: string }> (userDeletedAt is set when the author soft-deletes their own message).

reportMessage

Reports a message for moderation.
const result = await sublay.chat.reportMessage({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
  reason: "spam",
});
conversationId
string
required
The conversation ID.
messageId
string
required
The message ID.
reason
string
required
Why the message is being reported.
details
string
Additional detail.
ReturnsPromise<{ message: string; code: string }>

toggleReaction

Toggles (adds or removes) an emoji reaction on a message for the logged-in user.
const { reactionCounts, userReactions, delta } = await sublay.chat.toggleReaction({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
  emoji: "👍",
});
// delta is +1 if the reaction was added, -1 if removed.
conversationId
string
required
The conversation ID.
messageId
string
required
The message ID.
emoji
string
required
The reaction emoji (1–10 characters).
ReturnsPromise<{ reactionCounts: Record<string, number>; userReactions: string[]; delta: 1 | -1 }>

listReactions

Lists the users who reacted to a message with a given emoji.
const { data, pagination } = await sublay.chat.listReactions({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
  emoji: "👍",
});
conversationId
string
required
The conversation ID.
messageId
string
required
The message ID.
emoji
string
required
The reaction emoji to list reactors for.
page
number
Page number. Defaults to 1.
limit
number
Results per page. Defaults to 50, max 100.
ReturnsPromise<{ 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.
await sublay.chat.markAsRead({
  conversationId: "cnv_abc123",
  messageId: "msg_xyz789",
});
conversationId
string
required
The conversation ID.
messageId
string
required
The message up to which the conversation is marked read.
ReturnsPromise<{ message: string }>