---
description: Use RealtimeKit host controls to mute, pin, or remove participants in a live session.
title: Manage Participants in a Session
image: https://developers.cloudflare.com/realtime/realtimekit/core/manage-participants-in-a-session/og.png?v=e51984af50731733
---

[Skip to content](#main-content)

> 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.

# Manage Participants in a Session

Last updated Aug 24, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/realtime/realtimekit/core/manage-participants-in-a-session/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Prerequisites

The local participant (for example, a host or moderator) must have the required **Host Controls** permissions enabled in their preset. For details, refer to [Preset](https://developers.cloudflare.com/realtime/realtimekit/concepts/preset/).

Use RealtimeKit host controls to manage other participants in a live session. You can mute audio or video, pin a participant, or remove participants from the session. These actions require specific host control permissions enabled in the local participant's [Preset](https://developers.cloudflare.com/realtime/realtimekit/concepts/preset/). Before you show UI controls or call these methods, verify that the local participant has the necessary permissions. In this guide, the **local participant** refers to the user performing the actions.

WebMobile

ReactWeb ComponentsAngular

### Select a remote participant

To perform actions on a specific participant, you first need to retrieve their participant object. Remote participants (other participants) are available in `meeting.participants`. The local participant is available in `meeting.self`. Refer to [Meeting Object Explained](https://developers.cloudflare.com/realtime/realtimekit/core/meeting-object-explained/) for details.

```ts
const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
	// No remote participants are currently joined.
}
```

To perform actions on a specific participant, you first need to retrieve their participant object. Remote participants (other participants) are available in `meeting.participants`. The local participant is available in `meeting.self`. Refer to [Meeting Object Explained](https://developers.cloudflare.com/realtime/realtimekit/core/meeting-object-explained/) for details.

```ts
const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
	// No remote participants are currently joined.
}
```

To perform actions on a specific participant, you first need to retrieve their participant object. Remote participants (other participants) are available in `meeting.participants`. The local participant is available in `meeting.self`. Refer to [Meeting Object Explained](https://developers.cloudflare.com/realtime/realtimekit/core/meeting-object-explained/) for details.

```ts
const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
	// No remote participants are currently joined.
}
```

To perform actions on a specific participant, retrieve their participant object from the `participants` property. Remote participants are available in `meeting.participants.joined`. The local participant is available in `meeting.localUser`.

```kotlin
val joinedParticipants = meeting.participants.joined
val participant = joinedParticipants.firstOrNull()
if (participant == null) {
	// No remote participants are currently joined.
}
```

To perform actions on a specific participant, retrieve their participant object from the `participants` property. Remote participants are available in `meeting.participants.joined`. The local participant is available in `meeting.localUser`.

```swift
let joinedParticipants = meeting.participants.joined
guard let participant = joinedParticipants.first else {
	// No remote participants are currently joined.
	return
}
```

To perform actions on a specific participant, retrieve their participant object from the `participants` property. Remote participants are available in `meeting.participants.joined`. The local participant is available in `meeting.self`.

```jsx
const joinedParticipants = meeting.participants.joined;
const participant = joinedParticipants.toArray()[0];
if (!participant) {
	// No remote participants are currently joined.
}
```

Or use the `useRealtimeKitSelector` hook:

```jsx
import { useRealtimeKitSelector } from '@cloudflare/realtimekit-react-native';

const joinedParticipants = useRealtimeKitSelector((m) => m.participants.joined);
```

## Mute audio

Mute audio of participants when you need to manage background noise, moderate a classroom or webinar, or prevent interruptions during a session. This action requires the **Mute Audio** (`disable_participant_audio`) host control permission enabled in the local participant's preset.

### Mute a participant

To mute a specific participant's audio:

1. Check that the local participant has permission to mute other participants' audio.

   ```ts
   const canMuteAudio =
   	meeting.self.permissions.canDisableParticipantAudio === true;
   if (!canMuteAudio) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAudio()` on the target participant.

   If the local participant does not have the required permission, `disableAudio()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.disableAudio();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to mute other participants’ audio.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, the target participant's `audioEnabled` becomes `false`, and the SDK emits an `audioUpdate` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
   	// audioEnabled is false
   	// Update UI for the participant
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on(
   	"audioUpdate",
   	(participant, { audioEnabled, audioTrack }) => {
   		if (participant.id === targetParticipantId) {
   			// audioEnabled is false
   			// Update UI for the participant
   		}
   	},
   );
   ```



1. Check that the local participant has permission to mute other participants' audio.

   ```ts
   const canMuteAudio =
   	meeting.self.permissions.canDisableParticipantAudio === true;
   if (!canMuteAudio) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAudio()` on the target participant.

   If the local participant does not have the required permission, `disableAudio()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.disableAudio();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to mute other participants’ audio.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, the target participant's `audioEnabled` becomes `false`, and the SDK emits an `audioUpdate` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
   	// audioEnabled is false
   	// Update UI for the participant
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on(
   	"audioUpdate",
   	(participant, { audioEnabled, audioTrack }) => {
   		if (participant.id === targetParticipantId) {
   			// audioEnabled is false
   			// Update UI for the participant
   		}
   	},
   );
   ```



1. Check that the local participant has permission to mute other participants' audio.

   ```ts
   const canMuteAudio =
   	meeting.self.permissions.canDisableParticipantAudio === true;
   if (!canMuteAudio) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAudio()` on the target participant.

   If the local participant does not have the required permission, `disableAudio()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.disableAudio();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to mute other participants’ audio.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, the target participant's `audioEnabled` becomes `false`, and the SDK emits an `audioUpdate` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
   	// audioEnabled is false
   	// Update UI for the participant
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on(
   	"audioUpdate",
   	(participant, { audioEnabled, audioTrack }) => {
   		if (participant.id === targetParticipantId) {
   			// audioEnabled is false
   			// Update UI for the participant
   		}
   	},
   );
   ```



1. Check that the local participant has permission to mute other participants' audio.

```kotlin
val canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if (!canMuteAudio) {
	// Disable the control in your UI.
}
```

2. Call `disableAudio()` on the target participant. If the local participant does not have the required permission, `disableAudio()` returns a `HostError`.

```kotlin
val error = participant.disableAudio()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `audioEnabled` becomes `false`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// audioEnabled is false
		// Update UI for the participant
	}
})
```

1. Check that the local participant has permission to mute other participants' audio.

```swift
let canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if !canMuteAudio {
	// Disable the control in your UI.
}
```

2. Call `disableAudio()` on the target participant. If the local participant does not have the required permission, `disableAudio()` returns a `HostError`.

```swift
if let error = participant.disableAudio() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `audioEnabled` becomes `false`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// audioEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to mute other participants' audio.

```jsx
const canDisableParticipantAudio = meeting.self.permissions.canDisableParticipantAudio;
if (!canDisableParticipantAudio) {
	// Disable the control in your UI.
}
```

2. Call `disableAudio()` on the target participant.

```jsx
participant
	.disableAudio()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `audioEnabled` becomes `false`.

```jsx
meeting.participants.joined.on('audioUpdate', (participant) => {
	// participant.audioEnabled is false
	// Update UI for the participant
});
```

### Mute all participants

This affects all participants, including the local participant. To mute audio for all participants in the session:

1. Check that the local participant has permission to mute other participants' audio.

   ```ts
   const canMuteAudio =
   	meeting.self.permissions.canDisableParticipantAudio === true;
   if (!canMuteAudio) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAllAudio()`.

   If the local participant does not have the required permission, `disableAllAudio()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.disableAllAudio();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to mute other participants’ audio.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, each participant’s `audioEnabled` becomes `false`, and the SDK emits an `audioUpdate` event. The local participant also receives `audioUpdate` on `meeting.self`.

   Listen to remote participant updates on the `joined` map:

   ```ts
   meeting.participants.joined.on(
   	"audioUpdate",
   	(participant, { audioEnabled, audioTrack }) => {
   		// audioEnabled is false
   		// Update UI for the participant
   	},
   );
   ```

   Listen to the local participant update on `meeting.self`:

   ```ts
   meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
   	// audioEnabled is false
   	// Update UI for the local participant
   });
   ```



1. Check that the local participant has permission to mute other participants' audio.

   ```ts
   const canMuteAudio =
   	meeting.self.permissions.canDisableParticipantAudio === true;
   if (!canMuteAudio) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAllAudio()`.

   If the local participant does not have the required permission, `disableAllAudio()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.disableAllAudio();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to mute other participants’ audio.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, each participant’s `audioEnabled` becomes `false`, and the SDK emits an `audioUpdate` event. The local participant also receives `audioUpdate` on `meeting.self`.

   Listen to remote participant updates on the `joined` map:

   ```ts
   meeting.participants.joined.on(
   	"audioUpdate",
   	(participant, { audioEnabled, audioTrack }) => {
   		// audioEnabled is false
   		// Update UI for the participant
   	},
   );
   ```

   Listen to the local participant update on `meeting.self`:

   ```ts
   meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
   	// audioEnabled is false
   	// Update UI for the local participant
   });
   ```



1. Check that the local participant has permission to mute other participants' audio.

   ```ts
   const canMuteAudio =
   	meeting.self.permissions.canDisableParticipantAudio === true;
   if (!canMuteAudio) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAllAudio()`.

   If the local participant does not have the required permission, `disableAllAudio()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.disableAllAudio();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to mute other participants’ audio.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, each participant’s `audioEnabled` becomes `false`, and the SDK emits an `audioUpdate` event. The local participant also receives `audioUpdate` on `meeting.self`.

   Listen to remote participant updates on the `joined` map:

   ```ts
   meeting.participants.joined.on(
   	"audioUpdate",
   	(participant, { audioEnabled, audioTrack }) => {
   		// audioEnabled is false
   		// Update UI for the participant
   	},
   );
   ```

   Listen to the local participant update on `meeting.self`:

   ```ts
   meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
   	// audioEnabled is false
   	// Update UI for the local participant
   });
   ```



1. Check that the local participant has permission to mute other participants' audio.

```kotlin
val canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if (!canMuteAudio) {
	// Disable the control in your UI.
}
```

2. Call `disableAllAudio()` on the participants object. If the local participant does not have the required permission, `disableAllAudio()` returns a `HostError`.

```kotlin
val error = meeting.participants.disableAllAudio()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, each participant's `audioEnabled` becomes `false`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// audioEnabled is false
		// Update UI for the participant
	}
})
```

1. Check that the local participant has permission to mute other participants' audio.

```swift
let canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if !canMuteAudio {
	// Disable the control in your UI.
}
```

2. Call `disableAllAudio()` on the participants object. If the local participant does not have the required permission, `disableAllAudio()` returns a `HostError`.

```swift
if let error = meeting.participants.disableAllAudio() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, each participant's `audioEnabled` becomes `false`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// audioEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to mute other participants' audio.

