---
url: https://talkjs.com/docs/Data_APIs/Swift/Messages/
title: "Messages | Swift | TalkJS Documentation"
---

For AI agents: Find a documentation index at https://talkjs.com/llms.txt (full content at https://talkjs.com/llms-full.txt). Get a markdown version of any page by appending .md to its URL path.

# Messages

Send, edit, and react to messages in a conversation.

A message contains some content that was sent in a conversation. Users send messages using [ConversationRef.send](https://talkjs.com/docs/Swift_Data_API/Conversations/#ConversationRef__send__1). You can track the a conversation's messages in real-time using [ConversationRef.subscribeMessages](https://talkjs.com/docs/Swift_Data_API/Conversations/#ConversationRef__subscribeMessages).

## struct MessageRef

References the message with a given message ID.

### Method Overview

<table class="my-0"><tbody><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageRef__delete" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">delete</a></td><td><p>Deletes this message, or does nothing if the message does not exist.</p></td></tr><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageRef__deleteFields" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">deleteFields</a></td><td><p>Deletes properties of this message.</p></td></tr><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageRef__edit" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">edit</a></td><td><p>Edits this message.</p></td></tr><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageRef__get" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">get</a></td><td><p>Fetches a snapshot of the message.</p></td></tr><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageRef__reaction" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">reaction</a></td><td><p>Get a reference to a specific emoji reaction on this message</p></td></tr></tbody></table>

### Properties

**conversationId**: String

The ID of the conversation that the referenced message belongs to.

Immutable: if you want to reference a message from a different conversation, get a new MessageRef from that conversation.

**id**: String

The ID of the referenced message.

Immutable: if you want to reference a different message, get a new MessageRef instead.

### delete

func _messageRef_.delete() async

Deletes this message, or does nothing if the message does not exist.

Deleting a nonexistent message is treated as success.

This function will throw if you are not a participant in the conversation or if your role does not give you permission to delete this message.

#### Returns

Void

### deleteFields

func _messageRef_.deleteFields(\_:) async

Deletes properties of this message.

Pass the name of each property to delete as a separate parameter to this function. To delete a field in the `custom` property, pass it as `custom.FIELD_TO_DELETE`.

#### Parameters

**fields _(unnamed)_**: String...

#### Returns

Void

### edit

func _messageRef_.edit(text:custom:) async

func _messageRef_.edit(content:custom:) async

Edits this message.

The function will throw if the request is invalid, the message doesn’t exist, or you do not have permission to edit that message.

#### Parameters

**text _(optional)_**: String?

The new text to set as the message body.

**custom _(optional)_**: \[String : String?\]?

Custom metadata you have set on the message. This value acts as a patch. Remove specific properties by calling [MessageRef.deleteFields](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageRef__deleteFields) Default = no custom metadata

**content**: \[any [SendContentBlock](https://talkjs.com/docs/Data_APIs/Swift/Message_Content/#SendContentBlock)\]

The new content for the message. Any value provided here will overwrite the existing message content. By default users do not have permission to send [Link](https://talkjs.com/docs/Data_APIs/Swift/Message_Content/#Link), [ActionLink](https://talkjs.com/docs/Data_APIs/Swift/Message_Content/#ActionLink), or [ActionButton](https://talkjs.com/docs/Data_APIs/Swift/Message_Content/#ActionButton), as they can be used to trick the recipient.

#### Returns

Void

### get

func _messageRef_.get() async -> [MessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot)?

Fetches a snapshot of the message.

#### Returns

[MessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot)?

A snapshot of the message’s attributes, or nil if the message doesn’t exist, the conversation doesn’t exist, or you’re not a participant in the conversation.

### reaction

func _messageRef_.reaction(emoji:) -> [ReactionRef](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionRef)

Get a reference to a specific emoji reaction on this message

If you call `.reaction` with an invalid emoji, it will still succeed and you will still get a [ReactionRef](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionRef). However, the TalkJS server will reject any calls that use an invalid emoji.

In the future, this will also be used to fetch a full list of people who used that specific reaction on the message.

Reacting to the message with a Unicode emoji

```swift
await MessageRef.reaction(emoji: "🚀").add()
```

Removing your custom emoji reaction from the message

```swift
await MessageRef.reaction(emoji: ":cat-roomba:").remove()
```

#### Parameters

**emoji**: String

The emoji for the reaction you want to reference. a single Unicode emoji like “🚀” or a custom emoji like “:cat\_roomba:”. Custom emoji can be up to 50 characters long.

#### Returns

[ReactionRef](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionRef)

A [ReactionRef](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionRef) for the reaction with that emoji on this message. Throws If the emoji is not a string or is an empty string

## struct MessageSnapshot

A snapshot of a message’s attributes at a given moment in time.

### Method Overview

<table class="my-0"><tbody><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot____" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">==</a></td><td><p>Inherited from <code class="px-[4px] py-[1.6px] rounded-[4px] bg-gray-200/75 text-gray-700">Equatable.==(_:_:)</code>.</p></td></tr></tbody></table>

### Properties

**content**: \[any [ContentBlock](https://talkjs.com/docs/Data_APIs/Swift/Message_Content/#ContentBlock)\]

The main body of the message, as a list of blocks that are rendered top-to-bottom.

**createdAt**: Int64

Time at which the message was sent, as a unix timestamp in milliseconds.

**custom**: \[String : String\]

Custom metadata you have set on the message

**editedAt _(optional)_**: Int64?

Time at which the message was last edited, as a unix timestamp in milliseconds. `nil` if the message has never been edited.

**id**: String

The unique ID that is used to identify the message in TalkJS

**origin**: [MessageOrigin](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageOrigin)

Where this message origiranted from:

-   .web = Message sent via the UI or via ConversationBuilder.sendMessage
-   .rest = Message sent via the REST API’s “send message” endpoint
-   .import = Message sent via the REST API’s “import messages” endpoint
-   .email = Message sent by replying to an email notification

**plaintext**: String

The contents of the message, as a plain text string without any formatting or attachments. Useful for showing in a conversation list or in notifications.

**reactions**: \[[ReactionSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionSnapshot)\]

All the emoji reactions that have been added to this message.

There can be up to 50 different reactions on each message.

**referencedMessage _(optional)_**: [ReferencedMessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReferencedMessageSnapshot)?

A snapshot of the message that this message is aa reply to, or `nil` if this message is not a reply.

Only UserMessages can reference other messages. The referenced message snapshot does not have a `referencedMessage` field. Instead, it has `referencedMessageId`. This prevents TalkJS fetching an unlimited number of messages in a long chain of replies.

**sender _(optional)_**: [UserSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Users/#UserSnapshot)?

A snapshot of the user who sent the message, or nil if it is a system message. The user’s attributes may have been updated since they sent the message, in which case this snapshot contains the updated data. It is not a historical snapshot.

**type**: [MessageType](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageType)

Whether this message was “from a user” or a general system message without a specific sender.

The `sender` property is always present for `.UserMessage` messages and never present for `.SystemMessage` messages.

### \==

func _messageSnapshot_.\==(\_:\_:) -> Bool

Inherited from `Equatable.==(_:_:)`.

#### Parameters

**lhs _(unnamed)_**: [MessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot)

**rhs _(unnamed)_**: [MessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot)

#### Returns

Bool

## struct ReferencedMessageSnapshot

A snapshot of a message’s attributes at a given moment in time, used in [MessageSnapshot.referencedMessage](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot__referencedMessage).

### Method Overview

<table class="my-0"><tbody><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReferencedMessageSnapshot____" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">==</a></td><td><p>Inherited from <code class="px-[4px] py-[1.6px] rounded-[4px] bg-gray-200/75 text-gray-700">Equatable.==(_:_:)</code>.</p></td></tr></tbody></table>

### Properties

**content**: \[any [ContentBlock](https://talkjs.com/docs/Data_APIs/Swift/Message_Content/#ContentBlock)\]

The main body of the message, as a list of blocks that are rendered top-to-bottom.

**createdAt**: Int64

Time at which the message was sent, as a unix timestamp in milliseconds

**custom**: \[String : String\]

Custom metadata you have set on the message

**editedAt _(optional)_**: Int64?

Time at which the message was last edited, as a unix timestamp in milliseconds. `nil` if the message has never been edited.

**id**: String

The unique ID that is used to identify the message in TalkJS

**origin**: [MessageOrigin](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageOrigin)

Where this message originated from:

-   .web = Message sent via the UI or via ConversationBuilder.sendMessage
-   .rest = Message sent via the REST API’s “send message” endpoint
-   .import = Message sent via the REST API’s “import messages” endpoint
-   .email = Message sent by replying to an email notification

**plaintext**: String

The contents of the message, as a plain text string without any formatting or attachments. Useful for showing in a conversation list or in notifications.

**reactions**: \[[ReactionSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionSnapshot)\]

All the emoji reactions that have been added to this message.

**referencedMessageId _(optional)_**: String?

The ID of the message that this message is a reply to, or nil if this message is not a reply.

Since this is a snapshot of a referenced message, we do not automatically expand its referenced message. The ID of its referenced message is provided here instead.

**sender _(optional)_**: [UserSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Users/#UserSnapshot)?

A snapshot of the user who sent the message. The user’s attributes may have been updated since they sent the message, in which case this snapshot contains the updated data. It is not a historical snapshot.

Guaranteed to be set, unlike in MessageSnapshot, because you cannot reference a SystemMessage

**type**: [MessageType](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageType)

Referenced messages are always `.UserMessage` because you cannot reply to a system message.

### \==

func _referencedMessageSnapshot_.\==(\_:\_:) -> Bool

Inherited from `Equatable.==(_:_:)`.

#### Parameters

**lhs _(unnamed)_**: [ReferencedMessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReferencedMessageSnapshot)

**rhs _(unnamed)_**: [ReferencedMessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReferencedMessageSnapshot)

#### Returns

Bool

## struct MessageSubscription

A subscription to the messages in a specific conversation.

### Method Overview

<table class="my-0"><tbody><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSubscription__loadMore" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">loadMore</a></td><td><p>Expand the window to include older messages</p></td></tr><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSubscription__unsubscribe" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">unsubscribe</a></td><td><p>Unsubscribe from this resource and stop receiving updates.</p></td></tr></tbody></table>

### Properties

**connected**: Deferred<[MessageSubscriptionState](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSubscriptionState)\>

Resolves when the subscription starts receiving updates from the server.

Wait for this promise if you want to perform some action as soon as the subscription is active.

The promise rejects if the subscription is terminated before it connects.

**state**: [MessageSubscriptionState](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSubscriptionState) { get }

The current state of the subscription

An enum with the following fields:

`type` is one of “pending”, “active”, “unsubscribed”, or “error”.

When `type` is “pending”, this property is MessageSubscriptionState.pending.

When `type` is “active”, this property is MessageSubscriptionState.active(latestSnapshot:loadedAll:).

When `type` is “unsubscribed”, this property is MessageSubscriptionState.unsubscribed.

When `type` is “error”, this property is MessageSubscriptionState.error(\_:).

**terminated**: Deferred<[MessageSubscriptionState](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSubscriptionState)\>

Resolves when the subscription permanently stops receiving updates from the server.

This is either because you unsubscribed or because the subscription encountered an unrecoverable error.

### loadMore

func _messageSubscription_.loadMore(count:) async

Expand the window to include older messages

Calling `loadMore` multiple times in parallel will still only load one page of messages.

#### Parameters

**count _(optional)_**: Int?

The number of additional messages to load. Must be between 1 and 100

#### Returns

Void

### unsubscribe

func _messageSubscription_.unsubscribe()

Unsubscribe from this resource and stop receiving updates.

If the subscription is already in the MessageSubscriptionState.unsubscribed or MessageSubscriptionState.error(\_:) state, this is a no-op.

#### Returns

Void

## enum MessageSubscriptionState

Values:

-   **pending**
-   **unsubscribed**
-   **active(latestSnapshot:loadedAll:)**
    
    `latestSnapshot`: The most recently received snapshot for the messages, or `nil` if you’re not a participant in the conversation.
    
    `loadedAll`: True if `latestSnapshot` contains all messages in the conversation. Use [MessageSubscription.loadMore](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSubscription__loadMore) to load more.
    
    **latestSnapshot _(optional)_**: \[[MessageSnapshot](https://talkjs.com/docs/Data_APIs/Swift/Messages/#MessageSnapshot)\]?
    
    **loadedAll**: Bool
    
-   **error(\_:)**
    
    The error that caused the subscription to be terminated
    
    **\_ _(unnamed)_**: TalkJSError
    

## enum MessageType

Values:

-   **UserMessage**
-   **SystemMessage**

## enum MessageOrigin

Values:

-   **web**
-   **rest**
-   **import**
-   **email**

## struct ReactionRef

References a specific emoji reaction on a message.

### Method Overview

<table class="my-0"><tbody><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionRef__add" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">add</a></td><td><p>Adds this emoji reaction onto the message, from the current user.</p></td></tr><tr class="flex flex-col flex-no-wrap sm:table-row"><td><a href="https://talkjs.com/docs/Data_APIs/Swift/Messages/#ReactionRef__remove" class="no-underline font-mono text-blue-500 hover:text-blue-600 font-medium">remove</a></td><td><p>Removes this emoji reaction from the message, from the current user.</p></td></tr></tbody></table>

### Properties

**conversationId**: String

The ID of the conversation the message belongs to.

Immutable: if you want to reference a message from a different conversation, get a new MessageRef from that conversation and call `.reaction` on that MessageRef.

**emoji**: String

Which emoji the reaction is using.

Either a single Unicode emoji, or the name of a custom emoji with a colon at the start and end. This is not validated until you send a request to the server. Since custom emoji are configured in the frontend, there are no checks to make sure a custom emoji actually exists.

Immutable: if you want to use a different emoji, get a new ReactionRef instead.

Unicode emoji “👍”

Custom emoji “:cat-roomba:”

**messageId**: String

The ID of the message that this is a reaction to.

Immutable: if you want to react to a different message, get a new ReactionRef instead.

### add

func _reactionRef_.add() async

Adds this emoji reaction onto the message, from the current user.

The function will throw if the request is invalid, the message doesn’t exist, there are already 50 different reactions on this message, or if you do not have permission to use emoji reactions on that message.

#### Returns

Void

### remove

func _reactionRef_.remove() async

Removes this emoji reaction from the message, from the current user.

The function will throw if the request is invalid, the message doesn’t exist, or you do not have permission to use emoji reactions on that message.

#### Returns

Void

## struct ReactionSnapshot

A summary of a single emoji reaction on a message.

### Properties

**count**: Int

The number of times this emoji has been added to the message.

**currentUserReacted**: Bool

Whether the current user has reacted to the message with this emoji.

**emoji**: String

Which emoji the users reacted with.

Either a single Unicode emoji, or the name of a custom emoji with a colon at the start and end. Since custom emoji are defined in the frontend, they are not validated by the TalkJS server. The UI should ignore reactions that use unrecognised custom emoji.

NOTE: In unicode, it is possible to have multiple emoji that look identical but are represented differently. For example, `"👍" != "👍️"` because the second emoji includes a variation selector 16 codepoint. This codepoint forces the character to appear as an emoji.

TalkJS normalises all emoji reactions to be “fully qualified” according to this list. This prevents a message having multiple separate 👍 reactions.

Be careful when processing the `emoji` property, as this normalisation might break equality checks:

```swift
// Emoji has unnecessary variation selector 16
let sent = "👍"

// React with thumbs up,
await message.reaction(emoji: emoji).add()

// Fetch the reaction
let snapshot = await message.get()
let received = snapshot!.reactions[0].emoji

// Fails because TalkJS removed the variation selector
assert(sent == received)
```

Unicode emoji “👍”

Custom emoji “:cat-roomba:”
