Use in-meeting chat

The code on this page works with either the default UI or the custom UI.

The Meeting SDK lets you use in-meeting chat to communicate with other participants in the same meeting.

Handle chat functionality through the InMeetingChatController interface.

if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() {
}
ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController];
if (meetingChatController) {
}

Control chat settings

Before you use in-meeting chat, check if the current meeting or webinar supports chat, and then look at which participants or attendees can use chat.

Chat settings in a meeting

In a meeting, use ZoomSDKMeetingActionController.

if let meetingActionCtrl = ZoomSDK.shared().getMeetingService()?.getMeetingActionController() {
    if meetingActionCtrl.isParticipantsChatAllowed() {
    }
    // OR for more breakdown
    if let normalMeetingPrivilege = meetingActionCtrl.getChatStatus()?.getNormalMeetingPrivilege() {
        normalMeetingPrivilege.canChat
        normalMeetingPrivilege.canChatToAll
        normalMeetingPrivilege.canChatToIndividual
        normalMeetingPrivilege.isOnlyCanChatToHost
    }
}
ZoomSDKMeetingActionController *meetingActionCtrl = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingActionController];
if (meetingActionCtrl) {
    if (meetingActionCtrl.isParticipantsChatAllowed) {
    }
    // OR for more breakdown
    ZoomSDKNormalMeetingChatPrivilege *normalMeetingPrivilege = [[meetingActionCtrl getChatStatus] getNormalMeetingPrivilege];
    if (normalMeetingPrivilege) {
        normalMeetingPrivilege.canChat;
        normalMeetingPrivilege.canChatToAll;
        normalMeetingPrivilege.canChatToIndividual;
        normalMeetingPrivilege.isOnlyCanChatToHost;
    }
}

The ZoomSDKNormalMeetingChatPrivilege has these values.

  • canChat - The user may use chat to send both private and public messages.
  • canChatToAll - The user may use chat, but private messages are not allowed.
  • canChatToIndividual - The user may use chat only to individual user.
  • isOnlyCanChatToHost - The user may use chat only to host.

If the current user is the meeting's host, they can control chat settings by specifying a ZoomSDKChatPrivilegeType.

meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_Everyone)
meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_Host)
meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_Disable_Attendee_Chat)
meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_Host_Public)
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_Everyone];
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_Host];
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_Disable_Attendee_Chat];
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_Host_Public];

Chat settings in a webinar

In a webinar, use ZoomSDKMeetingActionController or ZoomSDKWebinarController.

