---
title: Chat
description: Send and receive chat messages in RealtimeKit meetings using the Core SDK.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/realtime/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Chat

This guide explains how to send and receive chat messages in a meeting using Cloudflare RealtimeKit.

WebMobile

ReactWeb ComponentsAngular

## Introduction

There are three types of messages that can be sent in chat:

* Text messages
* Images
* Files

The meeting chat object is stored in `meeting.chat`, which has methods for sending and receiving messages.

JavaScript

```

console.log("Chat object:", meeting.chat);


```

The `meeting.chat.messages` array contains all the messages that have been sent in the chat. This is an array of objects, where each object is of type `Message`.

JavaScript

```

console.log("All chat messages:", meeting.chat.messages);


```

There are three types of messages that can be sent in chat:

* Text messages
* Images
* Files

The meeting chat object is stored in `meeting.chat`, which has methods for sending and receiving messages.

```

meeting.chat;


```

The `meeting.chat.messages` array contains all the messages that have been sent in the chat. This is an array of objects, where each object is of type `Message`.

```

meeting.chat.messages;


```

There are three types of messages that can be sent in chat:

* Text messages
* Images
* Files

The meeting chat object is stored in `meeting.chat`, which has methods for sending and receiving messages.

```

meeting.chat


```

The `meeting.chat.messages` array contains all the messages that have been sent in the chat. This is an array of objects, where each object is of type `com.cloudflare.realtimekit.chat.ChatMessage`.

```

meeting.chat.messages


```

There are three types of messages that can be sent in chat:

* Text messages
* Images
* Files

The meeting chat object is stored in `meeting.chat`, which has methods for sending and receiving messages.

```

meeting.chat


```

The `meeting.chat.messages` array contains all the messages that have been sent in the chat. This is an array of objects, where each object is of type `RealtimeKit.ChatMessage`.

```

meeting.chat.messages


```

There are three types of messages that can be sent in chat:

* Text messages
* Images
* Files

The meeting chat object is stored in `meeting.chat`, which has methods for sending and receiving messages.

```

meeting.chat;


```

The `meeting.chat.messages` array contains all the messages that have been sent in the chat. This is an array of objects, where each object is of type `ChatMessage`.

```

meeting.chat.messages;


```

There are three types of messages that can be sent in chat:

* Text messages
* Images
* Files

The meeting chat object is stored in `meeting.chat`, which has methods for sending and receiving messages.

```

meeting.chat;


```

The `meeting.chat.messages` array contains all the messages that have been sent in the chat. This is an array of objects, where each object is of type `Message`.

```

meeting.chat.messages;


```

### Message Type

The `Message` type is defined as follows:

TypeScript

```

interface BaseMessage<T extends MessageType> {

  type: T;

  userId: string;

  displayName: string;

  time: Date;

  id: string;

  isEdited?: boolean;

  read?: boolean;

  pluginId?: string;

  pinned?: boolean;

  targetUserIds?: string[];

}


interface TextMessage extends BaseMessage<MessageType.text> {

  message: string;

}


interface ImageMessage extends BaseMessage<MessageType.image> {

  link: string;

}


interface FileMessage extends BaseMessage<MessageType.file> {

  name: string;

  size: number;

  link: string;

}


type Message = TextMessage | ImageMessage | FileMessage;


```

The `Message` type is defined as follows:

TypeScript

```

interface BaseMessage<T extends MessageType> {

  type: T;

  userId: string;

  displayName: string;

  time: Date;

  id: string;

  isEdited?: boolean;

  read?: boolean;

  pluginId?: string;

  pinned?: boolean;

  targetUserIds?: string[];

}


interface TextMessage extends BaseMessage<MessageType.text> {

  message: string;

}


interface ImageMessage extends BaseMessage<MessageType.image> {

  link: string;

}


interface FileMessage extends BaseMessage<MessageType.file> {

  name: string;

  size: number;

  link: string;

}


type Message = TextMessage | ImageMessage | FileMessage;


```

The `ChatMessage` class is defined as follows:

Kotlin

```

enum class ChatMessageType {

  TEXT,

  IMAGE,

  FILE

}


open class ChatMessage(

  val userId: String,

  val displayName: String,

  val read: Boolean,

  val pluginId: String?,

  val type: ChatMessageType,

  val time: String,

  val createdAtMillis: Long,

  val targetUserIds: List<String>?,

)


class TextMessage(val message: String): ChatMessage(...)


class ImageMessage(val link: String): ChatMessage(...)


class FileMessage(

  val name: String,

  val link: String,

  val size: Long,

): ChatMessage(...)


```

