Skill 121 · Build Zoom Meeting SDK App
Subchapter 121.5
references/breakout-rooms.mdMarkdown12 KBView on GitHub
Programmatically manage breakout rooms in Zoom meetings across all platforms.
Breakout rooms allow hosts to split meeting participants into smaller groups. This guide covers SDK APIs for creating, managing, and controlling breakout rooms.
| Platform | Support Level | Notes |
|---|---|---|
| Web SDK | Full | Complete API |
| iOS SDK | Full | Creator + Admin helpers |
| Android SDK | Full | Creator + Admin helpers |
| Windows SDK | Full | Controller interface |
| macOS SDK | Full | Controller interface |
| Linux SDK | Limited | Basic functionality only |
| Video SDK | Different | Uses “Subsessions” - not native breakout rooms |
Important: Video SDK does NOT have native breakout rooms. It uses a “Subsessions” concept requiring manual session management.
Create meetings with pre-assigned breakout rooms:
POST /v2/users/{userId}/meetings{
"topic": "Team Workshop",
"type": 2,
"settings": {
"breakout_room": {
"enable": true,
"rooms": [
{
"name": "Team Alpha",
"participants": ["user1@example.com", "user2@example.com"]
},
{
"name": "Team Beta",
"participants": ["user3@example.com", "user4@example.com"]
}
]
}
}
}Limitation: Pre-assigned rooms are NOT auto-opened. The host must manually open breakout rooms when the meeting starts. There is NO REST API to auto-open rooms.
// Create 5 rooms with auto-generated names (Room 1, Room 2, etc.)
ZoomMtg.BreakoutRoom.createBreakoutRoom({
data: 5,
success: (response) => console.log('Rooms created:', response),
error: (error) => console.error('Error:', error)
});
// Create named rooms
ZoomMtg.BreakoutRoom.createBreakoutRoom({
data: [
{ name: 'Engineering' },
{ name: 'Design' },
{ name: 'Product' }
],
success: (response) => console.log('Rooms created:', response),
error: (error) => console.error('Error:', error)
});ZoomMtg.BreakoutRoom.getBreakoutRooms({
success: (response) => {
const rooms = response.result.rooms;
rooms.forEach(room => {
console.log(`Room ID: ${room.boId}, Name: ${room.name}`);
});
},
error: (error) => console.error('Error:', error)
});// Get unassigned attendees first
ZoomMtg.BreakoutRoom.getUnassignedAttendeeList({
success: (response) => {
const unassigned = response.result.unassignedAttendeeList;
console.log('Unassigned:', unassigned);
}
});
// Assign user to a room
ZoomMtg.BreakoutRoom.assignUserToBreakoutRoom({
targetRoomId: 'room-id-here',
userId: 12345678,
success: (response) => console.log('Assigned:', response),
error: (error) => console.error('Error:', error)
});ZoomMtg.BreakoutRoom.moveUserToBreakoutRoom({
targetRoomId: 'destination-room-id',
userId: 12345678,
success: (response) => console.log('Moved:', response),
error: (error) => console.error('Error:', error)
});ZoomMtg.BreakoutRoom.openBreakoutRooms({
options: {
isAutoJoinRoom: false, // Let participants choose
isBackToMainSessionEnabled: true, // Allow returning to main
isTimerEnabled: true, // Enable countdown
timerDuration: 1800, // 30 minutes (seconds)
needCountDown: true, // Show countdown
waitSeconds: 60 // Wait before auto-join
},
success: (response) => console.log('Rooms opened:', response),
error: (error) => console.error('Error:', error)
});ZoomMtg.BreakoutRoom.closeBreakoutRooms({
success: (response) => console.log('Rooms closed:', response),
error: (error) => console.error('Error:', error)
});ZoomMtg.BreakoutRoom.broadcast({
message: 'Please return to the main room in 2 minutes',
success: (response) => console.log('Broadcast sent:', response),
error: (error) => console.error('Error:', error)
});// Get current user's breakout room
ZoomMtg.BreakoutRoom.getCurrentBreakoutRoom({
success: (response) => {
const { roomId, name, attendeeStatus } = response.result;
console.log(`Current room: ${name}, Status: ${attendeeStatus}`);
}
});
// attendeeStatus values:
// 1: UNASSIGNED - Not assigned to any room
// 2: ASSIGNED_NOT_JOIN - Assigned but hasn't joined yet
// 3: IN_BO - Currently in breakout room#import <MobileRTC/MobileRTC.h>
// Get meeting service
MobileRTCMeetingService *meetingService = [[MobileRTC sharedRTC] getMeetingService];
// Get breakout room creator (for creating rooms)
MobileRTCBOCreator *boCreator = [meetingService getCreatorHelper];
// Get breakout room admin (for managing rooms)
MobileRTCBOAdmin *boAdmin = [meetingService getAdminHelper];// Create 3 breakout rooms
[boCreator createBreakoutRoom:3 completion:^(NSError *error) {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
} else {
NSLog(@"Rooms created");
}
}];
// Create room with specific name
[boCreator createBreakoutRoomWithName:@"Engineering" completion:^(NSError *error) {
// Handle result
}];// Open all rooms
[boAdmin openAllRoomsCompletion:^(NSError *error) {
if (!error) {
NSLog(@"Rooms opened");
}
}];
// Assign user to room
[boAdmin assignUser:userId toRoom:roomId completion:^(NSError *error) {
if (!error) {
NSLog(@"User assigned");
}
}];
// Close all rooms
[boAdmin closeAllRoomsCompletion:^(NSError *error) {
if (!error) {
NSLog(@"Rooms closed");
}
}];@interface MyDelegate : NSObject <MobileRTCMeetingServiceDelegate>
@end
@implementation MyDelegate
- (void)onMeetingBreakoutRoomStatusChanged:(MobileRTCBreakoutRoomStatus)status {
switch (status) {
case MobileRTCBreakoutRoomStatusNotStarted:
NSLog(@"Breakout rooms not started");
break;
case MobileRTCBreakoutRoomStatusStarted:
NSLog(@"Breakout rooms started");
break;
case MobileRTCBreakoutRoomStatusClosed:
NSLog(@"Breakout rooms closed");
break;
}
}
@endimport us.zoom.sdk.ZoomSDK
val zoomSDK = ZoomSDK.getInstance()
val meetingService = zoomSDK.meetingService
val boController = meetingService?.inMeetingBreakoutRoomController
// Get creator (for creating rooms)
val creator = boController?.getCreatorHelper()
// Get admin (for managing rooms)
val admin = boController?.getAdminHelper()// Create breakout rooms
val error = creator?.createBreakoutRoom(5) // Create 5 rooms
if (error == SDKError.SDKERR_SUCCESS) {
Log.d("Breakout", "Rooms created")
}
// Create room with name
creator?.createBreakoutRoomWithName("Engineering")// Open all rooms
admin?.openAllRooms()
// Assign user to room
admin?.assignUser(userId, roomId)
// Move user between rooms
admin?.assignUser(userId, newRoomId) // Removes from old room
// Broadcast message
admin?.broadcastToAll("Please return in 2 minutes")
// Close all rooms
admin?.closeAllRooms()#include "meeting_breakout_rooms_interface.h"
class MyBreakoutRoomsEvent : public IMeetingBreakoutRoomsEvent {
public:
void OnBreakoutRoomsStartedNotification(const wchar_t* stBID) override {
// Handle breakout rooms started
wprintf(L"Breakout rooms started: %s\n", stBID);
}
};
// Get controller
IMeetingBreakoutRoomsController* pController =
pMeetingService->GetBreakoutRoomsController(nullptr);
// Set event handler
pController->SetEvent(new MyBreakoutRoomsEvent());
// Get list of rooms
IList<IBreakoutRoomsInfo*>* pRoomList = pController->GetBreakoutRoomsInfoList();
for (int i = 0; i < pRoomList->GetItemCount(); ++i) {
IBreakoutRoomsInfo* pRoom = pRoomList->GetItem(i);
wprintf(L"Room: %s (ID: %s)\n",
pRoom->GetBreakoutRoomName(),
pRoom->GetBID());
}
// Join a breakout room
pController->JoinBreakoutRoom(L"room-id");
// Leave breakout room
pController->LeaveBreakoutRoom();#import <ZoomSDK/ZoomSDK.h>
// Get controller
ZoomSDKBreakoutRoomsController *boController =
[[ZoomSDK sharedSDK] getMeetingService] getBreakoutRoomsController];
// Join breakout room
[boController requestJoinBreakoutRoom:@"room-id"];
// Leave breakout room
[boController requestLeaveBreakoutRoom];
// Close all rooms (host only)
[boController requestCloseAllBreakoutRooms];| Action | Host | Co-Host | Participant |
|---|---|---|---|
| Create breakout rooms | ✅ | ✅ | ❌ |
| Open breakout rooms | ✅ | ✅ | ❌ |
| Close breakout rooms | ✅ | ✅ | ❌ |
| Assign participants | ✅ | ✅ | ❌ |
| Move participants | ✅ | ❌ | ❌ |
| Broadcast messages | ✅ | ✅ | ❌ |
| Join any room | ✅ | ✅* | ❌ |
*Co-hosts can only join rooms assigned by host.
| Account Type | Max Rooms | Max Participants |
|---|---|---|
| Standard | 50 rooms | 500 total |
| Large Meeting Add-on | 100 rooms | 1,000 total |
Critical: There is NO API to auto-open pre-assigned breakout rooms. The host MUST manually open rooms when the meeting starts.
If no participant remains in the main session during breakout rooms, the main session may close after timeout. Ensure at least one participant (host or bot) stays in main session.
ZoomMtg.BreakoutRoom.getBreakoutRoomOptions({
success: (response) => {
if (response.result.isSupportBreakoutRoom) {
// Proceed to create rooms
}
}
});// Check before assigning
ZoomMtg.BreakoutRoom.getUserStatus({
userId: userId,
success: (response) => {
const { attendeeStatus } = response.result;
if (attendeeStatus === 3) { // IN_BO
// User already in a room - move instead of assign
}
}
});function handleBreakoutError(error) {
switch (error.method) {
case 'createBreakoutRoom':
if (error.errorMessage.includes('not support')) {
alert('Breakout rooms not enabled for this meeting');
}
break;
case 'assignUserToBreakoutRoom':
if (error.errorMessage.includes('not host')) {
alert('Only host/co-host can assign participants');
}
break;
}
}Video SDK does NOT have native breakout rooms. Instead, use “Subsessions”: