Messages

Open in

The Messages interface provides methods for sending, receiving, and managing chat messages in a room. Access it via room.messages.

Kotlin

1

val messages = room.messages

Properties

The Messages interface has the following properties:

Access to message reactions functionality for adding, removing, and subscribing to reactions on specific messages.

Subscribe to messages

messages.subscribe(listener: MessageListener): MessagesSubscription

Subscribe 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.

Kotlin

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:

listenerrequiredMessageListener
A callback function invoked when chat message events occur.

Returns

MessagesSubscription

Returns a MessagesSubscription that extends Subscription. It supports destructuring into (unsubscribe, subscription).

Unsubscribe from messages

subscription.unsubscribe(): Unit

Call 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:

startoptionalLong
Start of the time window to query, as a Unix timestamp in milliseconds.
endoptionalLong
End of the time window to query, as a Unix timestamp in milliseconds.
limitoptionalInt
Maximum number of messages to retrieve. Default: 100.
Returns

PaginatedResult<Message>

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): Message

Send 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.

Kotlin

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:

textrequiredString
The text content of the message.
metadataoptionalJsonObject
Extra information attached to the message for features like animations or linking to external resources.
headersoptionalMap<String, String>
Additional information in Ably message extras, usable for features like livestream timestamping or message flagging.

Returns

Message

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.

Kotlin

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:

startoptionalLong
Start of the time window to query, as a Unix timestamp in milliseconds.
endoptionalLong
End of the time window to query, as a Unix timestamp in milliseconds.
limitoptionalInt
Maximum number of messages to retrieve. Default: 100.
orderByoptionalOrderBy
Order in which to return results. Default: NewestFirst.

Returns

PaginatedResult<Message>

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): Message

Get 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.

Kotlin

1

2

val message = room.messages.get("01234567890@abcdefghij")
println("Message text: ${message.text}")

Parameters

The get() method takes the following parameters:

serialrequiredString
The unique serial identifier of the message to retrieve.

Returns

Message

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): Message

Update 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.

Kotlin

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): Message
Kotlin

1

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:

serialrequiredString
The unique identifier of the message to update.
textrequiredString
The new text content of the message.
metadataoptionalJsonObject
New metadata for the message.
headersoptionalMap<String, String>
New headers for the message.
operationDescriptionoptionalString
A human-readable description of why the update was performed.
operationMetadataoptionalMap<String, String>
Additional metadata about the operation. Do not use for authoritative information.

Returns

Message

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): Message

Delete 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.

Kotlin

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): Message
Kotlin

1

2

3

4

val deletedMessage = room.messages.delete(
    message = message,
    operationDescription = "Removed inappropriate content"
)

Parameters

The delete() method takes the following parameters:

serialrequiredString
The unique identifier of the message to delete.
operationDescriptionoptionalString
A human-readable description of why the message was deleted.
operationMetadataoptionalMap<String, String>
Additional metadata about the operation. Do not use for authoritative information.

Returns

Message

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.

Kotlin

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

The current page of results.

Check for more pages

hasNext(): Boolean

Returns 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

Kotlin

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()