if let webinarCtrl = ZoomSDK.shared().getMeetingService()?.getWebinarController() {
    // Attendee - ZoomSDKWebinarController doesn't seem to have a getAttendeeChatPriviledge  and only has getPanelistChatPrivilege
    // Panelist
    var panelistChatPriviledge: ZoomSDKPanelistChatPrivilege = ZoomSDKPanelistChatPrivilege_PanelistOnly
    if webinarCtrl.getPanelistChatPrivilege(&panelistChatPriviledge) == ZoomSDKError_Success {
        switch panelistChatPriviledge {
        case ZoomSDKPanelistChatPrivilege_PanelistOnly:
            // Allow panelists only to chat with each other
            return
        case ZoomSDKPanelistChatPrivilege_All:
            // Allow panelist to chat with everyone
            return
        default:
            // There won't be a default case
            return
        }
    }
}
// OR for more breakdown
if let meetingActionCtrl = ZoomSDK.shared().getMeetingService()?.getMeetingActionController() {
    // Attendee
    if let webinarAttendeeChatPrivilege = meetingActionCtrl.getChatStatus()?.getWebinarAttendeePrivilege() {
        webinarAttendeeChatPrivilege.canChat
        webinarAttendeeChatPrivilege.canChatToAllPanellist
        webinarAttendeeChatPrivilege.canChatToAllPanellistAndAttendee
    }
    // Panelist
    if let webinarPanelistChatPrivilege = meetingActionCtrl.getChatStatus()?.getWebinarPanelistPrivilege() {
        webinarPanelistChatPrivilege.canChatToIndividual
        webinarPanelistChatPrivilege.canChatToAllPanellist
        webinarPanelistChatPrivilege.canChatToAllPanellistAndAttendee
    }
}
ZoomSDKWebinarController *webinarCtrl = [[[ZoomSDK sharedSDK] getMeetingService] getWebinarController];
if (webinarCtrl) {
    // Attendee - ZoomSDKWebinarController doesn't seem to have a getAttendeeChatPriviledge  and only has getPanelistChatPrivilege
    // Panelist
    ZoomSDKPanelistChatPrivilege panelistChatPriviledge = ZoomSDKPanelistChatPrivilege_PanelistOnly;
    if ([webinarCtrl getPanelistChatPrivilege:&panelistChatPriviledge] == ZoomSDKError_Success) {
        switch (panelistChatPriviledge) {
            case ZoomSDKPanelistChatPrivilege_PanelistOnly:
                return;
            case  ZoomSDKPanelistChatPrivilege_All:
                // Allow panelists to chat with everyone
                return;
            default:
                // There won't be a default case
                return;
        }
    }
}
// OR for more breakdown
ZoomSDKMeetingActionController *meetingActionCtrl = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingActionController];
if (meetingActionCtrl) {
    // Attendee
    ZoomSDKWebinarAttendeeChatPrivilege *webinarAttendeeChatPrivilege = [[meetingActionCtrl getChatStatus] getWebinarAttendeePrivilege];
    if (webinarAttendeeChatPrivilege) {
        webinarAttendeeChatPrivilege.canChat;
        webinarAttendeeChatPrivilege.canChatToAllPanellist;
        webinarAttendeeChatPrivilege.canChatToAllPanellistAndAttendee;
    }
    // Panelist
    ZoomSDKWebinarPanelistChatPrivilege *webinarPanelistChatPrivilege = [[meetingActionCtrl getChatStatus] getWebinarPanelistPrivilege];
    if (webinarPanelistChatPrivilege) {
        webinarPanelistChatPrivilege.canChatToIndividual;
        webinarPanelistChatPrivilege.canChatToAllPanellist;
        webinarPanelistChatPrivilege.canChatToAllPanellistAndAttendee;
    }
}

The ZoomSDKWebinarAttendeeChatPrivilege uses one of these values.

  • canChat - Attendee can send message to chat.
  • canChatToAllPanellist - Can send message to all the panelists.
  • canChatToAllPanellistAndAttendee - Can send message to all the panelists and attendees.

The ZoomSDKWebinarPanelistChatPrivilege uses one of these values.

  • canChatToIndividual - Can send message to individual attendee.
  • canChatToAllPanellist - Can send message to all the panelists.
  • canChatToAllPanellistAndAttendee - Can send message to all.

Update a webinar's chat settings by setting a ZoomSDKChatPrivilegeType.

meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_Everyone)
meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_All_Panelist)
meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_Disable_Attendee_Chat)
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_Everyone];
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_All_Panelist];
[meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_Disable_Attendee_Chat];

Send messages

To send a public message in either a meeting or a webinar, instantiate a ChatMessageBuilder and set the content and message type.

if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() {
    let chatMsgInfoBuilder = ZoomSDKChatMsgInfoBuilder()
    /*
     Receiver (userID parameter) -
     For sending to all or all panelist: 0
     For sending to a specific user: the user's userID
     MessageType (ZoomSDKChatMessageType) -
     ZoomSDKChatMessageType_To_All - Meeting = to everyone or Webinar = to all panelist and attendees
     ZoomSDKChatMessageType_To_All_Panelist - Webinar = to all panelists
     ZoomSDKChatMessageType_To_Individual_Panelist - Webinar = to individual panelist
     ZoomSDKChatMessageType_To_Individual - To individual user
     */
    chatMsgInfoBuilder.setContent("Hello World!").setReceiver(0).setMessageType(ZoomSDKChatMessageType_To_All)
    let chatInfo = chatMsgInfoBuilder.build()
    meetingChatController.sendChatMsg(to: chatInfo)
}
ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController];
if (meetingChatController) {
    ZoomSDKChatMsgInfoBuilder *chatMsgInfoBuilder = [[ZoomSDKChatMsgInfoBuilder alloc] init];
    /*
     Receiver (userID parameter) -
     For sending to all or all panelist: 0
     For sending to a specific user: the user's userID
     MessageType (ZoomSDKChatMessageType) -
     ZoomSDKChatMessageType_To_All - Meeting = to everyone or Webinar = to all panelist and attendees
     ZoomSDKChatMessageType_To_All_Panelist - Webinar = to all panelists
     ZoomSDKChatMessageType_To_Individual_Panelist - Webinar = to individual panelist
     ZoomSDKChatMessageType_To_Individual - To individual user
     */
    [[[chatMsgInfoBuilder setContent:@"Hello World!"] setReceiver:0] setMessageType:ZoomSDKChatMessageType_To_All];
    ZoomSDKChatInfo *info = [chatMsgInfoBuilder build];
    ZoomSDKError error = [meetingChatController sendChatMsgTo:info];
}

