Three ways to add chat to your video calls with the Daily API

Get chatty with Daily

We have lots of conversations with developers building on Daily. One of the most common questions we hear is, “How can we add chat to our calls?” ‍

There are lots of reasons why teams might want to make text chat a part of their meetings, like if they’re building:

  • Classrooms, where a teacher might need to share lesson-related links or activities with students.

  • Virtual tours, when follow up information like detailed pricing could be sent instantly via chat instead of in an email later.

  • Any situation that needs a way for meeting participants to share thoughts and questions without interrupting the current speaker. (We can think of many of those!)

This post walks through all the ways to add chat to your video calls using just the Daily API: with our prebuilt UI from the dashboard or via a POST request to our /rooms endpoint, or within your own custom call layout. ‍

Enable chat in Daily's prebuilt UI

If you want to build a fast prototype or to minimize developer time for any reason, our prebuilt UI is the quickest way to get a chat enabled video call up and running quickly. Of course, a few trade offs come with speed. The default interface we provide is pretty set: you won’t be able to change how the chat icon or conversation thread appears. And, chat in this interface isn’t exposed to our API. It only persists during the call, so in order to see a chat history, you must save the messages in a downloadable text file before exiting the meeting. Finally, prebuilt chat isn’t currently available as a feature in HIPAA compliant calls.

If a more customizable option sounds like a better fit for you, skip ahead to "Build your own custom chat." Otherwise, read on! ‍

Turn on chat from the dashboard

Earlier this month, we launched lots of new features in the dashboard, including advanced room customization. ‍ From, click “Rooms” on the left navigation bar. Click the “Create room” button, and you should see lots of options for setting up your new room. Scroll to “Show advanced room settings.” You should see a menu that lists “Text chat” as an option. Toggle the “Off” button to “On.” After reviewing the other settings, click “Create room” at the bottom of the page.

Screenshot of the Daily dashboard advanced room settings.
Turn on “Text chat” from the advanced room settings in the Daily dashboard.

With that, you should have a prebuilt Daily room with chat enabled ready to go! Copy and paste the link in your browser, and look for the chat option in the bottom left toolbar:

Screenshot of call with chat enabled.
Look for the chat icon in the bottom left corner.

Create a chat enabled room with a POST request

If you'd rather not use the dashboard, you can also create a prebuilt Daily room with chat enabled through a POST request to our /rooms API endpoint. To make sure chat will be turned on, set the enable_chat configuration property to true:

curl --request POST \
     --url \
     --header 'authorization: Bearer INSERT_YOUR_TOKEN_HERE' \
     --header 'content-type: application/json' \
     --data '{"properties":{"enable_chat":true}}'

You should see a response like the one below if all goes well. Test the returned url in your browser to be sure.


Build your own custom chat with daily-js

While the first two options are great to get a video call with chat enabled quickly using the Daily prebuilt UI, developers sometimes need to build entirely custom video call experiences. We recommend building out those using the daily-js library in call object mode.

The Daily call object is like a direct line to the Daily API. It gives us the finest-grained control over a video call, letting us access its lowest level foundations, like participant video and audio tracks. With that great access comes great flexibility! But, it also means that features like text chat need to be added from scratch.

To add text chat to a custom call using daily-js, you’ll need to use the sendAppMessage() method and add a callback to the corresponding app-message event.

Text chat window reads a knock knock joke
This is how chat looks in our demo app, but you can style yours however you like, of course!

Let’s add chat to Paul’s original React demo app. Have a read through that post if you haven’t already, or if you’re short on time skim our demo repository's structure.

Once you’ve done that, we’re ready to add a new Chat.js component. Our <Chat> is a form that does a few things with the participant <input>, the message they type into chat. First, via React’s useState hook and our handleChange function, it tracks their input in the component state inputValue.

const [inputValue, setInputValue] = useState('');

const handleChange = (event) => {
useState hook and handleChange() function

When a participant sends a message, they call our handleSubmit function, which broadcasts the message stored in inputValue to other participants on the call using Daily’s sendAppMessage method.

callObject.sendAppMessage({ message: inputValue }, '-')
snippet from handleSubmit() that calls the Daily sendAppMessage() method

handleSubmit also updates the sender’s chatHistory state.

const name = callObject.participants().local.user_name
     ? callObject.participants().local.user_name
     : 'Guest';
       sender: name,
       message: inputValue,
snippet updates chatHistory state

In the return statement, <Chat> maps over every value in chatHistory to display the messages.

{, index) => (
   <div key={`entry-${index}`} className="messageList">
      <b>{entry.sender}</b>: {entry.message}

That covers what happens for the sender. As for the recipients, after the Daily sendAppMessage fires, it triggers the Daily "app-message" event. Our handleAppMessage event listener reacts to every "app-message." The handler gets the name of the sender from the Daily call object, and updates recipients’ chat histories using setChatHistory.

const participants = callObject.participants();
     const name = participants[event.fromId].user_name
       ? participants[event.fromId].user_name
       : 'Guest';
         sender: name,

After updating state, the function calls the props.notification() passed down from the parent <Tray> to highlight the recipient’s chat icon.

Menu bar with camera mic screenshare and chat icons; chat flickers on and off
Chat lights up when a call participant receives a new message

We added that chat icon in Tray.js, where we pass state booleans and controller functions as props to Chat.js that determine whether the icon is highlighted or if the chat window should be displayed (when it’s been clicked).

const [displayChat, setChatDisplay] = useState(false);
const [highlightedChat, setChatHighlight] = useState(false);

function toggleChat() {
   if (highlightedChat) {
function handleNewChat() {

// Relevant component snippets 
     <Chat onClickDisplay={displayChat} notification={handleNewChat} />

Want to chat more?

There are so many ways to keep customizing Daily calls. While we hope this post is a good springboard for adding text chat to your custom video calls, you might be interested in more advanced functionality, like enabling file exchange or a chat history that persists after a call ends. A third-party chat integration would be the best way to do that. Stay tuned for more!

For now, experiment with our repository, and please send feedback our way any time at

Never miss a story

Get the latest direct to your inbox.