The `ChatMessage` class is defined as follows:

Swift

```

public enum ChatMessageType {

    case text

    case image

    case file

}


open class ChatMessage {

    public let userId: String

    public let displayName: String

    public let read: Bool

    public let pluginId: String?

    public let type: ChatMessageType

    public let time: String

    public let createdAtMillis: Int64

    public let targetUserIds: [String]?

}


public final class TextMessage: ChatMessage {

    public let message: String

}


public final class ImageMessage: ChatMessage {

    public let link: String

}


public final class FileMessage: ChatMessage {

    public let name: String

    public let link: String

    public let size: Int64

}


```

The `ChatMessage` class is defined as follows:

Dart

```

enum MessageType { text, image, file }


class ChatMessage {

  final String displayName;

  final MessageType type;

  final bool read;

  final String userId;

  final String? pluginId;

  final String time;

}


class TextMessage extends ChatMessage {

  final String message;

}


class ImageMessage extends ChatMessage {

  final String link;

}


class FileMessage extends ChatMessage {

  final String name;

  final String link;

  final int size;

}


```

The `Message` type is defined as follows:

TypeScript

```

interface BaseMessage<T extends MessageType> {

  type: T;

  userId: string;

  displayName: string;

  time: Date;

  id: string;

  isEdited?: boolean;

  read?: boolean;

  pluginId?: string;

  pinned?: boolean;

  targetUserIds?: string[];

}


interface TextMessage extends BaseMessage<MessageType.text> {

  message: string;

}


interface ImageMessage extends BaseMessage<MessageType.image> {

  link: string;

}


interface FileMessage extends BaseMessage<MessageType.file> {

  name: string;

  size: number;

  link: string;

}


type Message = TextMessage | ImageMessage | FileMessage;


```

## Sending a Chat Message

### Send a Text Message

There is a method in `meeting.chat` to send a message of each type.

To send a text message, use the `meeting.chat.sendTextMessage()` method. This accepts a string message and sends it to the room.

JavaScript

```

const message = "Is this the real life?";

await meeting.chat.sendTextMessage(message);


```

There is a method in `meeting.chat` to send a message of each type.

To send a text message, use the `meeting.chat.sendTextMessage()` method. This accepts a string message and sends it to the room.

```

const message = "Is this the real life?";

await meeting.chat.sendTextMessage(message);


```

There is a method in `meeting.chat` to send a message of each type.

To send a text message, use the `meeting.chat.sendTextMessage()` method. This accepts a string message and sends it to the room.

Kotlin

```

val message = "Is this the real life?"

meeting.chat.sendTextMessage(message)


```

There is a method in `meeting.chat` to send a message of each type.

To send a text message, use the `meeting.chat.sendTextMessage()` method. This accepts a string message and sends it to the room.

Swift

```

var message = "Is this the real life?"

meeting.chat.sendTextMessage(message)


```

There is a method in `meeting.chat` to send a message of each type.

To send a text message, use the `meeting.chat.sendTextMessage()` method. This accepts a string message and sends it to the room.

Dart

```

final message = "Is this the real life?";

meeting.chat.sendTextMessage(message);


```

There is a method in `meeting.chat` to send a message of each type.

To send a text message, use the `meeting.chat.sendTextMessage()` method. This accepts a string message and sends it to the room.

```

const message = "Is this the real life?";

await meeting.chat.sendTextMessage(message);


```

### Send an Image

You can send an image with the help of `meeting.chat.sendImageMessage()`. This accepts an image of type `File`, and sends it to the participants in the meeting.

```

<label for="img">Select image:</label>

<input type="file" id="img" name="img" accept="image/*" />

<button onclick="onSendImage()">Send Image</button>


```

JavaScript

```

async function onSendImage() {

  const image = document.getElementById("img");

  await meeting.chat.sendImageMessage(image.files[0]);

}


```

You can send an image with the help of `meeting.chat.sendImageMessage()`. This accepts an image of type `File`, and sends it to the participants in the meeting.

```

import { useRef } from "react";


function ChatComponent() {

  const imageInputRef = useRef(null);


  const onSendImage = async () => {

    const image = imageInputRef.current;

    if (image && image.files[0]) {

      await meeting.chat.sendImageMessage(image.files[0]);

    }

  };


  return (

    <>

      <label htmlFor="img">Select image:</label>

      <input

        type="file"

        id="img"

        name="img"

        accept="image/*"

        ref={imageInputRef}

      />

      <button onClick={onSendImage}>Send Image</button>

    </>

  );

}


```

