The Messages interface provides methods for sending, receiving, and managing chat messages in a room. Access it via room.messages.
1
val messages = room.messagesProperties
The Messages interface has the following properties:
reactionsMessageReactionsSubscribe to messages
messages.subscribe(listener: MessageListener): MessagesSubscriptionSubscribe to chat message events in the room. This method allows you to listen for new messages and provides access to historical messages that occurred before the subscription was established.
The room must be attached for the listener to receive new message events.
1
2
3
4
5
6
7
8
9
val (unsubscribe, subscription) = room.messages.subscribe { event ->
println("Received message: ${event.message.text}")
}
// Get messages sent before subscribing
val history = subscription.historyBeforeSubscribe()
// To stop receiving messages
unsubscribe()Parameters
The subscribe() method takes the following parameters:
listenerrequiredMessageListenerReturns
MessagesSubscription
Returns a MessagesSubscription that extends Subscription. It supports destructuring into (unsubscribe, subscription).
Unsubscribe from messages
subscription.unsubscribe(): UnitCall unsubscribe() to stop listening for message events.
Get messages from before the subscription started
suspend subscription.historyBeforeSubscribe(start: Long? = null, end: Long? = null, limit: Int = 100): PaginatedResult<Message>Get messages sent to the room from before the subscription was established.
Parameters
The historyBeforeSubscribe() method takes the following parameters:
startoptionalLongendoptionalLonglimitoptionalInt100.Returns
This is a suspend function. It returns a PaginatedResult containing a list of Message objects, or throws a ChatException on failure.
Send a message
suspend messages.send(text: String, metadata: JsonObject? = null, headers: Map<String, String>? = null): MessageSend a message to the chat room. The message will be delivered to all subscribers in real-time.
This method uses the Ably Chat REST API and does not require the room to be attached.
1
2
3
val message = room.messages.send(text = "Hello, world!")
println("Message sent with serial: ${message.serial}")Parameters
The send() method takes the following parameters:
textrequiredStringmetadataoptionalJsonObjectheadersoptionalMap<String, String>Returns
This is a suspend function. It returns the sent Message object, or throws a ChatException on failure.
Get message history
suspend messages.history(start: Long? = null, end: Long? = null, limit: Int = 100, orderBy: OrderBy = OrderBy.NewestFirst): PaginatedResult<Message>Get messages that have been previously sent to the chat room. This method retrieves historical messages based on the provided query options, allowing you to paginate through message history, filter by time ranges, and control the order of results.
This method uses the Ably Chat REST API and does not require the room to be attached.
1
2
3
4
5
6
7
8
9
10
11
val history = room.messages.history(
limit = 50,
orderBy = OrderBy.NewestFirst
)
println("Messages: ${history.items}")
// Get next page if available
if (history.hasNext()) {
val nextPage = history.next()
}Parameters
The history() method takes the following parameters:
startoptionalLongendoptionalLonglimitoptionalInt100.orderByoptionalOrderByNewestFirst.Returns
This is a suspend function. It returns a PaginatedResult containing a list of Message objects, or throws a ChatException on failure.
Get a specific message
suspend messages.get(serial: String): MessageGet a specific message by its unique serial identifier.
This method uses the Ably Chat REST API and does not require the room to be attached.
1
2
val message = room.messages.get("01234567890@abcdefghij")
println("Message text: ${message.text}")Parameters
The get() method takes the following parameters:
serialrequiredStringReturns
This is a suspend function. It returns the Message object matching the given serial, or throws a ChatException on failure.
Update a message
suspend messages.update(serial: String, text: String, metadata: JsonObject? = null, headers: Map<String, String>? = null, operationDescription: String? = null, operationMetadata: Map<String, String>? = null): MessageUpdate a message in the chat room. This method modifies an existing message's content, metadata, or headers. The update creates a new version of the message while preserving the original serial identifier. Subscribers will receive an update event in real-time.
This method uses the Ably Chat REST API and does not require the room to be attached.
1
2
3
4
5
6
7
val updatedMessage = room.messages.update(
serial = message.serial,
text = "Updated message text",
operationDescription = "Fixed typo"
)
println("Message updated: ${updatedMessage.version}")An extension function overload is also available that accepts a Message object directly:
suspend Messages.update(updatedMessage: Message, operationDescription: String? = null, operationMetadata: Map<String, String>? = null): Message1
2
3
4
val updatedMessage = room.messages.update(
updatedMessage = message.copy(text = "Updated text"),
operationDescription = "Fixed typo"
)Parameters
The update() method takes the following parameters:
serialrequiredStringtextrequiredStringmetadataoptionalJsonObjectheadersoptionalMap<String, String>operationDescriptionoptionalStringoperationMetadataoptionalMap<String, String>Returns
This is a suspend function. It returns the updated Message object, or throws a ChatException on failure. The returned message will have its action property set to MessageUpdate.
Delete a message
suspend messages.delete(serial: String, operationDescription: String? = null, operationMetadata: Map<String, String>? = null): MessageDelete a message in the chat room. This method performs a "soft delete" on a message, marking it as deleted rather than permanently removing it. The deleted message will still be visible in message history but will be flagged as deleted. Subscribers will receive a deletion event in real-time.
This method uses the Ably Chat REST API and does not require the room to be attached.
1
2
3
4
5
6
val deletedMessage = room.messages.delete(
serial = message.serial,
operationDescription = "Removed inappropriate content"
)
println("Message deleted: ${deletedMessage.action}")An extension function overload is also available that accepts a Message object directly:
suspend Messages.delete(message: Message, operationDescription: String? = null, operationMetadata: Map<String, String>? = null): Message1
2
3
4
val deletedMessage = room.messages.delete(
message = message,
operationDescription = "Removed inappropriate content"
)Parameters
The delete() method takes the following parameters:
serialrequiredStringoperationDescriptionoptionalStringoperationMetadataoptionalMap<String, String>Returns
This is a suspend function. It returns the deleted Message object, or throws a ChatException on failure. The returned message will have its action property set to MessageDelete.
Collect messages as a Flow
Messages.asFlow(): Flow<ChatMessageEvent>Returns a Kotlin Flow that emits chat message events. This is an extension function on the Messages interface that provides a reactive alternative to listener-based subscriptions.
1
2
3
4
5
6
7
import kotlinx.coroutines.launch
launch {
room.messages.asFlow().collect { event ->
println("${event.message.clientId}: ${event.message.text}")
}
}Returns
Flow<ChatMessageEvent>
Returns a Flow that emits ChatMessageEvent events. The flow automatically manages the underlying subscription.
PaginatedResult
A PaginatedResult represents a page of results from a paginated query such as history() or historyBeforeSubscribe().
Properties
itemsList<Message>Check for more pages
hasNext(): BooleanReturns true if there are more pages available by calling next().
Get next page
suspend next(): PaginatedResult<Message>This is a suspend function. It returns the next page of results, or throws a ChatException on failure.
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import com.ably.chat.ChatMessageEventType
import com.ably.chat.OrderBy
import com.ably.chat.asFlow
import kotlinx.coroutines.launch
val room = chatClient.rooms.get("my-room")
room.attach()
// Subscribe to messages
val (unsubscribe, subscription) = room.messages.subscribe { event ->
val msg = event.message
when (event.type) {
ChatMessageEventType.Created ->
println("${msg.clientId}: ${msg.text}")
ChatMessageEventType.Updated ->
println("Message updated: ${msg.text}")
ChatMessageEventType.Deleted ->
println("Message deleted: ${msg.serial}")
}
}
// Or use Flow for reactive collection
launch {
room.messages.asFlow().collect { event ->
println("Message event: ${event.type}")
}
}
// Get recent history
val history = room.messages.history(limit = 10)
history.items.forEach { msg ->
println("[History] ${msg.clientId}: ${msg.text}")
}
// Send a message
val sent = room.messages.send(text = "Hello everyone!")
// Update the message
room.messages.update(
serial = sent.serial,
text = "Hello everyone! (edited)"
)
// Clean up
unsubscribe()