Participant Management
Learn how to access participants in a VideoSDK room, manage participant modes, control remote participants, and perform participant operations from your server.
Each participant has a unique participantId along with information such as their display name, mode, and published media streams.
Access local and remote participants
When your client joins a room, VideoSDK creates a local participant representing the current user.
Everyone else connected to the room is represented as a remote participant. As remote participants publish audio, video, or screen-share streams, those streams become available through their participant objects.
- React
- JavaScript
- React Native
- Flutter
- Android
- iOS
const { localParticipant, participants } = useMeeting();
// participants is a Map<participantId, Participant>
[...participants.keys()].map((participantId) => (
<ParticipantView key={participantId} participantId={participantId} />
));
Use useParticipant(participantId) to access the properties, streams, and controls for a specific participant, including the local participant.
const localParticipant = meeting.localParticipant;
meeting.participants.forEach((participant) => {
participant.streams.forEach((stream) => {
// attach stream.track to a media element keyed by participant.id
});
});
Retrieve a specific remote participant using its participantId:
const participant = meeting.participants.get(participantId);
const { localParticipant, participants } = useMeeting();
[...participants.keys()].map((participantId) => (
<ParticipantView key={participantId} participantId={participantId} />
));
const ParticipantView = ({ participantId }) => {
const { displayName, webcamStream, webcamOn } = useParticipant(participantId);
return (
<RTCView
streamURL={new MediaStream([webcamStream?.track]).toURL()}
/>
);
};
Participant? localParticipant = room.localParticipant;
Map<String, Participant> participants = room.participants;
GridView.count(
crossAxisCount: 2,
children: [
ParticipantTile(
participant: localParticipant!,
isLocalParticipant: true,
),
...participants.values
.map((participant) => ParticipantTile(participant: participant))
.toList()
],
);
participants.add(meeting.localParticipant)
meeting.addEventListener(object : MeetingEventListener() {
override fun onParticipantJoined(participant: Participant) {
participants.add(participant)
}
})
// in onBindViewHolder
for ((_, stream) in participant.streams) {
if (stream.kind.equals("video", ignoreCase = true)) {
holder.participantView.addTrack(stream.track as VideoTrack)
}
}
let localParticipant = self.meeting?.localParticipant
let otherParticipants = self.meeting?.participants
extension MeetingViewController: MeetingEventListener {
func onParticipantJoined(_ participant: Participant) {
participants.append(participant)
participant.addEventListener(self)
}
}
On iOS, participants is an array. You can retrieve a participant by ID with:
meeting?.participants.first(where: { $0.id == participantId })
Manage participant modes
A participant's mode determines whether they can publish or receive realtime media.
The three participant modes are described in Rooms, Sessions, Participants, and Streams.
You can change the local participant's mode after they join the room. When the mode changes, connected clients receive an onParticipantModeChanged event.
For example, promoting a viewer to the stage in an interactive live stream typically changes their mode from RECV_ONLY or SIGNALLING_ONLY to SEND_AND_RECV.
- React
- JavaScript
- React Native
- Flutter
- Android
- iOS
const { changeMode } = useMeeting();
await changeMode(Constants.modes.SEND_AND_RECV);
await meeting.changeMode(Constants.modes.SEND_AND_RECV);
const { changeMode } = useMeeting();
await changeMode(Constants.modes.SEND_AND_RECV);
room.changeMode(Mode.SEND_AND_RECV);
meeting!!.changeMode("SEND_AND_RECV")
await meeting?.changeMode(.SEND_AND_RECV)
For an interactive live streaming example, see Manage roles.
Participant properties
Participant objects expose information about the user and the media they are publishing.
For example, React's useParticipant(participantId) hook provides the following commonly used properties:
| Property | Type | Description |
|---|---|---|
displayName | string | Display name provided when the participant joined. |
participant | Participant | Underlying participant object containing properties such as id, displayName, local, and the participant's streams map. |
isLocal | boolean | true when the participant represents the current client. |
mode | string | Current participant mode: SEND_AND_RECV, RECV_ONLY, or SIGNALLING_ONLY. |
metaData | object | Custom metadata passed when the participant joined, such as a profile image URL or application-specific role. |
webcamOn / micOn / screenShareOn | boolean | Indicates whether the corresponding media stream is currently being published. |
webcamStream / micStream / screenShareStream | Stream | Provides access to the participant's camera, microphone, and screen-share streams. See Stream management. |
isActiveSpeaker | boolean | true while the participant is detected as the active speaker. |
Equivalent participant information is available across the client SDKs using platform-specific naming and APIs.
See the useParticipant reference for the complete React API.
Moderate remote participants
Participants with moderation permissions can control certain actions for other participants in the room.
Moderation requires the allow_mod grant in the moderator's token. See How a client connects for more information about token permissions.
| Method | What it does | Event behavior |
|---|---|---|
enableMic() / enableWebcam() | Requests that the participant enable their microphone or camera. | The target receives onMicRequested or onWebcamRequested and can call accept() or reject(). |
disableMic() / disableWebcam() | Disables the participant's microphone or camera immediately. | Connected participants receive onStreamDisabled. |
remove() | Disconnects the participant from the room. | The removed participant receives onMeetingLeft with reason REMOVE_PEER; other participants receive onParticipantLeft. |
pin() / unpin() | Pins or unpins the participant's camera, screen share, or both using CAM, SHARE, or SHARE_AND_CAM. | Connected participants receive onPinStateChanged. |
- React
- JavaScript
- React Native
- Flutter
- Android
- iOS
const {
enableMic,
disableWebcam,
remove,
pin,
} = useParticipant(participantId);
await enableMic(); // asks the participant to unmute
await disableWebcam(); // turns their camera off now
await pin("CAM"); // pin their camera tile
await remove(); // remove them from the room
const participant = meeting.participants.get(participantId);
await participant.enableMic(); // asks the participant to unmute
await participant.disableWebcam(); // turns their camera off now
await participant.pin("CAM"); // pin their camera tile
await participant.remove(); // remove them from the room
const {
enableMic,
disableWebcam,
remove,
pin,
} = useParticipant(participantId);
await enableMic(); // asks the participant to unmute
await disableWebcam(); // turns their camera off now
await pin("CAM"); // pin their camera tile
await remove(); // remove them from the room
final participant = room.participants[participantId]!;
participant.unmuteMic(); // asks the participant to unmute
participant.disableCam(); // turns their camera off now
participant.pin(PinType.CAM); // pin their camera tile
participant.remove(); // remove them from the room
Flutter uses unmuteMic(), muteMic(), enableCam(), and disableCam() for microphone and camera controls. Media requests are exposed through Events.micRequested and Events.cameraRequested.
val participant = meeting!!.participants[participantId]!!
participant.enableMic() // asks the participant to unmute
participant.disableWebcam() // turns their camera off now
participant.pin("CAM") // pin their camera tile
participant.remove() // remove them from the room
let participant = meeting?.participants.first(
where: { $0.id == participantId }
)
participant?.enableMic() // asks the participant to unmute
participant?.disableWebcam() // turns their camera off now
participant?.pin(pinType: .CAM) // pin their camera tile
participant?.remove() // remove them from the room
For complete moderation flows, see Toggle remote participant media and Remove participant.
Manage participants from your server
You can also retrieve and remove participants from your backend using the VideoSDK Server SDK or REST API.
The Server SDK participants resource operates on the currently active session for a room. When using the Server SDK, you provide the roomId, and the SDK resolves the active session.
For REST API requests, participant endpoints operate on a sessionId. You can retrieve the current session for a room first with:
GET /v2/sessions?roomId=ROOM_ID
For Server SDK initialization, see Room management.
List active participants
List the participants currently connected to a room.
If the room does not have an active session, the request returns an empty page.
- REST
- Node.js
- Go
- Rust
curl "https://api.videosdk.live/v2/sessions/$SESSION_ID/participants/active?page=1&perPage=20" \
-H "Authorization: $VIDEOSDK_TOKEN"
# { "pageInfo": { ... }, "data": [ { "participantId": "...", "name": "..." } ] }
const participants = await client.participants.list(roomId);
for await (const p of participants) {
console.log(p.participantId, p.name);
}
for p, err := range client.Participants.ListAutoPaging(
ctx,
roomID,
videosdk.ListParams{},
) {
if err != nil {
return err
}
fmt.Println(p.ParticipantID, p.Name)
}
use futures_util::StreamExt;
let mut participants = Box::pin(
client
.participants()
.list_stream(room_id, videosdk::ListParams::default()),
);
while let Some(p) = participants.next().await {
let p = p?;
println!("{} {}", p.participant_id, p.name);
}
Get a participant
Retrieve a specific active participant by their participantId.
When using the Server SDK, the room must have an active session.
- REST
- Node.js
- Go
- Rust
curl "https://api.videosdk.live/v2/sessions/$SESSION_ID/participants/active" \
-H "Authorization: $VIDEOSDK_TOKEN"
# Filter `data[]` by participantId.
# There is no single-participant REST endpoint.
const participant = await client.participants.get(
roomId,
"participant-alice"
);
p, err := client.Participants.Get(
ctx,
roomID,
"participant-alice",
)
let participant = client
.participants()
.get(room_id, "participant-alice")
.await?;
Remove a participant
Remove an active participant from a room.
The participant is disconnected from the current session and receives onMeetingLeft with the reason REMOVE_PEER, matching the behavior of the client-side remove() moderation method.
- REST
- Node.js
- Go
- Rust
curl -X POST https://api.videosdk.live/v2/sessions/participants/remove \
-H "Authorization: $VIDEOSDK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "roomId": "'"$ROOM_ID"'", "participantId": "participant-alice" }'
# Add "sessionId" to the body to target a specific session.
await client.participants.remove(
roomId,
"participant-alice"
);
msg, err := client.Participants.Remove(
ctx,
roomID,
"participant-alice",
)
client
.participants()
.remove(room_id, "participant-alice")
.await?;
Server-side Participant object
The Server SDK returns a Participant object when you retrieve a participant or iterate through a participant list.
| Field | Type | Description |
|---|---|---|
participantId | string | Unique identifier for the participant. |
name | string | Participant's display name, when available. |
timelog | object[] | Join and leave intervals for the participant. Each entry contains start and end; end remains null while the participant is connected. |
For participants from previous sessions and participant-level quality statistics, see the Sessions reference.
Next steps
Participants reference
List, retrieve, and remove participants using the Server SDK.
Stream management
Publish and receive camera, microphone, and screen-share streams and control media quality.
Building AI agents
Understand how AI agents join rooms as participants, receive media, and respond.
How a client connects
Understand room IDs, access tokens, and the permissions that control participant actions.