You can send an image with the help of `meeting.chat.sendImageMessage()` and sends it to the participants in the meeting.

Kotlin

```

meeting.chat.sendImageMessage(imageUri) { err ->

  // Handle error if any

}


```

You can send an image with the help of `meeting.chat.sendImageMessage()` and sends it to the participants in the meeting.

Swift

```

meeting.chat.sendImageMessage(imageURL: url) { err in

  // Handle error if any

}


```

You can send an image with the help of `meeting.chat.sendImageMessage()` which sends it to the participants in the meeting. It takes a string filePath as argument.

Dart

```

final filePath = "file_path_of_image";

meeting.chat.sendImageMessage(filePath, (error) {

  // Handle error if any

});


```

You can send an image with the help of `meeting.chat.sendImageMessage()`. This accepts an image of type File, and sends it to the participants in the meeting.

```

import DocumentPicker from "@react-native-documents/picker";


async function onSendImage() {

  // Get the image uri and create an object with the following fields

  const res = await DocumentPicker.pickSingle({

    type: [DocumentPicker.types.images],

  });

  const image = {

    uri: res.uri,

    name: res.name,

    size: res.size,

    type: res.type,

  };

  await meeting.chat.sendImageMessage(image);

}


```

### Send a File

Sending a file is similar to sending an image. The only difference is that when you send an image, a preview will be shown in the meeting chat, which is not the case for sending files. That being said, an image can be sent as a file too using `meeting.chat.sendFileMessage()`.

```

<label for="file">Select file:</label>

<input type="file" id="file" name="file" />

<button onclick="onSendFile()">Send File</button>


```

JavaScript

```

async function onSendFile() {

  const file = document.getElementById("file");

  await meeting.chat.sendFileMessage(file.files[0]);

}


```

Sending a file is similar to sending an image. The only difference is that when you send an image, a preview will be shown in the meeting chat, which is not the case for sending files. That being said, an image can be sent as a file too using `meeting.chat.sendFileMessage()`.

```

import { useRef } from "react";


function ChatComponent() {

  const fileInputRef = useRef(null);


  const onSendFile = async () => {

    const file = fileInputRef.current;

    if (file && file.files[0]) {

      await meeting.chat.sendFileMessage(file.files[0]);

    }

  };


  return (

    <>

      <label htmlFor="file">Select file:</label>

      <input type="file" id="file" name="file" ref={fileInputRef} />

      <button onClick={onSendFile}>Send File</button>

    </>

  );

}


```

Sending a file is similar to sending an image. The only difference is that when you send an image, a preview will be shown in the meeting chat, which is not the case for sending files. That being said, an image can be sent as a file too using `meeting.chat.sendFileMessage()`.

Kotlin

```

meeting.chat.sendFileMessage(fileUri) { err ->

  // Handle error if any

}


```

Sending a file is similar to sending an image. The only difference is that when you send an image, a preview will be shown in the meeting chat, which is not the case for sending files. That being said, an image can be sent as a file too using `meeting.chat.sendFileMessage()`.

Swift

```

meeting.chat.sendFileMessage(fileURL: url) { err in

  // Handle error if any

}


```

You can send a file with the help of `meeting.chat.sendFileMessage()` which sends it to the participants in the meeting. It takes a string filePath as argument.

Dart

```

final filePath = "file_path_of_pdf";

meeting.chat.sendFileMessage(filePath, (error) {

  // Handle error if any

});


```

Sending a file is similar to sending an image. The only difference is that when you send an image, a preview will be shown in the meeting chat, which is not the case for sending files. That being said, an image can be sent as a file too using `meeting.chat.sendFileMessage()`.

```

import DocumentPicker from "@react-native-documents/picker";


async function onSendFile() {

  // Get the file uri and create an object with the following fields

  const res = await DocumentPicker.pickSingle({

    type: [DocumentPicker.types.allFiles],

  });

  const file = {

    uri: res.uri,

    name: res.name,

    size: res.size,

    type: res.type,

  };

  await meeting.chat.sendFileMessage(file);

}


```

### Send Any Message Type

There is also a common method called `meeting.chat.sendMessage()` that can be used to send any of the three types of messages displayed above. It essentially calls one of the methods from above depending upon the type of payload you send to the method. The `sendMessage()` method accepts a parameter `message` of the following type:

TypeScript

```

async function sendMessage(

  message:

    | { type: "text"; message: string }

    | { type: "image"; image: File }

    | { type: "file"; file: File },

) {

  // ...

}


```

Here is how you would use the `sendMessage()` method to send a text message:

