Messages Overview

LAST EDIT Mar 01 2021

Let's dive right into it, the example below shows how to send a simple message using Stream:

1
2
3
const message = await channel.sendMessage({ 
    text: '@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.', 
});
1
2
3
4
5
6
7
8
9
10
11
ChannelClient channelClient = client.channel("messaging", "general"); 
Message message = new Message(); 
message.setText("Josh, I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish."); 
 
channelClient.sendMessage(message).enqueue(result -> { 
    if (result.isSuccess()) { 
        Message sentMessage = result.data(); 
    } else { 
        // Handle result.error() 
    } 
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import StreamChat 
 
/// 1: Create a `ChannelId` that represents the channel you want to send a message to. 
let channelId = ChannelId(type: .messaging, id: "general") 
 
/// 2: Use the `ChatClient` to create a `ChatChannelController` with the `ChannelId`. 
let channelController = chatClient.channelController(for: channelId) 
 
/// 3: Call `ChatChannelController.createNewMessage` to create the message. 
channelController.createNewMessage(text: "Hello") { result in 
    switch result { 
    case .success(let messageId): 
        print(messageId) 
    case .failure(let error): 
        print(error) 
    } 
}
1
2
3
4
5
6
7
8
9
10
11
12
val channelClient = client.channel("messaging", "general") 
val message = Message( 
    text = "Josh, I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish." 
) 
 
channelClient.sendMessage(message).enqueue { result -> 
    if (result.isSuccess) { 
        val sentMessage: Message = result.data() 
    } else { 
        // Handle result.error() 
    } 
}
1
2
3
4
5
final message = Message( 
  text: '@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.' 
); 
 
await channel.sendMessage(message);
1
2
3
4
5
6
// Sending a message from jenny mentioning bob-1 
 
$message = $channel->sendMessage([ 
	'text' => '@Bob I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.', 
	], 
	'jenny');
1
2
3
4
5
message = { 
    "text": "@Bob I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.", 
} 
 
channel.send_message(message, user_id)
1
2
3
4
5
message := &stream_chat.Message{ 
	Text: "@Bob I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.", 
} 
 
filledMessage, err := channel.SendMessage(message, userID)

Note how server side SDKs require that you specify user_id to indicate who is sending the message. You can add custom fields to both the message and the attachments. There's a 5KB limit for the custom fields. File uploads are uploaded to the CDN so don't count towards this 5KB limit.

nametypedescriptiondefaultoptional
textstringThe text of the chat message (Stream chat supports markdown and automatically enriches URLs).
attachmentsarrayA list of attachments (audio, videos, images, and text). Max is 10 attachments per message. Each attachment can have up to 5KB.
userobjectThis value is automatically set in client-side mode. You only need to send this value when using the server-side APIs.
mentioned_usersarrayA list of users mentioned in the message. You send this as a list of user IDs and receive back the full user data.
message custom dataobjectExtra data for the message. Must not exceed 5KB in size.
skip_pushbooldo not send a push notificationfalse

Complex ExampleCopied!

A more complex example for creating a message is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const message = await channel.sendMessage({ 
    text: '@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.', 
    attachments: [ 
        { 
            type: 'image', 
            asset_url: 'https://bit.ly/2K74TaG', 
            thumb_url: 'https://bit.ly/2Uumxti', 
            myCustomField: 123 
        } 
    ], 
    skip_push: true 
    mentioned_users: [josh.id], 
    anotherCustomField: 234 
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Create an image attachment 
Attachment attachment = new Attachment(); 
attachment.setType("image"); 
attachment.setImageUrl("https://bit.ly/2K74TaG"); 
attachment.setThumbUrl("https://bit.ly/2Uumxti"); 
attachment.getExtraData().put("myCustomField", 123); 
 
// Create a message with the attachment and a user mention 
Message message = new Message(); 
message.setText("@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish."); 
message.getAttachments().add(attachment); 
message.setMentionedUsersIds(Arrays.asList("josh-id")); 
message.getExtraData().put("anotherCustomField", 234); 
 
// Send the message to the channel 
channelClient.sendMessage(message).enqueue(result -> { /* ... */ });
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
import StreamChat 
 
/// This example will add a custom attachment to a message 
 
/// 1: Create a `ChannelId` that represents the channel you want to send a message to. 
let channelId = ChannelId(type: .messaging, id: "general") 
 
/// 2: Use the `ChatClient` to create a `ChatChannelController` with the `ChannelId`. 
let channelController = chatClient.channelController(for: channelId) 
 
/// 3: Create a product structure that conforms to `AttachmentEnvelope` 
struct ProductAttachment: AttachmentEnvelope { 
    var type: AttachmentType = .image 
     
    let id: String 
    let name: String 
    let price: Int 
} 
 
/// 4: Instantiate the product attachment 
let iPhone = ProductAttachment(id: "iPhone13,3", name: "iPhone 12 Pro", price: 999) 
 
/// 4: Call `ChatChannelController.createNewMessage` to create the message with the custom attachment. 
channelController.createNewMessage(text: "Hello", attachments: [iPhone])  { result in 
    switch result { 
    case .success(let messageId): 
        print(messageId) 
    case .failure(let error): 
        print(error) 
    } 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Create an image attachment 
val attachment = Attachment( 
    type = "image", 
    imageUrl = "https://bit.ly/2K74TaG", 
    thumbUrl = "https://bit.ly/2Uumxti", 
    extraData = mutableMapOf("myCustomField" to 123), 
) 
 
// Create a message with the attachment and a user mention 
val message = Message( 
    text = "@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.", 
    attachments = mutableListOf(attachment), 
    mentionedUsersIds = mutableListOf("josh-id"), 
    extraData = mutableMapOf("anotherCustomField" to 234), 
) 
 
// Send the message to the channel 
channelClient.sendMessage(message).enqueue { /* ... */ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
final message = Message( 
  text: '@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.', 
  attachments: [ 
    Attachment( 
      type: "image", 
      assetUrl: "https://bit.ly/2K74TaG", 
      thumbUrl: "https://bit.ly/2Uumxti", 
      extraData: { 
        "myCustomField": 123, 
      } 
    ), 
  ], 
  mentionedUsers: [ 
    User(id: "josh") 
  ], 
  extraData: { 
    "anotherCustomField": 234, 
  }, 
); 
 
await channel.sendMessage(message);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Sending a message from jenny mentioning bob-1 
 
$message = $channel->sendMessage([ 
	'text' => '@Bob I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.', 
	'attachments' => 
		[ 
			[ 
				'type' => 'image', 
				'asset_url' => 'https://bit.ly/2K74TaG', 
				'thumb_url' => 'https://bit.ly/2Uumxti', 
				'myCustomField' => 123 
			] 
 
		], 
	'mentioned_users' => ['bob-1'], 
	'anotherCustomField' => 456 
	], 
	'jenny');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
message = { 
    "text": "@Bob I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.", 
    "attachments": [ 
        { 
            "type": "image", 
            "asset_url": "https://bit.ly/2K74TaG", 
            "thumb_url": "https://bit.ly/2Uumxti", 
            "myCustomField": 123, 
        } 
    ], 
    "mentioned_users": ["bob-1"], 
    "anotherCustomField": 456, 
} 
 
channel.send_message(message, user_id)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
message := &stream_chat.Message{ 
	Text: "@Bob I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.", 
	Attachments: []*stream_chat.Attachment{ 
		&stream_chat.Attachment{ 
			Type:     "image", 
			ThumbURL: "https://bit.ly/2K74TaG", 
			AssetURL: "https://bit.ly/2Uumxti", 
			ExtraData: map[string]interface{}{ 
				"myCustomField": 123, 
			}, 
		}, 
	}, 
 
	ExtraData: map[string]interface{}{ 
		"anotherCustomField": 456, 
	}, 
 
	MentionedUsers: []*stream_chat.User{ 
		&stream_chat.User{Name: "bob-1"}, 
	}, 
} 
 
filledMessage, err := channel.SendMessage(message, userID)

By default Stream’s UI components support the following attachment types:

  • Audio
  • Video
  • Image
  • Text

You can specify different types as long as you implement the frontend rendering logic to handle them. Common use cases include:

  • Embedding products (photos, descriptions, outbound links, etc.)
  • Sharing of a users location

The React tutorial for Stream Chat explains how to customize the Attachment component.

Get a MessageCopied!

You can get a single message by its ID using the getMessage call:

1
await client.getMessage(messageID);
1
2
3
4
5
6
7
channelClient.getMessage("message-id").enqueue(result -> { 
    if (result.isSuccess()) { 
        Message message = result.data(); 
    } else { 
        // Handle result.error() 
    } 
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import StreamChat 
 
/// 1: Create a `ChannelId` that represents the channel you want to get a message from. 
let channelId = ChannelId(type: .messaging, id: "general") 
 
/// 1: Create a `MessageId` that represents the message you want to get. 
let messageId = "message-id" 
 
/// 2: Use the `ChatClient` to create a `ChatChannelController` with the `ChannelId`. 
let messageController = chatClient.messageController(cid: channelId, messageId: messageId) 
 
/// 3: Call `ChatChannelController.createNewMessage` to create the message. 
messageController.synchronize { error in 
    // handle possible errors / access message 
    print(error ?? messageController.message!) 
}
1
2
3
4
5
6
7
channelClient.getMessage("message-id").enqueue { result -> 
    if (result.isSuccess) { 
        val message = result.data() 
    } else { 
        // Handle result.error() 
    } 
}
1
final message = await client.getMessage("message-id");
1
$message = $client->getMessage('message-id');
1
response = client.get_message(msg_id)
1
msg, err := client.GetMessage(msgID)

Update a MessageCopied!

You can edit a message by calling updateMessage and including a message with an ID – the ID field is required when editing a message:

1
2
const message = { id: 123, text: 'the edited version of my text' }; 
const update = await client.updateMessage(message);
1
2
3
4
5
6
7
8
9
10
11
// Update some field of the message 
message.setText("my updated text"); 
 
// Send the message to the channel 
channelClient.updateMessage(message).enqueue(result -> { 
    if (result.isSuccess()) { 
        Message updatedMessage = result.data(); 
    } else { 
        // Handle result.error() 
    } 
});
1
2
3
4
messageController.editMessage(text: "Hello!!!") { error in 
    // handle possible errors / access message 
    print(error ?? messageController.message!) 
}
1
2
3
4
5
6
7
8
9
10
11
// Update some field of the message 
message.text = "my updated text" 
 
// Send the message to the channel 
channelClient.updateMessage(message).enqueue { result -> 
    if (result.isSuccess) { 
        val updatedMessage = result.data() 
    } else { 
        // Handle result.error() 
    } 
}
1
await client.updateMessage(Message(id: "123", text: "the edited version of my text"));
1
2
3
4
5
6
7
$message = [ 
	'user_id' => 'jenny', 
	'id' => 'message-id', 
	'text' => 'the edited version of my text' 
]; 
 
$update = $client->updateMessage($message);
1
2
3
4
5
6
7
client.update_message( 
    { 
        "id": msg_id, 
        "text": "the edited version of my text", 
        "user_id": user_id, 
    } 
)
1
2
3
4
5
6
7
updatedMessage := &stream_chat.Message{ 
	ID:   msgID, 
	Text: "the edited version of my text", 
	User: &stream_chat.User{ID: userID}, 
} 
 
filledMessage, err := client.UpdateMessage(updatedMessage, msgID)

Delete A MessageCopied!

You can delete a message by calling deleteMessage  and including a message with an ID. Messages can be soft deleted or hard deleted. Unless specified via the hard parameter, messages are soft deleted.

1
2
3
4
await client.deleteMessage(messageID); 
 
// hard delete the message (works only server-side) 
await client.deleteMessage(messageID, true);
1
2
3
4
5
6
7
channelClient.deleteMessage("message-id").enqueue(result -> { 
    if (result.isSuccess()) { 
        Message deletedMessage = result.data(); 
    } else { 
        // Handle result.error() 
    } 
});
1
2
3
4
messageController.deleteMessage { error in 
    // handle possible errors 
    print(error ?? "success") 
}
1
2
3
4
5
6
7
channelClient.deleteMessage("message-id").enqueue { result -> 
    if (result.isSuccess) { 
        val deletedMessage = result.data() 
    } else { 
        // Handle result.error() 
    } 
}
1
await client.deleteMessage("123");
1
2
3
4
5
// soft delete the message 
$client->deleteMessage('message-id'); 
 
// hard delete the message 
$client->deleteMessage('message-id', ['hard' => true]);
1
2
3
4
5
# soft delete a message 
client.delete_message(msg_id) 
 
# hard delete a message 
client.delete_message(msg_id, hard=True)
1
2
// Soft Delete 
err := client.DeleteMessage(msgID)
Example of a soft deleted message in a conversation

Soft delete Copied!

  1. Can be done client-side by users

  2. Message is still returned in the message list and all its data is kept as it is

  3. Message type is set to "deleted"

  4. Reactions and replies are kept in place

Hard deleteCopied!

  1. Can only be done server-side

  2. The message is removed from the channel and its data wiped

  3. All reactions are deleted

  4. All replies and their reactions are deleted

By default messages are soft deleted, this is a great way to keep the channel history consistent.