```jsx
const canDisableParticipantAudio = meeting.self.permissions.canDisableParticipantAudio;
if (!canDisableParticipantAudio) {
	// Disable the control in your UI.
}
```

2. Call `disableAllAudio()` on the participants object.

```jsx
meeting.participants
	.disableAllAudio(true)
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
```

3. Handle the result by listening for updates. After the call succeeds, each participant's `audioEnabled` becomes `false`.

```jsx
meeting.participants.joined.on('audioUpdate', (participant) => {
	// participant.audioEnabled is false
	// Update UI for the participant
});
```

## Disable video

Disable video of participants when you need to moderate a session, enforce privacy, or prevent unwanted video during a classroom or webinar. This action requires the **Mute Video** (`disable_participant_video`) host control permission enabled in the local participant's preset.

### Disable video for a participant

To disable a specific participant's video:

1. Check that the local participant has permission to disable other participants' video.

   ```ts
   const canDisableVideo =
   	meeting.self.permissions.canDisableParticipantVideo === true;
   if (!canDisableVideo) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableVideo()` on the target participant.

   If the local participant does not have the required permission, `disableVideo()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.disableVideo();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to disable other participants’ video.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, the target participant's `videoEnabled` becomes `false`, and the SDK emits a `videoUpdate` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
   	// videoEnabled is false
   	// Update UI for the participant
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on(
   	"videoUpdate",
   	(participant, { videoEnabled, videoTrack }) => {
   		// videoEnabled is false
   		// Update UI for the participant
   	},
   );
   ```