JavaScript

```

const message = "Is this just fantasy?";

await meeting.chat.sendMessage({ type: "text", message });


```

There is also a common method called `meeting.chat.sendMessage()` that can be used to send any of the three types of messages displayed above. It essentially calls one of the methods from above depending upon the type of payload you send to the method. The `sendMessage()` method accepts a parameter `message` of the following type:

TypeScript

```

async function sendMessage(

  message:

    | { type: "text"; message: string }

    | { type: "image"; image: File }

    | { type: "file"; file: File },

) {

  // ...

}


```

Here is how you would use the `sendMessage()` method to send a text message:

```

const message = "Is this just fantasy?";

await meeting.chat.sendMessage({ type: "text", message });


```

There is also a common method called `meeting.chat.sendMessage()` that can be used to send any of the three types of messages displayed above. It essentially calls one of the methods from above depending upon the type of payload you send to the method. The `sendMessage()` method accepts a parameter `message` of the following type:

TypeScript

```

async function sendMessage(

  message:

    | { type: "text"; message: string }

    | { type: "image"; image: File }

    | { type: "file"; file: File },

) {

  // ...

}


```

Here is how you would use the `sendMessage()` method to send a text message:

```

const message = "Is this just fantasy?";

await meeting.chat.sendMessage({ type: "text", message });


```

## Receiving Chat Messages

The `meeting.chat` object emits events when new chat messages are received. You can listen for the `chatUpdate` event to log when a new chat message is received.

JavaScript

```

meeting.chat.on("chatUpdate", ({ message, messages }) => {

  console.log(`Received message ${message}`);

  console.log(`All messages in chat: ${messages.join(", ")}`);

});


```

Here, `message` is of type `Message`, as defined in the introduction. `messages` is a list of all chat messages in the meeting, which is the same as `meeting.chat.messages`.

When a chat message is received, the `meeting.chat.messages` list is also updated.

JavaScript

```

console.log(JSON.stringify(meeting.chat.messages));


meeting.chat.on("chatUpdate", () => {

  console.log(JSON.stringify(meeting.chat.messages));

});


```

The `meeting.chat` object emits events when new chat messages are received. You can listen for the `chatUpdate` event to log when a new chat message is received.

```

import { useRealtimeKitSelector } from "@cloudflare/realtimekit-react";


// useRealtimeKitSelector hooks only works when `RealtimeKitProvider` is used.

const messages = useRealtimeKitSelector((m) => m.chat.messages);


```

Alternatively:

```

meeting.chat.on("chatUpdate", ({ message, messages }) => {

  console.log(`Received message ${message}`);

  console.log(`All messages in chat: ${messages.join(", ")}`);

});


```

Here, `message` is of type `Message`, as defined in the introduction. `messages` is a list of all chat messages in the meeting, which is the same as `meeting.chat.messages`.

When a chat message is received, the `meeting.chat.messages` list is also updated.

```

console.log(JSON.stringify(meeting.chat.messages));


meeting.chat.on("chatUpdate", () => {

  console.log(JSON.stringify(meeting.chat.messages));

});


```

To be able to receive chat messages you need to implement a method `onChatUpdates()` method from callback `RtkChatEventListener`. You can subscribe to this events by calling `meeting.addChatEventListener(rtkChatEventListener)`.

Kotlin

```

meeting.addChatEventListener(object : RtkChatEventListener {

  override fun onChatUpdates(messages: List<ChatMessage>) {

    // to load chat messages

  }


  override fun onNewChatMessage(message: ChatMessage) {

    // when a new chat message is shared in the meeting

  }


  override fun onMessageRateLimitReset() {

    // when the rate limit for sending messages of self is reset

  }

})


```

The `onChatUpdates()` method will be called whenever there is a change in the chat messages. The `messages` parameter is a list of `ChatMessage` objects that have been sent in the chat.

The `onNewChatMessage()` method will be called whenever a new chat message is shared in the meeting. The `message` parameter is a `ChatMessage` object that has been sent in the chat.

The `onMessageRateLimitReset()` method will be called when the rate limit for sending messages of self is reset and you can send messages again. The default rate limit is 180 messages within 60 seconds.

To be able to receive chat messages you need to implement a method `onChatUpdates()` method from callback `RtkChatEventListener`. You can subscribe to this events by calling `meeting.addChatEventListener(rtkChatEventListener)`.

Swift

