Skip to content

Read conversations and messages

messages() uses the filters below. Kotlin and Swift also expose enrichedMessages() with the same filters. Browser and Node do not expose a separate enrichedMessages() method because messages() already returns enriched messages. Browser and Node call the sent-time fields sentBeforeNs and sentAfterNs. Kotlin and Swift call them beforeNs and afterNs.

OptionDefaultDescription
limitNoneMaximum result count
sentBeforeNs / beforeNsNoneMessages sent before this time
sentAfterNs / afterNsNoneMessages sent after this time
insertedBeforeNs, insertedAfterNsNoneFilter by local insertion time
sortBysentAtSort by sent or inserted time
directionPlatform-specificAscending or descending
deliveryStatusAllPublished, unpublished, or failed
contentTypes, excludeContentTypesAll / noneInclude or exclude content types
excludeSenderInboxIdsNoneExclude sender inbox IDs

Kotlin and Swift default to descending order. Browser and Node default to ascending order. Pass direction when order matters.

countMessages() returns a count without loading messages. It uses the content, sender, status, and time filters, but does not accept limit or direction.

const
const messages: DecodedMessage<unknown>[]
messages
= await
conversation: Conversation<unknown>
conversation
.
Conversation<unknown>.messages(options?: ListMessagesOptions): Promise<DecodedMessage<unknown>[]>

Lists messages in this conversation

@paramoptions - Optional filtering and pagination options

@returnsPromise that resolves with an array of decoded messages

messages
({
ListMessagesOptions.limit?: bigint | undefined
limit
: 10n });

On Kotlin and Swift, enrichedMessages() retrieves messages with reactions, replies, and other associated data included. Browser and Node messages() provides the same enriched result.

Be sure to handle content types properly by using the generic content<T>() method with the appropriate type for reactions and replies.

By default, messages are sorted by their sentAtNs timestamp (time when the message was sent). When you sort by sentAtNs, messages might arrive out of order. For example, a message sent 5 minutes ago might arrive in the local database after a message sent 1 minute ago. This can cause pagination issues, where you might miss messages when loading the next page.

Kotlin and Swift can avoid this issue. They can sort by insertedAtNs (time when the message was inserted into the local database). Insertion timestamps are strictly sequential in the local database. Browser and Node do not expose insertedAtNs on decoded messages. Their supported cursor is sentAtNs. Messages with the same sentAtNs value can cross a page boundary, so deduplicate messages by ID.

Here is how to paginate messages with the cursor that each SDK exposes:

const
const firstPage: DecodedMessage<unknown>[]
firstPage
= await
group: Group<unknown>
group
.
Conversation<unknown>.messages(options?: ListMessagesOptions): Promise<DecodedMessage<unknown>[]>

Lists messages in this conversation

@paramoptions - Optional filtering and pagination options

@returnsPromise that resolves with an array of decoded messages

messages
({
ListMessagesOptions.limit?: bigint | undefined
limit
: 20n,
ListMessagesOptions.sortBy?: MessageSortBy | undefined
sortBy
:
enum MessageSortBy
MessageSortBy
.
function (enum member) MessageSortBy.SentAt = 0
SentAt
,
ListMessagesOptions.direction?: SortDirection | undefined
direction
:
enum SortDirection
SortDirection
.
function (enum member) SortDirection.Descending = 1
Descending
,
});
const
const secondPage: DecodedMessage<unknown>[]
secondPage
= await
group: Group<unknown>
group
.
Conversation<unknown>.messages(options?: ListMessagesOptions): Promise<DecodedMessage<unknown>[]>

Lists messages in this conversation

@paramoptions - Optional filtering and pagination options

@returnsPromise that resolves with an array of decoded messages

messages
({
ListMessagesOptions.limit?: bigint | undefined
limit
: 20n,
ListMessagesOptions.sortBy?: MessageSortBy | undefined
sortBy
:
enum MessageSortBy
MessageSortBy
.
function (enum member) MessageSortBy.SentAt = 0
SentAt
,
ListMessagesOptions.direction?: SortDirection | undefined
direction
:
enum SortDirection
SortDirection
.
function (enum member) SortDirection.Descending = 1
Descending
,
ListMessagesOptions.sentBeforeNs?: bigint | undefined
sentBeforeNs
:
const firstPage: DecodedMessage<unknown>[]
firstPage
.
Array<DecodedMessage<unknown>>.at(index: number): DecodedMessage<unknown> | undefined

Returns the item located at the specified index.

@paramindex The zero-based index of the desired code unit. A negative index will count back from the last item.

at
(-1)?.
DecodedMessage<unknown>.sentAtNs: bigint | undefined
sentAtNs
,
});

We recommend listing allowed conversations only. This ensures that spammy conversations don’t appear in the main inbox.

MethodReturns
conversations.list(options)Groups and DMs
conversations.listGroups(options)Groups only
conversations.listDms(options)DMs only
const
const conversations: (Group<BuiltInContentTypes> | Dm<BuiltInContentTypes>)[]
conversations
= await
client: Client<BuiltInContentTypes>
client
.
Client<BuiltInContentTypes>.conversations: Conversations<BuiltInContentTypes>

Gets the conversations manager for this client

conversations
.
Conversations<BuiltInContentTypes>.list(options?: ListConversationsOptions): Promise<(Group<BuiltInContentTypes> | Dm<BuiltInContentTypes>)[]>

Lists all conversations with optional filtering

@paramoptions - Optional filtering and pagination options

@returnsPromise that resolves with an array of conversations

list
();
OptionDefaultDescription
consentStatesAllowed and unknownConsent states to include
conversationTypeBothGroups or DMs
limitNoneMaximum result count
orderByPlatform-specificCreation or last activity
createdBeforeNs, createdAfterNsNoneCreation-time bounds
lastActivityBeforeNs, lastActivityAfterNsNoneKotlin and Swift only
includeDuplicateDmsfalseInclude every underlying stitched DM

Paginate with orderBy: 'createdAt' and createdBeforeNs. This stable sort prevents a conversation from moving between pages while you read them.

Browser and Node default orderBy to createdAt. Kotlin and Swift default it to lastActivity. Pass it explicitly when order matters.

Do not use with streaming

Do not paginate a conversation list while a conversation stream adds items to that same list. Keep the stream and paginated result separate until pagination ends.