1. Check that the local participant has permission to disable other participants' video.

   ```ts
   const canDisableVideo =
   	meeting.self.permissions.canDisableParticipantVideo === true;
   if (!canDisableVideo) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableVideo()` on the target participant.

   If the local participant does not have the required permission, `disableVideo()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.disableVideo();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to disable other participants’ video.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, the target participant's `videoEnabled` becomes `false`, and the SDK emits a `videoUpdate` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
   	// videoEnabled is false
   	// Update UI for the participant
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on(
   	"videoUpdate",
   	(participant, { videoEnabled, videoTrack }) => {
   		// videoEnabled is false
   		// Update UI for the participant
   	},
   );
   ```



1. Check that the local participant has permission to disable other participants' video.

   ```ts
   const canDisableVideo =
   	meeting.self.permissions.canDisableParticipantVideo === true;
   if (!canDisableVideo) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableVideo()` on the target participant.

   If the local participant does not have the required permission, `disableVideo()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.disableVideo();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to disable other participants’ video.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, the target participant's `videoEnabled` becomes `false`, and the SDK emits a `videoUpdate` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
   	// videoEnabled is false
   	// Update UI for the participant
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on(
   	"videoUpdate",
   	(participant, { videoEnabled, videoTrack }) => {
   		// videoEnabled is false
   		// Update UI for the participant
   	},
   );
   ```



1. Check that the local participant has permission to disable other participants' video.

```kotlin
val canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if (!canMuteVideo) {
	// Disable the control in your UI.
}
```

2. Call `disableVideo()` on the target participant. If the local participant does not have the required permission, `disableVideo()` returns a `HostError`.