```

extension MainChatListener: RtkChatEventListener {

  func onChatUpdates(messages: [ChatMessage]) {

    // to load chat messages

  }


  func onNewChatMessage(message: ChatMessage) {

    // when a new chat message is shared in the meeting

  }


  func onMessageRateLimitReset() {

    // when the rate limit for sending messages of self is reset

  }

}


```

The `onChatUpdates()` method will be called whenever there is a change in the chat messages. The `messages` parameter is a list of `ChatMessage` objects that have been sent in the chat.

The `onNewChatMessage()` method will be called whenever a new chat message is shared in the meeting. The `message` parameter is a `ChatMessage` object that has been sent in the chat.

The `onMessageRateLimitReset()` method will be called when the rate limit for sending messages of self is reset and you can send messages again. The default rate limit is 180 messages within 60 seconds.

To be able to receive chat messages you need to implement a method `onChatUpdates()` method from callback `RtkChatEventListener`. You can subscribe to this events by calling `meeting.addChatEventListener(rtkChatEventListener)`.

Dart

```

class ChatEventListener extends RtkChatEventListener {

  @override

  void onChatUpdates(List<ChatMessage> messages) {

    messages.map((msg) {

      switch (msg.type) {

        case MessageType.text:

          print((msg as TextMessage).displayName);

          print((msg).message);


          // Show message/return state to show text message UI.


          break;

        case MessageType.image:

          print((msg as ImageMessage).displayName);

          print((msg).link);


          // Show message/return state to show image message UI.

          break;

        case MessageType.file:

          print((msg as FileMessage).name);

          print((msg).link);

          print((msg).size);

          // Show message/return state to show file message UI.


          break;

      }

    });

  }


  void onNewChatMessage(ChatMessage message) {

    // your code to handle new chat message

  }

}


```

In this context, `messages` refers to a list of all the chat messages in the meeting. The type of message used is `ChatMessage`, which was introduced earlier in the introduction to Chat topic.

Whenever a chat message is received, the `meeting.chat.messages` list is automatically updated.

The `meeting.chat` object emits events when new chat messages are received. You can listen for the `chatUpdate` event to log when a new chat message is received.

```

meeting.chat.on("chatUpdate", ({ message, messages }) => {

  console.log(`Received message ${message}`);

  console.log(`All messages in chat: ${messages.join(", ")}`);

});


```

Here, `message` is of type `Message`, as defined in the introduction. `messages` is a list of all chat messages in the meeting, which is the same as `meeting.chat.messages`.

When a chat message is received, the `meeting.chat.messages` list is also updated.

```

console.log(JSON.stringify(meeting.chat.messages));


meeting.chat.on("chatUpdate", () => {

  console.log(JSON.stringify(meeting.chat.messages));

});


```

## Editing Chat Messages

### Edit a Text Message

There is a method in `meeting.chat` to edit a message of each type.

To edit a text message, use the `meeting.chat.editTextMessage()` method. This accepts a `messageId` (type `string`) and a `message` (type `string`).

JavaScript

```

const message = meeting.chat.messages[0];

const messageId = message?.id;

const newMessage = "Is this the real life?";


await meeting.chat.editTextMessage(messageId, newMessage);


```

There is a method in `meeting.chat` to edit a message of each type.

To edit a text message, use the `meeting.chat.editTextMessage()` method. This accepts a `messageId` (type `string`) and a `message` (type `string`).

```

const message = meeting.chat.messages[0];

const messageId = message?.id;

const newMessage = "Is this the real life?";


await meeting.chat.editTextMessage(messageId, newMessage);


```

There is a method in `meeting.chat` to edit a message of each type.

To edit a text message, use the `meeting.chat.editTextMessage()` method. This accepts a `messageId` (type `string`) and a `message` (type `string`).

```

const message = meeting.chat.messages[0];

const messageId = message?.id;

const newMessage = "Is this the real life?";

await meeting.chat.editTextMessage(messageId, newMessage);


```

### Edit an Image

You can edit an image with the help of `meeting.chat.editImageMessage()`. This accepts a `messageId` of type `string` and an image of type `File`.

```

<label for="img">Edit image:</label>

<input type="file" id="img" name="img" accept="image/*" />

<button onclick="onEditImage()">Edit Image</button>


```

JavaScript

```

async function onEditImage() {

  const messageId = "...";

  const image = document.getElementById("img");

  await meeting.chat.editImageMessage(messageId, image.files[0]);

}


```

You can edit an image with the help of `meeting.chat.editImageMessage()`. This accepts a `messageId` of type `string` and an image of type `File`.

