Messages Overview

Last Edit: Mar 03 2020

Below is a detailed example of how to send a message using Stream Chat:


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
        }
    ],
    mentioned_users: [josh.id],
    anotherCustomField: 234
});
                    

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.");
HashMap<string, object="">extraDataMessage = new HashMap<>();
extraDataMessage.put("anotherCustomField",234);
message.setExtraData(extraDataMessage);

// add an image attachment to the message
Attachment attachment = new Attachment();
attachment.setType("image");
attachment.setImageURL("https://bit.ly/2K74TaG");
attachment.setFallback("test image");
// add some custom data to the attachment
HashMap<string, object=""> extraDataAttachment = new HashMap<>();
extraDataAttachment.put("myCustomField", 123);
attachment.setExtraData(extraDataAttachment);

message.setAttachments(Arrays.asList(attachment));

// include the user ID of the mentioned user
message.setMentionedUsersId(Arrays.asList("josh-id"));

channel.sendMessage(message,
    new MessageCallback() {
        @Override
        public void onSuccess(MessageResponse response) {

        }

        @Override
        public void onError(String errMsg, int errCode) {

        }
    }
);
                    

// First of let's create an extra data for a channel.
struct Product: Codable {
    let id: String
    let name: String
    let price: Int
}

struct AttachmentData: Codable {
    let info: String
}

// Update your extra data types for the decoding.
ExtraData.decodableTypes = [.channel(ChannelInfo.self),
                            .message(Product.self),
                            .attachment(AttachmentData.self)]

// Create an extra data for message.
let iPhone = Product(id: "iPhone12,3", name: "iPhone 11 Pro", price: 999)

// Create an extra data for the attachment.
let fish = AttachmentData(info: "Just a fish to increase sales.")

// Create attachment.
let attachment = Attachment(type: .image,
                            title: "A fish",
                            imageURL: URL(string: "https://bit.ly/2K74TaG")!,
                            extraData: fish)

// Create a message with the extra data and attachments.
let message = Message(text: "We have a new iPhone 11 Pro. Do you want to buy it?",
                      attachments: [attachment],
                      extraData: iPhone,
                      mentionedUsers: [User(id: "josh-id", name: "Josh")])

channel.send(message: message).subscribe().disposed(by: disposeBag)
                    

val message = Message()
message.text =
    "Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish."
message.extraData["anotherCustomField"] = 234

// add an image attachment to the message
val attachment = Attachment()
attachment.type = "image"
attachment.imageUrl = "https://bit.ly/2K74TaG"
attachment.fallback = "test image"
// add some custom data to the attachment
attachment.extraData["myCustomField"] = 123

message.attachments.add(attachment)

// include the user id of the mentioned user
message.mentionedUsers.add(User("josh-id"))

channel.sendMessage(message).enqueue {
    val message = it.data()
}
                    

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

// 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');
                    

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)
                    

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)
                    

There are five built-in fields for the message:

Name Type Description Default Optional
text string The text of the chat message (Stream chat supports markdown and automatically enriches URLs).
attachments array A list of attachments (audio, videos, images, and text). Max is 10 attachments per message. Each attachment can have up to 5KB.
user object This value is automatically set in client-side mode. You only need to send this value when using the server-side APIs.
mentioned_users array A 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 data object Extra data for the message. Must not exceed 5KB in size.

Note that both the message and the attachments can contain custom fields. By default Stream’s frontend 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 Message

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


await client.getMessage(messageID);
                    

client.getMessage(messageId, new MessageCallback(){
    @Override
    public void onSuccess(MessageResponse response) {
        
    }

    @Override
    public void onError(String errMsg, int errCode) {

    }
});
                    

Client.shared.message(with: messageId)
    .subscribe(onNext: { response in
        print(response)
    })
    .disposed(by: disposeBag)
                    

channelController.getMessage(messageId).enqueue {
    val message = it.data()
}
                    

final message = await client.getMessage("message-id");
                    

$message = $client->getMessage('message-id');
                    

response = client.get_message(msg_id)
                    

msg, err := client.GetMessage(msgID)
                    

Update a Message

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


const message = { id: 123, text: 'the edited version of my text' };
const update = await client.updateMessage(message);
                    

// update some field of the message
message.setText("my updated text");

// send the message to the channel
client.updateMessage(message, new MessageCallback(){
    @Override
    public void onSuccess(MessageResponse response) {

    }

    @Override
    public void onError(String errMsg, int errCode) {

    }
});
                    

let editedMessage = Message(id: message.id, text: newText)
channel.send(message: editedMessage).subscribe().disposed(by: disposeBag)
                    

// update some field of the message
message.text = "my updated text"
// send the message to the channel
channelController.updateMessage(message).enqueue {
    val message = it.data()
}
                    

await client.updateMessage(Message(id: "123", text: "the edited version of my text"));
                    

$message = [
	'user_id' => 'jenny',
	'id' => 'message-id',
	'text' => 'the edited version of my text'
];

$update = $client->updateMessage($message);
                    

client.update_message(
    {
        "id": msg_id,
        "text": "the edited version of my text",
        "user_id": user_id,
    }
)
                    

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 Message

You can delete a message by calling removeMessage  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.


await client.deleteMessage(messageID);

// hard delete the message (works only server-side)
await client.deleteMessage(messageID, true);
                    

client.deleteMessage("messageID", new MessageCallback(){
    @Override
    public void onSuccess(MessageResponse response) {

    }

    @Override
    public void onError(String errMsg, int errCode) {

    }
});
                    

// Delete a message.
channel.delete(message: message).subscribe().disposed(by: disposeBag)
// or
message.delete().subscribe().disposed(by: disposeBag)
                    

channelController.deleteMessage(messageId).enqueue { 
    val deletedMessage = it.data()
}
                    

await client.deleteMessage("123");
                    

// soft delete the message
$client->deleteMessage('message-id');

// hard delete the message
$client->deleteMessage('message-id', ['hard' => true]);
                    

# soft delete a message
client.delete_message(msg_id)

# hard delete a message
client.delete_message(msg_id, hard=True)
                    

// Soft Delete
err := client.DeleteMessage(msgID)
                    
Example of a soft deleted message in a conversation

Soft delete

  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 delete

  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.