```kotlin
val error = participant.disableVideo()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `videoEnabled` becomes `false`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// videoEnabled is false
		// Update UI for the participant
	}
})
```

1. Check that the local participant has permission to disable other participants' video.

```swift
let canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if !canMuteVideo {
	// Disable the control in your UI.
}
```

2. Call `disableVideo()` on the target participant. If the local participant does not have the required permission, `disableVideo()` returns a `HostError`.

```swift
if let error = participant.disableVideo() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `videoEnabled` becomes `false`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// videoEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to disable other participants' video.

```jsx
const canDisableParticipantVideo = meeting.self.permissions.canDisableParticipantVideo;
if (!canDisableParticipantVideo) {
	// Disable the control in your UI.
}
```

2. Call `disableVideo()` on the target participant.

```jsx
participant
	.disableVideo()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `videoEnabled` becomes `false`.

```jsx
meeting.participants.joined.on('videoUpdate', (participant) => {
	// participant.videoEnabled is false
	// Update UI for the participant
});
```

### Disable video for all participants

This affects all participants, including the local participant. To disable video for all participants in the session:

1. Check that the local participant has permission to disable other participants' video.

   ```ts
   const canDisableVideo =
   	meeting.self.permissions.canDisableParticipantVideo === true;
   if (!canDisableVideo) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAllVideo()`.

   If the local participant does not have the required permission, `disableAllVideo()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.disableAllVideo();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to disable other participants’ video.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, each participant’s `videoEnabled` becomes `false`, and the SDK emits a `videoUpdate` event. The local participant also receives `videoUpdate` on `meeting.self`.

   Listen to remote participant updates on the `joined` map:

   ```ts
   meeting.participants.joined.on(
   	"videoUpdate",
   	(participant, { videoEnabled, videoTrack }) => {
   		// videoEnabled is false
   		// Update UI for the participant
   	},
   );
   ```

   Listen to local participant update on `meeting.self`:

   ```ts
   meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
   	// videoEnabled is false
   	// Update UI for the local participant
   });
   ```



1. Check that the local participant has permission to disable other participants' video.

   ```ts
   const canDisableVideo =
   	meeting.self.permissions.canDisableParticipantVideo === true;
   if (!canDisableVideo) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAllVideo()`.

   If the local participant does not have the required permission, `disableAllVideo()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.disableAllVideo();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to disable other participants’ video.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, each participant’s `videoEnabled` becomes `false`, and the SDK emits a `videoUpdate` event. The local participant also receives `videoUpdate` on `meeting.self`.

   Listen to remote participant updates on the `joined` map:

   ```ts
   meeting.participants.joined.on(
   	"videoUpdate",
   	(participant, { videoEnabled, videoTrack }) => {
   		// videoEnabled is false
   		// Update UI for the participant
   	},
   );
   ```

   Listen to local participant update on `meeting.self`:

   ```ts
   meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
   	// videoEnabled is false
   	// Update UI for the local participant
   });
   ```



1. Check that the local participant has permission to disable other participants' video.

   ```ts
   const canDisableVideo =
   	meeting.self.permissions.canDisableParticipantVideo === true;
   if (!canDisableVideo) {
   	// Disable the control in your UI.
   }
   ```


2. Call `disableAllVideo()`.

   If the local participant does not have the required permission, `disableAllVideo()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.disableAllVideo();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to disable other participants’ video.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, each participant’s `videoEnabled` becomes `false`, and the SDK emits a `videoUpdate` event. The local participant also receives `videoUpdate` on `meeting.self`.

   Listen to remote participant updates on the `joined` map:

   ```ts
   meeting.participants.joined.on(
   	"videoUpdate",
   	(participant, { videoEnabled, videoTrack }) => {
   		// videoEnabled is false
   		// Update UI for the participant
   	},
   );
   ```

   Listen to local participant update on `meeting.self`:

   ```ts
   meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
   	// videoEnabled is false
   	// Update UI for the local participant
   });
   ```



1. Check that the local participant has permission to disable other participants' video.

```kotlin
val canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if (!canMuteVideo) {
	// Disable the control in your UI.
}
```

2. Call `disableAllVideo()` on the participants object. If the local participant does not have the required permission, `disableAllVideo()` returns a `HostError`.

```kotlin
val error = meeting.participants.disableAllVideo()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, each participant's `videoEnabled` becomes `false`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// videoEnabled is false
		// Update UI for the participant
	}
})
```

1. Check that the local participant has permission to disable other participants' video.

```swift
let canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if !canMuteVideo {
	// Disable the control in your UI.
}
```

2. Call `disableAllVideo()` on the participants object. If the local participant does not have the required permission, `disableAllVideo()` returns a `HostError`.

```swift
if let error = meeting.participants.disableAllVideo() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, each participant's `videoEnabled` becomes `false`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// videoEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to disable other participants' video.

```jsx
const canDisableParticipantVideo = meeting.self.permissions.canDisableParticipantVideo;
if (!canDisableParticipantVideo) {
	// Disable the control in your UI.
}
```

2. Call `disableAllVideo()` on the participants object.

```jsx
meeting.participants
	.disableAllVideo(true)
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
```

3. Handle the result by listening for updates. After the call succeeds, each participant's `videoEnabled` becomes `false`.

```jsx
meeting.participants.joined.on('videoUpdate', (participant) => {
	// participant.videoEnabled is false
	// Update UI for the participant
});
```

## Pin participants

Pin a participant to highlight them, such as a webinar presenter or classroom teacher. This is a session-wide action. All participants will see the pinned participant as the focus. This action requires the **Pin Participant** (`pin_participant`) host control permission enabled in the local participant's preset.

Note

Only one participant can be pinned at a time. Pinning a new participant automatically unpins the previous one.

### Pin a participant

To pin a participant in a session:

1. Check that the local participant has permission to pin participants.

   ```ts
   const canPinParticipant = meeting.self.permissions.pinParticipant === true;
   if (!canPinParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `pin()` on the target participant.

   If the local participant does not have the required permission, `pin()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.pin();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to pin participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The target participant's `isPinned` becomes true.
   - The participant is added to `meeting.participants.pinned`.
   - The SDK emits a `pinned` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("pinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is true
   	// Update your UI.
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on("pinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is true
   	// Update your UI.
   });
   ```

   If there was an existing pinned participant before, then the SDK emits an `unpinned` event for that participant.
4. On the target pinned participant's side, `meeting.self.isPinned` becomes `true` and `meeting.self` emits `pinned`:

   ```ts
   meeting.self.on("pinned", (selfParticipant) => {
   	// Update the local UI to indicate the participant is pinned.
   });
   ```



1. Check that the local participant has permission to pin participants.

   ```ts
   const canPinParticipant = meeting.self.permissions.pinParticipant === true;
   if (!canPinParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `pin()` on the target participant.

   If the local participant does not have the required permission, `pin()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.pin();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to pin participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The target participant's `isPinned` becomes true.
   - The participant is added to `meeting.participants.pinned`.
   - The SDK emits a `pinned` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("pinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is true
   	// Update your UI.
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on("pinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is true
   	// Update your UI.
   });
   ```

   If there was an existing pinned participant before, then the SDK emits an `unpinned` event for that participant.
4. On the target pinned participant's side, `meeting.self.isPinned` becomes `true` and `meeting.self` emits `pinned`:

   ```ts
   meeting.self.on("pinned", (selfParticipant) => {
   	// Update the local UI to indicate the participant is pinned.
   });
   ```



1. Check that the local participant has permission to pin participants.

   ```ts
   const canPinParticipant = meeting.self.permissions.pinParticipant === true;
   if (!canPinParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `pin()` on the target participant.

   If the local participant does not have the required permission, `pin()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.pin();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to pin participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The target participant's `isPinned` becomes true.
   - The participant is added to `meeting.participants.pinned`.
   - The SDK emits a `pinned` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("pinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is true
   	// Update your UI.
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on("pinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is true
   	// Update your UI.
   });
   ```

   If there was an existing pinned participant before, then the SDK emits an `unpinned` event for that participant.
4. On the target pinned participant's side, `meeting.self.isPinned` becomes `true` and `meeting.self` emits `pinned`:

   ```ts
   meeting.self.on("pinned", (selfParticipant) => {
   	// Update the local UI to indicate the participant is pinned.
   });
   ```



1. Check that the local participant has permission to pin participants.

```kotlin
val canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if (!canPinParticipant) {
	// Disable the control in your UI.
}
```

2. Call `pin()` on the target participant. If the local participant does not have the required permission, `pin()` returns a `HostError`.

```kotlin
val error = participant.pin()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `isPinned` becomes `true` and the participant is available in `meeting.participants.pinned`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onParticipantPinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is true
		// Update your UI.
	}
})
```

1. Check that the local participant has permission to pin participants.

```swift
let canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if !canPinParticipant {
	// Disable the control in your UI.
}
```

2. Call `pin()` on the target participant. If the local participant does not have the required permission, `pin()` returns a `HostError`.

```swift
if let error = participant.pin() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `isPinned` becomes `true` and the participant is available in `meeting.participants.pinned`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onParticipantPinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is true
		// Update your UI.
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to pin participants.

```jsx
const canPinParticipant = meeting.self.permissions.pinParticipant;
if (!canPinParticipant) {
	// Disable the control in your UI.
}
```

2. Call `pin()` on the target participant.

```jsx
participant.pin();
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `isPinned` becomes `true` and the participant is available in `meeting.participants.pinned`.

```jsx
meeting.participants.pinned.on('participantPinned', (participant) => {
	// participant.isPinned is true
	// Update your UI.
});
```

### Unpin a participant

Unpin a participant when you need to undo the highlight and return the session to a standard grid or active speaker view. To unpin a pinned participant in a session:

1. Check that the local participant has permission to unpin participants.

   ```ts
   const canUnpinParticipant = meeting.self.permissions.pinParticipant === true;
   if (!canUnpinParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `unpin()` on the target participant.

   If the local participant does not have the required permission, `unpin()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.unpin();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to unpin participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The target participant's `isPinned` becomes `false`.
   - The participant is removed from `meeting.participants.pinned`.
   - The SDK emits an `unpinned` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("unpinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is false
   	// Update your UI.
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on("unpinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is false
   	// Update your UI.
   });
   ```


4. On the target unpinned participant's side, `meeting.self.isPinned` becomes `false` and `meeting.self` emits `unpinned`:

   ```ts
   meeting.self.on("unpinned", (selfParticipant) => {
   	// Update the local UI to indicate the participant is no longer pinned.
   });
   ```



1. Check that the local participant has permission to unpin participants.

   ```ts
   const canUnpinParticipant = meeting.self.permissions.pinParticipant === true;
   if (!canUnpinParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `unpin()` on the target participant.

   If the local participant does not have the required permission, `unpin()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.unpin();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to unpin participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The target participant's `isPinned` becomes `false`.
   - The participant is removed from `meeting.participants.pinned`.
   - The SDK emits an `unpinned` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("unpinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is false
   	// Update your UI.
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on("unpinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is false
   	// Update your UI.
   });
   ```


4. On the target unpinned participant's side, `meeting.self.isPinned` becomes `false` and `meeting.self` emits `unpinned`:

   ```ts
   meeting.self.on("unpinned", (selfParticipant) => {
   	// Update the local UI to indicate the participant is no longer pinned.
   });
   ```



1. Check that the local participant has permission to unpin participants.

   ```ts
   const canUnpinParticipant = meeting.self.permissions.pinParticipant === true;
   if (!canUnpinParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `unpin()` on the target participant.

   If the local participant does not have the required permission, `unpin()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.unpin();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to unpin participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The target participant's `isPinned` becomes `false`.
   - The participant is removed from `meeting.participants.pinned`.
   - The SDK emits an `unpinned` event.

   **Option A**: Listen on the participant object

   ```ts
   participant.on("unpinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is false
   	// Update your UI.
   });
   ```

   **Option B**: Listen on the `joined` map

   ```ts
   meeting.participants.joined.on("unpinned", (updatedParticipant) => {
   	// updatedParticipant.isPinned is false
   	// Update your UI.
   });
   ```


4. On the target unpinned participant's side, `meeting.self.isPinned` becomes `false` and `meeting.self` emits `unpinned`:

   ```ts
   meeting.self.on("unpinned", (selfParticipant) => {
   	// Update the local UI to indicate the participant is no longer pinned.
   });
   ```



1. Check that the local participant has permission to unpin participants.

```kotlin
val canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if (!canPinParticipant) {
	// Disable the control in your UI.
}
```

2. Call `unpin()` on the target participant. If the local participant does not have the required permission, `unpin()` returns a `HostError`.

```kotlin
val error = participant.unpin()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `isPinned` becomes `false`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onParticipantUnpinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is false
		// Update your UI.
	}
})
```

1. Check that the local participant has permission to unpin participants.

```swift
let canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if !canPinParticipant {
	// Disable the control in your UI.
}
```

2. Call `unpin()` on the target participant. If the local participant does not have the required permission, `unpin()` returns a `HostError`.

```swift
if let error = participant.unpin() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `isPinned` becomes `false`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onParticipantUnpinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is false
		// Update your UI.
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to unpin participants.

```jsx
const canPinParticipant = meeting.self.permissions.pinParticipant;
if (!canPinParticipant) {
	// Disable the control in your UI.
}
```

2. Call `unpin()` on the target participant.

```jsx
participant.unpin();
```

3. Handle the result by listening for updates. After the call succeeds, the target participant's `isPinned` becomes `false`.

```jsx
meeting.participants.pinned.on('unpinned', (participant) => {
	// participant.isPinned is false
	// Update your UI.
});
```

## Remove participants

Remove participants from the session when you need to moderate disruptive behavior or enforce session rules. This action requires the **Kick Participants** (`kick_participant`) host control permission enabled in the local participant's preset.

### Remove a participant

To remove a specific participant from the session:

1. Check that the local participant has permission to remove participants.

   ```ts
   const canKickParticipant = meeting.self.permissions.kickParticipant === true;
   if (!canKickParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `kick()` on the target participant.

   If the local participant does not have the required permission, `kick()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.kick();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to remove participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The kicked participant is removed from `meeting.participants.joined`.
   - The participant is removed from other participant maps they were in (for example, `meeting.participants.pinned`).
   - The SDK emits `participantLeft` on `meeting.participants.joined`.

   ```ts
   meeting.participants.joined.on("participantLeft", (participant) => {
   	// Remove the participant tile from the UI.
   });
   ```

   Other participants in the session also observe the participant leaving through `participantLeft`.
4. On the removed participant's side, the session disconnects and `meeting.self` emits `roomLeft` event with state set to `kicked`.

   ```ts
   meeting.self.on("roomLeft", ({ state }) => {
   	if (state === "kicked") {
   		// Show a message and navigate the user out of the meeting UI.
   	}
   });
   ```



1. Check that the local participant has permission to remove participants.

   ```ts
   const canKickParticipant = meeting.self.permissions.kickParticipant === true;
   if (!canKickParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `kick()` on the target participant.

   If the local participant does not have the required permission, `kick()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.kick();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to remove participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The kicked participant is removed from `meeting.participants.joined`.
   - The participant is removed from other participant maps they were in (for example, `meeting.participants.pinned`).
   - The SDK emits `participantLeft` on `meeting.participants.joined`.

   ```ts
   meeting.participants.joined.on("participantLeft", (participant) => {
   	// Remove the participant tile from the UI.
   });
   ```

   Other participants in the session also observe the participant leaving through `participantLeft`.
4. On the removed participant's side, the session disconnects and `meeting.self` emits `roomLeft` event with state set to `kicked`.

   ```ts
   meeting.self.on("roomLeft", ({ state }) => {
   	if (state === "kicked") {
   		// Show a message and navigate the user out of the meeting UI.
   	}
   });
   ```



1. Check that the local participant has permission to remove participants.

   ```ts
   const canKickParticipant = meeting.self.permissions.kickParticipant === true;
   if (!canKickParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `kick()` on the target participant.

   If the local participant does not have the required permission, `kick()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await participant.kick();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to remove participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds:
   - The kicked participant is removed from `meeting.participants.joined`.
   - The participant is removed from other participant maps they were in (for example, `meeting.participants.pinned`).
   - The SDK emits `participantLeft` on `meeting.participants.joined`.

   ```ts
   meeting.participants.joined.on("participantLeft", (participant) => {
   	// Remove the participant tile from the UI.
   });
   ```

   Other participants in the session also observe the participant leaving through `participantLeft`.
4. On the removed participant's side, the session disconnects and `meeting.self` emits `roomLeft` event with state set to `kicked`.

   ```ts
   meeting.self.on("roomLeft", ({ state }) => {
   	if (state === "kicked") {
   		// Show a message and navigate the user out of the meeting UI.
   	}
   });
   ```



1. Check that the local participant has permission to remove participants.

```kotlin
val canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if (!canKickParticipant) {
	// Disable the control in your UI.
}
```

2. Call `kick()` on the target participant. If the local participant does not have the required permission, `kick()` returns a `HostError`.

```kotlin
val error = participant.kick()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the kicked participant is removed from `meeting.participants.joined`.

```kotlin
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onParticipantLeave(participant: RtkRemoteParticipant) {
		// Remove the participant tile from the UI.
	}
})
```

1. Check that the local participant has permission to remove participants.

```swift
let canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if !canKickParticipant {
	// Disable the control in your UI.
}
```

2. Call `kick()` on the target participant. If the local participant does not have the required permission, `kick()` returns a `HostError`.

```swift
if let error = participant.kick() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, the kicked participant is removed from `meeting.participants.joined`.

```swift
extension MeetingViewModel: RtkParticipantsEventListener {
	func onParticipantLeave(participant: RtkRemoteParticipant) {
		// Remove the participant tile from the UI.
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
```

1. Check that the local participant has permission to remove participants.

```jsx
const canKickParticipant = meeting.self.permissions.kickParticipant;
if (!canKickParticipant) {
	// Disable the control in your UI.
}
```

2. Call `kick()` on the target participant.

```jsx
participant
	.kick()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
```

3. Handle the result by listening for updates. After the call succeeds, the kicked participant is removed from `meeting.participants.joined`.

```jsx
meeting.participants.joined.on('participantLeft', (participant) => {
	// Remove the participant tile from the UI.
});
```

### Remove all participants

This removes everyone from the session, including the local participant. This ends the session for everyone.