To reply to an existing message in a thread, first get a threadId for the message being responded to. For more information on how to get the threadId, see Receive messages. Once you've retrieved the thread ID, pass it in and set the type based on whether the parent message is public or private.

if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() {
    // 1. Identify the message (ZoomSDKChatInfo) you want to reply to and get its threadID
    let chatInfo: ZoomSDKChatInfo? = nil
    guard let chatInfo = chatInfo else { return }
    let threadID = chatInfo.getThreadID()
    // 2. Build ZoomSDKChatMsgInfoBuilder with threadID
    let threadReplyMessage = ZoomSDKChatMsgInfoBuilder().setThreadId(threadID).setContent("Reply to Hello World!").setMessageType(ZoomSDKChatMessageType_To_All).build()
    // 3. Send reply message
    meetingChatController.sendChatMsg(to: threadReplyMessage)
}
ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController];
if (meetingChatController) {
    // 1. Identify the message (ZoomSDKChatInfo) you want to reply to and get its threadID
    ZoomSDKChatInfo *chatInfo = nil;
    if (!chatInfo) {
        return;
    }
    NSString *threadID = chatInfo.getThreadID;
    // 2. Build ZoomSDKChatMsgInfoBuilder with threadID
    ZoomSDKChatMsgInfoBuilder *chatMsgInfoBuilder = [[ZoomSDKChatMsgInfoBuilder alloc] init];
    ZoomSDKChatInfo *threadReplyMessage = [[[[chatMsgInfoBuilder setThreadId:threadID] setContent:@"Reply to Hello World!"] setMessageType:ZoomSDKChatMessageType_To_All] build];
    // 3. Send reply message
    ZoomSDKError error = [meetingChatController sendChatMsgTo:threadReplyMessage];
}

Messages sent from the SDK can also include quoted text. The quote position specifies the start and end characters in the quoted text string.

if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() {
    // Using positionStart as 0 and positionEnd as 42 as an example
    let quoteMessage = ZoomSDKChatMsgInfoBuilder().setQuotePosition(0, positionEnd: 42).setContent("This is a sample message stylized as a quote").setMessageType(ZoomSDKChatMessageType_To_All).build()
    meetingChatController.sendChatMsg(to: quoteMessage)
}
ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController];
if (meetingChatController) {
    // Using positionStart as 0 and positionEnd as 42 as an example
    ZoomSDKChatMsgInfoBuilder *chatMsgInfoBuilder = [[ZoomSDKChatMsgInfoBuilder alloc] init];
    ZoomSDKChatInfo *quoteMessage = [[[[chatMsgInfoBuilder setQuotePosition:0 positionEnd:42] setContent:@"This is a sample message stylized as a quote"] setMessageType:ZoomSDKChatMessageType_To_All] build];
    ZoomSDKError error = [meetingChatController sendChatMsgTo:quoteMessage];
}

Receive messages

To display content from chat messages, the SDK provides a callback to get notified of when a new message is sent to the meeting. You can also use this callback to confirm that a message sent by the current user has successfully been posted to the meeting chat.

Confirm to the ZoomSDKMeetingChatControllerDelegate protocol first, then use the chatInfo parameter within onChatMessageNotification to get information about the chat message. Some data, like receiverID, will only be available for specific types of messages.