```

import { useRef } from "react";


function ChatComponent() {

  const imageInputRef = useRef(null);


  const onEditImage = async () => {

    const messageId = "...";

    const image = imageInputRef.current;

    if (image && image.files[0]) {

      await meeting.chat.editImageMessage(messageId, image.files[0]);

    }

  };


  return (

    <>

      <label htmlFor="img">Edit image:</label>

      <input

        type="file"

        id="img"

        name="img"

        accept="image/*"

        ref={imageInputRef}

      />

      <button onClick={onEditImage}>Edit Image</button>

    </>

  );

}


```

You can edit an image with the help of `meeting.chat.editImageMessage()`. This accepts a `messageId` of type `string` and an image of type File.

```

import DocumentPicker from "@react-native-documents/picker";


async function onEditImage() {

  const messageId = "...";

  // Get the image uri and create an object with the following fields

  const res = await DocumentPicker.pickSingle({

    type: [DocumentPicker.types.images],

  });

  const image = {

    uri: res.uri,

    name: res.name,

    size: res.size,

    type: res.type,

  };

  await meeting.chat.editImageMessage(messageId, image);

}


```

### Edit a File

Editing a file is similar to editing an image. To edit a file, use `meeting.chat.editFileMessage()`.

```

<label for="file">Edit file:</label>

<input type="file" id="file" name="file" />

<button onclick="onEditFile()">Edit File</button>


```

JavaScript

```

async function onEditFile() {

  const messageId = "...";

  const file = document.getElementById("file");

  await meeting.chat.editFileMessage(messageId, file.files[0]);

}


```

Editing a file is similar to editing an image. To edit a file, use `meeting.chat.editFileMessage()`.

```

import { useRef } from "react";


function ChatComponent() {

  const fileInputRef = useRef(null);


  const onEditFile = async () => {

    const messageId = "...";

    const file = fileInputRef.current;

    if (file && file.files[0]) {

      await meeting.chat.editFileMessage(messageId, file.files[0]);

    }

  };


  return (

    <>

      <label htmlFor="file">Edit file:</label>

      <input type="file" id="file" name="file" ref={fileInputRef} />

      <button onClick={onEditFile}>Edit File</button>

    </>

  );

}


```

Editing a file is similar to editing an image. To edit a file, use `meeting.chat.editFileMessage()`.

```

import DocumentPicker from "@react-native-documents/picker";


async function onEditFile() {

  const messageId = "...";

  // Get the file uri and create an object with the following fields

  const res = await DocumentPicker.pickSingle({

    type: [DocumentPicker.types.allFiles],

  });

  const file = {

    uri: res.uri,

    name: res.name,

    size: res.size,

    type: res.type,

  };

  await meeting.chat.editFileMessage(messageId, file);

}


```

### Edit Any Message Type

There is also a common method called `meeting.chat.editMessage()` that can be used to edit any of the three types of messages displayed above. It essentially calls one of the methods from above depending upon the type of payload you send to the method. The `editMessage()` method accepts parameters `messageId` and `message` of the following type:

TypeScript

```

async function editMessage(

  messageId: string,

  message:

    | { type: "text"; message: string }

    | { type: "image"; image: File }

    | { type: "file"; file: File },

) {

  // ...

}


```

Here is how you would use the `editMessage()` method to edit a text message:

JavaScript

```

const messageId = "...";

const message = "Is this just fantasy?";

await meeting.chat.editMessage(messageId, { type: "text", message });


```

There is also a common method called `meeting.chat.editMessage()` that can be used to edit any of the three types of messages displayed above. It essentially calls one of the methods from above depending upon the type of payload you send to the method. The `editMessage()` method accepts parameters `messageId` and `message` of the following type:

TypeScript

```

async function editMessage(

  messageId: string,

  message:

    | { type: "text"; message: string }

    | { type: "image"; image: File }

    | { type: "file"; file: File },

) {

  // ...

}


```

Here is how you would use the `editMessage()` method to edit a text message:

```

const messageId = "...";

const message = "Is this just fantasy?";

await meeting.chat.editMessage(messageId, { type: "text", message });


```

There is also a common method called `meeting.chat.editMessage()` that can be used to edit any of the three types of messages displayed above. It essentially calls one of the methods from above depending upon the type of payload you send to the method. The `editMessage()` method accepts parameters `messageId` and `message` of the following type:

TypeScript

```

async function editMessage(

  messageId: string,

  message:

    | { type: "text"; message: string }

    | { type: "image"; image: File }

    | { type: "file"; file: File },

) {

  // ...

}


```

Here is how you would use the `editMessage()` method to edit a text message:

```

const messageId = "...";

const message = "Is this just fantasy?";

await meeting.chat.editMessage(messageId, { type: "text", message });


```

