---
source_url: https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/drafts
title: Create message drafts
updated_at: 2026-06-04T11:09:48.089Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Create message drafts

`MessageDraft` represents an unpublished message. Use it to:

* [Edit text](#update-message-text) before publishing
* Add [channel references](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/channels/references), [user mentions](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/users/mentions), and [links](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/links)
* Attach [files](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/files)

Display message elements (mentions, references, links) in your UI by adding a [message draft change listener](#add-message-draft-change-listener).

### Basics

Message drafts consist of `MessageElement` objects, which can be either instances of `Text` or `MentionTarget`.

`Text` are simple strings, while `MentionTarget` elements are used for user mentions, channel references, and URLs. They contain a text and a reference to the linked element regardless if it's a user, a channel, or a URL.

Each `MentionTarget` has a `MentionType` enum property, which defines the type of mention. Available targets include:

* `MentionTarget.User`
* `MentionTarget.Channel`
* `MentionTarget.Url`

:::note Store draft messages locally
Chat SDK does not persist drafts. Implement your own local storage to save drafts across channel switches.
:::

### Class diagram

### Example

Consider the message `Hey, I sent Alex this link on the #offtopic channel.` where:

* `Alex` is a reference to the user with the ID of `alex_d`
* `link` is a URL of the `www.pubnub.com` website
* `#offtopic` is a reference to the channel with the ID of `group.offtopic`

The list of `MessageElement` objects returned by the `MessageDraftChangeListener` is as follows:

| Part of Message | Element Type | Code Used to Create |
| --- | --- | --- |
| Hey, I sent | `Text` | [messageDraft.Update("Hey, I sent Alex this link on the #offtopic channel.");](#update-message-text) |
| Alex | `MentionTarget` | [messageDraft.AddMention(12, 4, new MentionTarget() {Target = "alex_ d", Type = MentionType.User});](#add-message-element) |
| this | `Text` | [messageDraft.Update("Hey, I sent Alex this link on the #offtopic channel.")](#update-message-text) |
| link | `MentionTarget` | [messageDraft.AddMention( 22, 4, new MentionTarget() {Target = "https://www.pubnub.com", Type = MentionType.Url});](#add-message-element) |
| on the | `Text` | [messageDraft.Update("Hey, I sent Alex this link on the #offtopic channel.");](#update-message-text) |
| #offtopic | `MentionTarget` | [messageDraft.AddMention(34, 9, new MentionTarget() {Target = "group.offtopic", Type = MentionType.Channel});](#add-message-element) |
| channel. | `Text` | [messageDraft.Update("Hey, I sent Alex this link on the #offtopic channel.");](#update-message-text) |

### Internal mention format

By internally leveraging a Markdown-like syntax, the message draft format integrates links directly into the message text using the pattern `[link text](https://www.pubnub.com/docs/link target)` understood by the Unity Chat SDK.

| Mention Type | Example |
| --- | --- |
| user | `[John Doe](https://www.pubnub.com/docs/pn-user://john_doe)` |
| channel | `[General Chat](https://www.pubnub.com/docs/pn-channel://group.chat.123)` |
| url | `[PubNub](https://www.pubnub.com)` |

Custom schemas like `pn-user://` and `pn-channel://` are used to identify user and channel mentions, while traditional URLs are supported as-is.

:::warning Adding message elements
You don't use this Markdown-like syntax when adding message elements. It's only a representation of your message elements under the hood.
For more information, refer to [Add message element](#add-message-element).
:::

## Create a draft message

`CreateMessageDraft()` creates a message draft ([MessageDraft object](https://www.pubnub.com/docs/chat/unity-chat-sdk/learn/chat-entities/message-draft)) that can consist of:

* Plain text
* [Mentioned users](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/users/mentions)
* [Referenced channels](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/channels/references)
* [Links](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/links)
* [Files](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/files)

### Method signature

This method has the following signature:

```csharp
public MessageDraft CreateMessageDraft(
  UserSuggestionSource userSuggestionSource = UserSuggestionSource.GLOBAL, 
  bool isTypingIndicatorTriggered = true, 
  int userLimit = 10, 
  int channelLimit = 10,
  bool shouldSearchForSuggestions = false
)
```

#### Input

| Parameter | Description |
| --- | --- |
| `userSuggestionSource`Type: `UserSuggestionSource = .GLOBAL` or `UserSuggestionSource = .CHANNEL`Default: `UserSuggestionSource = .GLOBAL` | This parameter refers to the [Mentions](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/users/mentions) feature. Data source from which you want to retrieve users. You can choose either the list of channel members (`.CHANNEL`) or users on the app's Admin Portal keyset (`.GLOBAL`). |
| `isTypingIndicatorTriggered`Type: `Bool`Default: `true` | This parameter refers to the [Typing Indicator](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/channels/typing-indicator) feature. Defines if the typing indicator should be enabled when writing the message. |
| `userLimit`Type: `Int`Default: `10` | This parameter refers to the [Mentions](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/users/mentions) feature. Maximum number of usernames (`name` field from the `User` object) you can mention in one message (the default value is `10` and max is `100`). |
| `channelLimit`Type: `Int`Default: `10` | This parameter refers to the [References](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/channels/references) feature. Maximum number of channel names (`name` field from the `Channel` object) you can reference in one message (the default value is `10` and max is `100`). |
| `shouldSearchForSuggestions`Type: `Bool`Default: `false` | Whether the MessageDraft should automatically search for suggestions whenever the text is changed. When set to `true`, the `OnDraftUpdated` event will include suggested mentions for users, channels, and links. |

#### Output

| Type | Description |
| --- | --- |
| `MessageDraft` | Instance of `MessageDraft`, which represents a draft version of a message with the content, all links, referenced channels, mentioned users and their names. |

### Sample code

Create a draft message containing just plain text.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var channelResult = await chat.GetChannel("support");
if (channelResult.Error) return;
var channel = channelResult.Result;
        
var messageDraft = channel.CreateMessageDraft();
```

## Add message draft change listener

The `OnDraftUpdated` event is triggered when there is a change to a message draft. You must handle the event to update to the contents of a message draft, as well as retrieve the current message elements suggestions for user mentions, channel reference, and links. For example, when the message draft contains `... @name ...` or `... #chann ...`.

:::warning Enable receiving suggested mentions
You must enable receiving suggested mentions by setting `messageDraft.ShouldSearchForSuggestions = true;` before introducing your event handler.
:::

### Event signature

```csharp
public event Action<List<MessageElement>, List<SuggestedMention>> OnDraftUpdated; 
```

### Event handler signature

```csharp
void EventHandler(List<MessageElement> elements, List<SuggestedMention> mentions)
```

| Parameter | Description |
| --- | --- |
| `elements` *Type: `MessageElement`Default: n/a | A list of `MessageElement` objects, representing the current state of the message draft. This could contain a mix of plain text and links, channel references, or user mentions. |
| `mentions` *Type: `SuggestedMention`Default: n/a | A list of [SuggestedMention](#suggestedmention) objects. These are potential suggestions for message elements based on the current text in the draft. Suggested mentions are not returned by default. You must enable receiving them by setting `messageDraft.ShouldSearchForSuggestions = true;` before introducing your event handler. |

#### SuggestedMention

A `SuggestedMention` represents a potential mention suggestion received from [MessageDraftChangeListener](#add-message-draft-change-listener).

Suggested mentions are not returned by default. You must enable receiving them by setting `messageDraft.ShouldSearchForSuggestions = true;` before introducing your event handler.

| Parameter | Description |
| --- | --- |
| `Offset`Type: `Int` | The position from the start of the message draft where the message elements starts. It's counted from the beginning of the message (including spaces), with `0` as the first character. |
| `ReplaceFrom`Type: `String` | The original text at the given offset in the message draft text. |
| `ReplaceTo`Type: `String` | The suggested replacement for the `replaceFrom` text. |
| `Target`Type: `MentionTarget` | The message element type. Available types include: MentionTarget.User, MentionTarget.Channel, MentionTarget.Url |

#### Output

This method doesn't return any data.

### Sample code

Add the listener to your message draft.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var channelResult = await chat.GetChannel("support");
if (channelResult.Error) return;
var channel = channelResult.Result;
        
// Create a message draft
var messageDraft = channel.CreateMessageDraft();

// Enable receiving search suggestions
messageDraft.ShouldSearchForSuggestions = true;

// Use a dedicated callback
void InsertDelegateCallback(List<MessageElement> elements, List<SuggestedMention> mentions)
{
  // your logic goes here
}

// Add the InsertDelegateCallback function to the OnDraftUpdated event
messageDraft.OnDraftUpdated += InsertDelegateCallback;

// Or use a lambda
// Event handlers added with a lambda
messageDraft.OnDraftUpdated += (elements, mentions) =>
{
  // your logic goes here
};
```

## Remove message draft change listener

Remove a previously added `OnDraftUpdated` event handler. You can only remove an event handler that was added using a dedicated callback.

### Sample code

Remove a listener from your message draft.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var channelResult = await chat.GetChannel("support");
if (channelResult.Error) return;
var channel = channelResult.Result;
        
// Create a message draft
var messageDraft = channel.CreateMessageDraft();

// Enable receiving search suggestions
messageDraft.ShouldSearchForSuggestions = true;

// Use a dedicated callback
void InsertDelegateCallback(List<MessageElement> elements, List<SuggestedMention> mentions)
{
  // your logic goes here
}

// Add the InsertDelegateCallback function to the OnDraftUpdated event
messageDraft.OnDraftUpdated += InsertDelegateCallback;

// Remove the InsertDelegateCallback function to the OnDraftUpdated event
messageDraft.OnDraftUpdated -= InsertDelegateCallback;
```

## Add message element

`AddMention()` adds a user mention, channel reference or a link specified by a mention target at a given offset.

### Method signature

This method has the following signature:

```csharp
messageDraft.AddMention(
  int offset, 
  int length, 
  MentionTarget target
)
```

#### Input

| Parameter | Description |
| --- | --- |
| `offset` *Type: `int`Default: n/a | Position of a character in a message where the message element you want to insert starts. It's counted from the beginning of the message (including spaces), with `0` as the first character. |
| `length` *Type: `int`Default: n/a | Number of characters the message element should occupy in the draft message's text. |
| `target` *Type: `MentionTarget`Default: n/a | Mention target type. `mentionTarget = new MentionTarget { Type = MentionType, Target = String };` Available mention types include: MentionTarget.User, MentionTarget.Channel, MentionTarget.Url |

#### Output

This method returns no output data.

### Sample code

Create the `Hello Alex! I have sent you this link on the #offtopic channel.` message where `Alex` is a user mention, `link` is a URL, and `#offtopic` is a channel reference.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var channelResult = await chat.GetChannel("support");
if (channelResult.Error) return;
var channel = channelResult.Result;
        
var messageDraft = channel.CreateMessageDraft();

// Add initial text
messageDraft.Update("Hello Alex!");

// Add a user mention to the string "Alex"
messageDraft.AddMention(6, 4, new MentionTarget {
    Target = "alex_d",
    Type = MentionType.User
});

// Change the text
messageDraft.Update("Hello Alex! I have sent you this link on the #offtopic channel.");

// Add a URL mention to the string "link"
messageDraft.AddMention(33, 4, new MentionTarget {
    Target = "www.pubnub.com",
    Type = MentionType.Url
});

// Add a channel mention to the string "#offtopic"
messageDraft.AddMention(45, 9, new MentionTarget {
    Target = "group.offtopic",
    Type = MentionType.Channel
});
```

## Remove message element

`RemoveMention()` removes a user mention, channel reference, or a link at a given offset.

### Method signature

This method has the following signature:

```csharp
messageDraft.RemoveMention(int offset)
```

#### Input

| Parameter | Description |
| --- | --- |
| `offset` *Type: `int`Default: n/a | Position of the first character of the message element you want to remove. |

:::warning Offset value
If you don't provide the position of the first character of the message element to remove, it isn't removed.
:::

#### Output

This method returns no output data.

### Sample code

Remove the URL element from the word `link` in the `Hello Alex! I have sent you this link on the #offtopic channel.` message.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// Assume the message reads:
// Hello Alex! I have sent you this link on the #offtopic channel.

// Remove the link mention
messageDraft.RemoveMention(33);
```

## Update message text

`Update()` lets you replace the text of a [draft message](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/drafts) with new content.

:::warning Removing message elements
As a best effort, the optimal set of insertions and removals that converts the current text to the provided text is calculated to preserve any message elements.
If any message element text is found to be modified in the updated text, the message element is removed.
:::

### Method signature

This method has the following signature:

```csharp
messageDraft.Update(string text)
```

#### Input

| Parameter | Description |
| --- | --- |
| `text` *Type: `string`Default: n/a | Text of the message that you want to update. |

#### Output

This method returns no output data.

### Sample code

Change the message `I sent Alex this picture.` to `I did not send Alex this picture.` where `Alex` is a user mention.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// the message reads:
// I sent [Alex] this picture.
// where [Alex] is a user mention
messageDraft.Update("I did not send Alex this picture.");
// the message now reads: 
// I did not send [Alex] this picture.
// the mention is preserved because its text wasn't changed
```

:::note Mention text changes
If you decided to change the name `Alex` to some other name, the mention would be removed because your updated text's index coincided with an existing mention.
For more manual control over inserting and removing parts of a message, refer to [Insert message text](#insert-message-text) and [Remove message text](#remove-message-text).
:::

## Insert suggested message element

Inserts a message element returned by the [MessageDraftChangeListener](#add-message-draft-change-listener) into the `MessageDraft`.

:::warning Text must match
The `SuggestedMention` must be up to date with the message text, that is, `SuggestedMention.ReplaceFrom` must match the message draft at position `SuggestedMention.ReplaceFrom`, otherwise an exception is thrown.
:::

### Method signature

This method has the following signature:

```csharp
messageDraft.InsertSuggestedMention(
  SuggestedMention mention, 
  string text
)
```

#### Input

| Parameter | Description |
| --- | --- |
| `mention` *Type: [SuggestedMention](#suggestedmention)Default: n/a | A user, channel, or URL suggestion obtained from [MessageDraftChangeListener](#add-message-draft-change-listener). |
| `text` *Type: `string`Default: n/a | The text you want the message element to display. |

#### Output

This method returns no output data.

### Sample code

Register a listener and insert a suggested element.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var channelResult = await chat.GetChannel("support");
if (channelResult.Error) return;
var channel = channelResult.Result;
        
var messageDraft = channel.CreateMessageDraft();
messageDraft.ShouldSearchForSuggestions = true;
messageDraft.OnDraftUpdated += (elements, mentions) =>
{
    if (!mentions.Any())
    {
        return;
    }
    messageDraft.InsertSuggestedMention(mentions[0], mentions[0].ReplaceTo);
};
messageDraft.InsertText(0, "maybe i'll mention @John");
```

## Insert message text

`InsertText()` lets you insert plain text in the [draft message](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/drafts) at a given offset from the beginning of the message.

:::warning Removing message elements
If the position of the text you want to insert corresponds to an existing message element, this element is removed.
:::

### Method signature

This method has the following signature:

```csharp
messageDraft.InsertText(
  int offset, 
  string text
)
```

#### Input

| Parameter | Description |
| --- | --- |
| `offset` *Type: `int`Default: n/a | Position of a character in a message where the text you want to insert starts. It's counted from the beginning of the message (including spaces), with `0` as the first character. |
| `text` *Type: `string`Default: n/a | Text that you want to insert. |

#### Output

This method returns no output data.

### Sample code

In the message `Check this support article https://www.support-article.com/.`, add the word `out` between the words `Check` and `this`.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// The message reads:
// Check this support article https://www.support-article.com/.
        
// Add "out" after "Check" (position 6, right after "Check ")
messageDraft.InsertText(6, "out ");
        
// The message now reads:
// Check out this support article https://www.support-article.com/.
```

## Remove message text

`RemoveText()` lets you remove plain text from the [draft message](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/drafts) at a given offset from the beginning of the message.

:::warning Removing message elements
If the position of the text you want to remove corresponds to an existing message element, this element is removed.
:::

### Method signature

This method has the following signature:

```csharp
messageDraft.RemoveText(
  int offset, 
  int length
)
```

#### Input

| Parameter | Description |
| --- | --- |
| `offset` *Type: `int`Default: n/a | Position of a character in a message where the text you want to insert starts. It's counted from the beginning of the message (including spaces), with `0` as the first character. |
| `length` *Type: `int`Default: n/a | How many characters to remove, starting at the given `offset`. |

#### Output

This method returns no output data.

### Sample code

In the message `Check out this support article https://www.support-article.com/.`, remove the word `out`.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// The message reads:
// Check out this support article https://www.support-article.com/.

messageDraft.RemoveText(5, 4);
// The message now reads:
// Check this support article https://www.support-article.com/.
```

## Append message text

`AppendText()` adds text to the end of the current draft message. This is a convenience method equivalent to calling `InsertText()` at the end of the text.

### Method signature

This method has the following signature:

```csharp
messageDraft.AppendText(string text)
```

#### Input

| Parameter | Description |
| --- | --- |
| `text` *Type: `string`Default: n/a | Text to append at the end of the draft message. |

#### Output

This method returns no output data.

### Sample code

Append text to an existing draft message.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
```

## Get message elements

`GetMessageElements()` parses the Markdown text of a message or draft into a list of `MessageElement` objects representing plain text segments, user mentions, channel references, and links.

This method is available on both the `MessageDraft` and [Message](https://www.pubnub.com/docs/chat/unity-chat-sdk/learn/chat-entities/message) objects. On `MessageDraft`, it returns the current draft elements. On `Message`, it parses the received message text.

### Method signature

This method has the following signature:

```csharp
// On a MessageDraft instance
messageDraft.GetMessageElements()

// On a Message instance
message.GetMessageElements()

// Static method (parses any markdown text)
MessageDraft.GetMessageElements(string markdownText)
```

#### Input

| Parameter | Description |
| --- | --- |
| `markdownText`Type: `string`Default: n/a | The markdown text containing links to parse. Only required when calling the static overload. |

#### Output

| Type | Description |
| --- | --- |
| `List<MessageElement>` | A list of `MessageElement` objects representing plain text segments and mentions/links parsed from the message. |

### Sample code

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// Parse elements from a draft before sending
var elements = messageDraft.GetMessageElements();

// Parse elements from a received message
elements = message.GetMessageElements();

// Parse any markdown string directly
elements = MessageDraft.GetMessageElements("[Alex](https://www.pubnub.com/docs/pn-user://alex_d) check the [#general](https://www.pubnub.com/docs/pn-channel://group.general) channel");
```

## Quote a message in a draft

Set the `QuotedMessage` property on a `MessageDraft` to attach a [quoted message](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/quotes) to the draft. When the draft is sent, the quoted message metadata is included automatically.

| Property | Description |
| --- | --- |
| `QuotedMessage`Type: `Message` | The message to quote. Set to `null` to remove the quote. When set, the sent message will include the quoted message's timetoken, text, and user ID. |

### Sample code

```csharp
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var quotedMessageResult = await chat.GetMessage("support", "16200000000000001");
if(quotedMessageResult.Error)
{
    return;
}
var quotedMessage = quotedMessageResult.Result;
        
var channelResult = await chat.GetChannel("support");
if (channelResult.Error)
{
    Debug.LogError($"Couldn't get channel, error: {channelResult.Exception.Message}");
    return;
}
var testChannel = channelResult.Result;
        
//Creating a Message Draft to attatch a Quote
var messageDraft = testChannel.CreateMessageDraft();
messageDraft.InsertText(0, "message with a quote");
messageDraft.QuotedMessage = quotedMessage;
        
await messageDraft.Send();
```

## Send a draft message

`Send()` publishes the draft text message with all [mentioned users](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/users/mentions), [links](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/links), [referenced channels](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/channels/references), [attached files](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/files), and [quoted messages](#quote-a-message-in-a-draft).

Whenever you mention any users, `Send()` also emits [events of type mention](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/custom-events#events-for-mentions).

:::info Draft-first pattern
Mentions, files, and quoted messages are set directly on the `MessageDraft` object through properties and methods like [AddMention()](#add-message-element), [Files](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/files), and [QuotedMessage](#quote-a-message-in-a-draft). They are not passed through `SendTextParams`.
:::

### Method signature

This method has the following signature:

```csharp
messageDraft.Send(SendTextParams sendTextParams)
```

#### Input

| Parameter | Description |
| --- | --- |
| `sendTextParams`Type: `SendTextParams`Default: `new()` | Object which holds additional parameters. |
| `> Meta`Type: `Dictionary<string, object>`Default: `new()` | Additional metadata for the request. |
| `> StoreInHistory`Type: `bool`Default: `true` | If `true`, the messages are stored in [Message Persistence](https://www.pubnub.com/docs/general/storage) (PubNub storage). If `StoreInHistory` is not specified, the Message Persistence configuration specified on the Admin Portal keyset is used. |
| `> SendByPost`Type: `bool`Default: `false` | When `true`, the SDK uses HTTP POST to publish the messages. The message is sent in the BODY of the request instead of the query string when HTTP GET is used. The messages are also compressed to reduce their size. |
| `> CustomPushData`Type: `Dictionary<string, string>`Default: `new()` | Custom data to include in push notifications. |

#### Output

An awaitable `Task`.

### Sample code

Send a draft message containing just plain text.

```csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
var channelResult = await chat.GetChannel("support");
if (channelResult.Error) return;
var channel = channelResult.Result;
        
// Create a message draft
var messageDraft = channel.CreateMessageDraft();

// Add initial text
messageDraft.Update("Hello Alex!");

// Send the message
await messageDraft.Send();
```