# Breakout Rooms Programmatically manage breakout rooms in Zoom meetings across all platforms. ## Overview 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 | 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. ## REST API: Pre-assigned Rooms Create meetings with pre-assigned breakout rooms: ```bash POST /v2/users/{userId}/meetings ``` ```json { "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. --- ## Web SDK Implementation ### Create Breakout Rooms ```javascript // 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) }); ``` ### Get Breakout Rooms ```javascript 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) }); ``` ### Assign Participants ```javascript // 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) }); ``` ### Move Participants Between Rooms ```javascript ZoomMtg.BreakoutRoom.moveUserToBreakoutRoom({ targetRoomId: 'destination-room-id', userId: 12345678, success: (response) => console.log('Moved:', response), error: (error) => console.error('Error:', error) }); ``` ### Open Breakout Rooms ```javascript 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) }); ``` ### Close Breakout Rooms ```javascript ZoomMtg.BreakoutRoom.closeBreakoutRooms({ success: (response) => console.log('Rooms closed:', response), error: (error) => console.error('Error:', error) }); ``` ### Broadcast Message ```javascript 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) }); ``` ### Check User Status ```javascript // 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 ``` --- ## iOS SDK Implementation ### Get Helpers ```objc #import // 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 Rooms ```objc // 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 }]; ``` ### Manage Rooms ```objc // 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"); } }]; ``` ### Event Handling ```objc @interface MyDelegate : NSObject @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; } } @end ``` --- ## Android SDK Implementation ### Get Helpers ```kotlin import 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 Rooms ```kotlin // 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") ``` ### Manage Rooms ```kotlin // 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() ``` --- ## Windows/macOS SDK Implementation ### Windows (C++) ```cpp #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* 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(); ``` ### macOS (Objective-C) ```objc #import // 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]; ``` --- ## Permissions ### Host/Co-Host Restrictions | 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. --- ## Limitations ### Capacity Limits | Account Type | Max Rooms | Max Participants | |--------------|-----------|------------------| | Standard | 50 rooms | 500 total | | Large Meeting Add-on | 100 rooms | 1,000 total | ### Recording Limitations - **Cloud Recording**: Only records the **main session** - **Local Recording**: Records only the room the recorder is in - **Host cannot record** breakout rooms they're not in ### Cannot Auto-Open Pre-Assigned Rooms **Critical:** There is NO API to auto-open pre-assigned breakout rooms. The host MUST manually open rooms when the meeting starts. ### Session Timeout 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. --- ## Best Practices ### 1. Check Support Before Creating ```javascript ZoomMtg.BreakoutRoom.getBreakoutRoomOptions({ success: (response) => { if (response.result.isSupportBreakoutRoom) { // Proceed to create rooms } } }); ``` ### 2. Handle User Status ```javascript // 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 } } }); ``` ### 3. Error Handling ```javascript 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 Note Video SDK does **NOT** have native breakout rooms. Instead, use "Subsessions": 1. Create separate Video SDK sessions 2. Move participants between sessions programmatically 3. Implement your own room management logic See: https://developers.zoom.us/blog/build-breakout-rooms-for-video-sdk/ --- ## Resources - **Web SDK Docs**: https://developers.zoom.us/docs/meeting-sdk/web/ - **iOS SDK Docs**: https://developers.zoom.us/docs/meeting-sdk/ios/ - **Android SDK Docs**: https://developers.zoom.us/docs/meeting-sdk/android/ - **REST API - Meetings**: https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#tag/Meetings - **Developer Forum**: https://devforum.zoom.us/