## Other Chat Functions

### Get Messages by a User

The `meeting.chat` object exposes certain other methods for convenience when working with chat.

You can get messages by a particular user by passing the user's ID to the `meeting.chat.getMessagesByUser()` method.

JavaScript

```

// Find the userId of the user with name "Freddie".

const { userId } = meeting.participants.joined

  .toArray()

  .find((p) => p.name === "Freddie");


const messages = meeting.chat.getMessagesByUser(userId);


```

The `meeting.chat` object exposes certain other methods for convenience when working with chat.

You can get messages by a particular user by passing the user's ID to the `meeting.chat.getMessagesByUser()` method.

```

// Find the userId of the user with name "Freddie".

const { userId } = meeting.participants.joined

  .toArray()

  .find((p) => p.name === "Freddie");


const messages = meeting.chat.getMessagesByUser(userId);


```

The `meeting.chat` object exposes certain other methods for convenience when working with chat.

You can get messages by a particular user by passing the user's ID to the `meeting.chat.getMessagesByUser()` method.

```

// Find the userId of the user with name "Freddie".

const { userId } = meeting.participants.joined

  .toArray()

  .find((p) => p.name === "Freddie");


const messages = meeting.chat.getMessagesByUser(userId);


```

### Get Messages of a Particular Type

You can also get messages of a particular type using the `meeting.chat.getMessagesByType()` method. For example, you can get all image messages present in the chat using the following snippet:

JavaScript

```

const imageMessages = meeting.chat.getMessagesByType("image");


```

You can also get messages of a particular type using the `meeting.chat.getMessagesByType()` method. For example, you can get all image messages present in the chat using the following snippet:

```

const imageMessages = meeting.chat.getMessagesByType("image");


```

You can also get messages of a particular type using the `meeting.chat.getMessagesByType()` method. For example, you can get all image messages present in the chat using the following snippet:

```

const imageMessages = meeting.chat.getMessagesByType("image");


```

### Pinning a Chat Message

You can pin a number of messages to the chat. When you pin a message, the message object will have the attribute `pinned: true`, using which you can identify if a message is pinned.

To pin a message:

JavaScript

```

// Pin the first message in the chat (could be text, image, or file).

const { id } = meeting.chat.messages[0];

await meeting.chat.pin(id);


```

Once you pin a message, it will be added to `meeting.chat.pinned`.

JavaScript

```

const { id } = meeting.chat.messages[0];

await meeting.chat.pin(id);


console.log(meeting.chat.pinned);

console.log(meeting.chat.pinned.length > 0); // Should be true


```

You can also unpin a pinned message by using the `meeting.chat.unpin()` method.

JavaScript

```

// Unpin the first pinned message.

const { id } = meeting.chat.pinned[0];

await meeting.chat.unpin(id);


```

You can listen for events to know when a message is pinned or unpinned.

JavaScript

```

meeting.chat.on("pinMessage", ({ message }) => {

  console.log("A message was pinned", JSON.stringify(message));

});


meeting.chat.on("unpinMessage", ({ message }) => {

  console.log("A message was unpinned", JSON.stringify(message));

});


```

You can pin a number of messages to the chat. When you pin a message, the message object will have the attribute `pinned: true`, using which you can identify if a message is pinned.

To pin a message:

```

// Pin the first message in the chat (could be text, image, or file).

const { id } = meeting.chat.messages[0];

await meeting.chat.pin(id);


```

Once you pin a message, it will be added to `meeting.chat.pinned`.

```

const { id } = meeting.chat.messages[0];

await meeting.chat.pin(id);


console.log(meeting.chat.pinned);

console.log(meeting.chat.pinned.length > 0); // Should be true


```

You can also unpin a pinned message by using the `meeting.chat.unpin()` method.

```

// Unpin the first pinned message.

const { id } = meeting.chat.pinned[0];

await meeting.chat.unpin(id);


```

You can listen for events to know when a message is pinned or unpinned.

```

meeting.chat.on("pinMessage", ({ message }) => {

  console.log("A message was pinned", JSON.stringify(message));

});


meeting.chat.on("unpinMessage", ({ message }) => {

  console.log("A message was unpinned", JSON.stringify(message));

});


```

You can pin a number of messages to the chat. When you pin a message, the message object will have the attribute `pinned: true`, using which you can identify if a message is pinned.

To pin a message:

```

// Pin the first message in the chat (could be text, image, or file).

const { id } = meeting.chat.messages[0];

await meeting.chat.pin(id);


```