For a complete end-a-session flow, refer to [End a session](https://developers.cloudflare.com/realtime/realtimekit/core/end-a-session/).

To remove all participants from the session:

1. Check that the local participant has permission to remove participants.

   ```ts
   const canKickParticipant = meeting.self.permissions.kickParticipant === true;
   if (!canKickParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `kickAll()`.

   If the local participant does not have the required permission, `kickAll()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.kickAll();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to remove participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, all participants exit the session. On each client, `meeting.self` emits `roomLeft` with state set to `ended`.

   ```ts
   meeting.self.on("roomLeft", ({ state }) => {
   	if (state === "ended") {
   		// Show a message and navigate the user out of the meeting UI.
   	}
   });
   ```



1. Check that the local participant has permission to remove participants.

   ```ts
   const canKickParticipant = meeting.self.permissions.kickParticipant === true;
   if (!canKickParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `kickAll()`.

   If the local participant does not have the required permission, `kickAll()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.kickAll();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to remove participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, all participants exit the session. On each client, `meeting.self` emits `roomLeft` with state set to `ended`.

   ```ts
   meeting.self.on("roomLeft", ({ state }) => {
   	if (state === "ended") {
   		// Show a message and navigate the user out of the meeting UI.
   	}
   });
   ```



1. Check that the local participant has permission to remove participants.

   ```ts
   const canKickParticipant = meeting.self.permissions.kickParticipant === true;
   if (!canKickParticipant) {
   	// Disable the control in your UI.
   }
   ```


2. Call `kickAll()`.

   If the local participant does not have the required permission, `kickAll()` throws a `ClientError` with code `1201`.

   ```ts
   try {
   	await meeting.participants.kickAll();
   } catch (err: any) {
   	if (err?.code === 1201) {
   		// The local participant does not have permission to remove participants.
   		return;
   	}
   	throw err;
   }
   ```


3. Handle the result by listening for updates.

   After the call succeeds, all participants exit the session. On each client, `meeting.self` emits `roomLeft` with state set to `ended`.

   ```ts
   meeting.self.on("roomLeft", ({ state }) => {
   	if (state === "ended") {
   		// Show a message and navigate the user out of the meeting UI.
   	}
   });
   ```



1. Check that the local participant has permission to remove participants.

```kotlin
val canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if (!canKickParticipant) {
	// Disable the control in your UI.
}
```

2. Call `kickAll()` on the participants object. If the local participant does not have the required permission, `kickAll()` returns a `HostError`.

```kotlin
val error = meeting.participants.kickAll()
if (error != null) {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, all participants exit the session.

```kotlin
meeting.addMeetingRoomEventListener(object : RtkMeetingRoomEventListener {
	override fun onMeetingEnded() {
		// Show a message and navigate the user out of the meeting UI.
	}
})
```

1. Check that the local participant has permission to remove participants.

```swift
let canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if !canKickParticipant {
	// Disable the control in your UI.
}
```

2. Call `kickAll()` on the participants object. If the local participant does not have the required permission, `kickAll()` returns a `HostError`.

```swift
if let error = meeting.participants.kickAll() {
	// Handle error - permission denied.
}
```

3. Handle the result by listening for updates. After the call succeeds, all participants exit the session.

```swift
extension MeetingViewModel: RtkMeetingRoomEventListener {
	func onMeetingEnded() {
		// Show a message and navigate the user out of the meeting UI.
	}
}

// Register the listener
meeting.addMeetingRoomEventListener(meetingRoomEventListener: self)
```

1. Check that the local participant has permission to remove participants.

```jsx
const canKickParticipant = meeting.self.permissions.kickParticipant;
if (!canKickParticipant) {
	// Disable the control in your UI.
}
```

2. Call `kickAll()` on the participants object.

```jsx
meeting.participants
	.kickAll()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
```

3. Handle the result by listening for updates. After the call succeeds, all participants exit the session.

```jsx
meeting.self.on('roomLeft', ({ state }) => {
	if (state === 'kicked') {
		// Show a message and navigate the user out of the meeting UI.
	}
});
```

## Next steps

- Review how presets control permissions in [Preset](https://developers.cloudflare.com/realtime/realtimekit/concepts/preset/).
- Review error handling details in [Error Codes](https://developers.cloudflare.com/realtime/realtimekit/core/error-codes/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/realtime/realtimekit/core/manage-participants-in-a-session/#page","headline":"Manage Participants in a Session","description":"Use RealtimeKit host controls to mute, pin, or remove participants in a live session.","url":"https://developers.cloudflare.com/realtime/realtimekit/core/manage-participants-in-a-session/","inLanguage":"en","image":"https://developers.cloudflare.com/realtime/realtimekit/core/manage-participants-in-a-session/og.png?v=e51984af50731733","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