if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() {
meetingChatController.delegate = self
}
func onChatMessageNotification(_ chatInfo: ZoomSDKChatInfo) {
    chatInfo.getMessageID() // A unique identifier assigned to this message.
    chatInfo.getMsgContent() // The content of the message that is visible to users in the meeting.
    chatInfo.getTimeStamp() // The time at which the message was sent.
    chatInfo.getSenderUserID() // The Zoom user ID of the user who sent the message.
    chatInfo.getSenderDisplayName() // The display name of the user who sent the message.
    chatInfo.getReceiverUserID() // The Zoom user ID of the user on the receiving end of a private message.
    chatInfo.getReceiverDisplayName() // The display name of the user on the receiving end of a private message.
    chatInfo.isChatToWaitingRoom() // Whether the message was sent to the waiting room.
    chatInfo.getChatMessageType() // The message type, see "ZoomSDKChatMessageType".
    chatInfo.isComment() // Whether the chat message is a comment responding to a thread.
    chatInfo.isThread() // Whether the chat message is a thread with comments.
    chatInfo.getThreadID() // The unique identifier associated with a thread
    chatInfo.getSegmentDetails() // Get the detailed attributes such as bold, italic, strikethrough and more.
}
// In your .h file
@interface ZMSDKWindow : NSWindowController <ZoomSDKMeetingChatControllerDelegate> {
}
// In your .m file
- (void)onChatMessageNotification:(ZoomSDKChatInfo *)chatInfo {
    [chatInfo getMessageID]; // A unique identifier assigned to this message.
    [chatInfo getMsgContent]; // The content of the message that is visible to users in the meeting.
    [chatInfo getTimeStamp]; // The time at which the message was sent.
    [chatInfo getSenderUserID]; // The Zoom user ID of the user who sent the message.
    [chatInfo getSenderDisplayName]; // The display name of the user who sent the message.
    [chatInfo getReceiverUserID]; // The Zoom user ID of the user on the receiving end of a private message.
    [chatInfo getReceiverDisplayName]; // The display name of the user on the receiving end of a private message.
    [chatInfo isChatToWaitingRoom]; // Whether the message was sent to the waiting room.
    [chatInfo getChatMessageType]; // The message type, see "ZoomSDKChatMessageType".
    [chatInfo isComment]; // Whether the chat message is a comment responding to a thread.
    [chatInfo isThread]; // Whether the chat message is a thread with comments.
    [chatInfo getThreadID]; // The unique identifier associated with a thread
    [chatInfo getSegmentDetails]; // Get the detailed attributes such as bold, italic, strikethrough and more.
}

Delete messages

To delete a message sent by the current user, call the deleteChatMessage method under ZoomSDKMeetingActionController with the msgId. This will trigger the onChatMsgDeleteNotification callback under ZoomSDKMeetingActionControllerDelegate

if let meetingActionController = ZoomSDK.shared().getMeetingService()?.getMeetingActionController() {
    let msgID: String = ""
    if meetingActionController.isChatMessageCanBeDeleted(msgID) {
        meetingActionController.deleteChatMessage(msgID)
    }
}
- (void) deleteMessage {
    ZoomSDKMeetingActionController *meetingActionController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingActionController];
    if (meetingActionController) {
        NSString *msgID = @"";
        if ([meetingActionController isChatMessageCanBeDeleted:msgID]) {
            [meetingActionController deleteChatMessage:msgID];
        }
    }
}

Parse text format

The SDK supports receiving various styles of chat messages such as bold, italic, quote, font color and size, and many more. The styles are included as a list of ZoomSDKChatMsgSegmentDetails objects under each of the ZoomSDKChatInfo object.

if let chatInfoSegmentDetails = chatInfo.getSegmentDetails() {
    for segment in chatInfoSegmentDetails {
        segment.strContent
        segment.boldAttrs
        segment.italicAttrs
        segment.underlineAttrs // and more
    }
}
NSArray<ZoomSDKChatMsgSegmentDetails *> *chatInfoSegmentDetails = [chatInfo getSegmentDetails];
if (chatInfoSegmentDetails) {
    for (ZoomSDKChatMsgSegmentDetails *segment in chatInfoSegmentDetails) {
        [segment strContent];
        [segment boldAttrs];
        [segment italicAttrs];
        [segment underlineAttrs]; // and more
    }
}

Understanding all the chat callbacks

For chat related callbacks, there are 2 delegates to subscribe to.

Under ZoomSDKMeetingActionControllerDelegate, the callbacks are onChatStatusChangedNotification and onChatMsgDeleteNotification.

Under ZoomSDKMeetingChatControllerDelegate, the callbacks are onChatMessageNotification and onChatMessageEditNotification.