Once you pin a message, it will be added to `meeting.chat.pinned`.

```

const { id } = meeting.chat.messages[0];

await meeting.chat.pin(id);


console.log(meeting.chat.pinned);

console.log(meeting.chat.pinned.length > 0); // Should be true


```

You can also unpin a pinned message by using the `meeting.chat.unpin()` method.

```

// Unpin the first pinned message.

const { id } = meeting.chat.pinned[0];

await meeting.chat.unpin(id);


```

You can listen for events to know when a message is pinned or unpinned.

```

meeting.chat.on("pinMessage", ({ message }) => {

  console.log("A message was pinned", JSON.stringify(message));

});


meeting.chat.on("unpinMessage", ({ message }) => {

  console.log("A message was unpinned", JSON.stringify(message));

});


```

### Deleting a Chat Message

The `meeting.chat` namespace exposes a method called `deleteMessage()`. It takes a parameter `messageId` of type `string`.

JavaScript

```

const messageId = "...";

await meeting.chat.deleteMessage(messageId);


```

The `meeting.chat` namespace exposes a method called `deleteMessage()`. It takes a parameter `messageId` of type `string`.

```

const messageId = "...";

await meeting.chat.deleteMessage(messageId);


```

The `meeting.chat` namespace exposes a method called `deleteMessage()`. It takes a parameter `messageId` of type `string`.

```

const messageId = "...";

await meeting.chat.deleteMessage(messageId);


```

## Export chat messages

You can programmatically retrieve all chat messages of a RealtimeKit session in the following ways:

* Using the Chat Replay API
* Setting up webhook for the `meeting.chatSynced` event

### Get chat download URL

To get the chat download URL, make an HTTP `GET` request to the [Chat Replay API endpoint](https://developers.cloudflare.com/api/resources/realtime%5Fkit/subresources/sessions/methods/get%5Fsession%5Fchat/). The API returns:

```

{

  "success": true,

  "data": {

    "chat_download_url": "string",

    "chat_download_url_expiry": "string"

  }

}


```

* **`chat_download_url`** \- A URL that allows you to download the entire chat dump of a session in CSV format from AWS S3
* **`chat_download_url_expiry`** \- The expiry timestamp of the `chat_download_url`. If the URL expires, call this endpoint again to obtain a new download URL

For details on the Chat Replay API endpoint, refer to the [Realtime Kit API documentation](https://developers.cloudflare.com/api/resources/realtime%5Fkit/subresources/sessions/methods/get%5Fsession%5Fchat/).

### Download the chat dump file

You can download the chat dump file in CSV format by making an HTTP `GET` request to the `chat_download_url` obtained in the previous step.

The process of downloading a file from an HTTP URL differs based on whether you are downloading on the client side or server side.

#### Download on the client

To download at client side:

1. Make a `GET` request to the `chat_download_url`
2. Convert the response to a blob
3. Create an invisible `<a>` HTML element with a `download` attribute and add the blob to its `href`
4. Programmatically click on the `<a>` element so that the browser automatically starts downloading, then remove the `<a>` element

#### Download on the server

To download on the server using Node.js streams:

1. Create a writable stream for a local file
2. Make a `GET` request to `chat_download_url`
3. Get a readable stream using `res.body` and pipe to the writable stream created in the first step

### CSV chat dump format

The CSV file contains all chat messages along with participant information and metadata. It includes the following column headings:

* **`id`** \- Unique chat message ID
* **`participantId`** \- ID of the participant who sent the message
* **`sessionId`** \- The session ID from which the chat message was sent
* **`meetingId`** \- The ID of the meeting to which this session belongs
* **`displayName`** \- Display name of the participant who sent this message
* **`pinned`** \- A boolean that indicates if the current message was pinned
* **`isEdited`** \- A boolean that indicates if the current message was edited
* **`payloadType`** \- An ENUM that indicates the type of payload sent in the chat message. It can be one of `TEXT_MESSAGE`, `IMAGE_MESSAGE`, `FILE_MESSAGE`
* **`payload`** \- The actual payload sent in the chat message
* **`createdAt`** \- Timestamp when this chat message was sent

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/realtime/","name":"Realtime"}},{"@type":"ListItem","position":3,"item":{"@id":"/realtime/realtimekit/","name":"RealtimeKit"}},{"@type":"ListItem","position":4,"item":{"@id":"/realtime/realtimekit/core/","name":"Build using Core SDK"}},{"@type":"ListItem","position":5,"item":{"@id":"/realtime/realtimekit/core/chat/","name":"Chat"}}]}
```
