---
id: messages
sidebar_position: 16
title: Messages
---

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

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

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.

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

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

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 Message

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

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

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

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

### Partial Update

A partial update can be used to set and unset specific fields when it is necessary to retain additional data fields on the object.
AKA a patch style update.

```dart
// partial update message text
const text = 'the text was partial updated';
const updated = await client.partiallyUpdateMessage(originalMessage.id, {
    set: {
        text
    }
});

// unset color property
await client.partiallyUpdateMessage(originalMessage.id, {
    'unset': ['color'],
});

// set nested property
await client.partiallyUpdateMessage(originalMessage.id, {
    'set': {
        'details.status': 'complete'
    },
});
```

### Delete A Message

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.

```dart
await client.deleteMessage("123");
```

### 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 be done client-side by users but be cautious this action is not recoverable
2.  The message is removed from the channel and its data is wiped
3.  All reactions are deleted
4.  All replies and their reactions are deleted
5.  By default messages are soft deleted, this is a great way to keep the channel history consistent.