Join a Room from a Client
Learn how to install a VideoSDK client SDK, authenticate with an access token, join a room, respond to participant and media events, and handle leaving or reconnecting.
If you want to understand how roomId and access tokens work before implementing the client flow, see How a client connects to VideoSDK.
Install the SDK
Choose the SDK for your platform.
- React
- JavaScript
- React Native
- Flutter
- Android
- iOS
npm install @videosdk.live/react-sdk
For the complete setup, see the React quick start.
npm install @videosdk.live/js-sdk
You can also load the SDK from the CDN:
<script src="https://sdk.videosdk.live/js-sdk/1.1.1/videosdk.js"></script>
For the complete setup, see the JavaScript quick start.
npm install @videosdk.live/react-native-sdk @videosdk.live/react-native-incallmanager react-native-safe-area-context
Register the SDK's native service before your application renders:
import { register } from "@videosdk.live/react-native-sdk";
register();
For the complete setup, see the React Native quick start.
flutter pub add videosdk
For the complete setup, see the Flutter quick start.
Add the SDK dependency:
dependencies {
implementation 'live.videosdk:rtc-android-sdk:2.2.0'
}
Add the required permissions:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
For the complete setup, see the Android quick start.
Add the SDK to your Podfile:
pod 'VideoSDKRTC', :git => 'https://github.com/videosdk-live/videosdk-rtc-ios-sdk.git'
Add camera and microphone permission descriptions:
<key>NSCameraUsageDescription</key>
<string>Camera permission description</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone permission description</string>
For the complete setup, see the iOS quick start.
Server SDKs for Node.js, Go, and Rust run on your backend. The Python SDK is used for AI agents. See Server SDK and AI agents.
Generate an access token
Before a client can join a room, your backend must generate an access token.
The token determines which room and participant the client can connect as, and which permissions they receive.
For an explanation of token grants, see How a client connects to VideoSDK.
- REST
- Node.js
- Go
- Rust
There is no REST endpoint that generates a token. Sign the JWT on your server using your VideoSDK API key and secret.
const jwt = require("jsonwebtoken");
const { v4: uuid } = require("uuid");
const token = jwt.sign(
{
apikey: process.env.VIDEOSDK_API_KEY,
permissions: ["allow_join"],
roomId,
participantId: "user-123",
},
process.env.VIDEOSDK_SECRET,
{
algorithm: "HS256",
expiresIn: "2h",
jwtid: uuid(),
}
);
const token = client
.accessToken()
.setParticipant("user-123")
.grant(Grant.AllowJoin)
.forRoom(roomId)
.expiresIn("2h")
.toJwt();
b, _ := client.AccessToken()
token, _ := b.
SetParticipant("user-123").
Grant(videosdk.GrantAllowJoin).
ForRoom(roomID).
ExpiresIn(2 * time.Hour).
ToJWT()
let token = client
.access_token()?
.set_participant("user-123")
.grant(Grant::AllowJoin)
.for_room(&room_id)
.expires_in(Duration::from_secs(2 * 60 * 60))
.to_jwt()?;
For development, you can generate a temporary token from the VideoSDK dashboard.
For complete token configuration, including payload fields, permissions, and alternative signing methods, see Authentication and tokens.
Join a room
To join, provide:
- The
roomId. - The access token generated by your backend.
- A display name.
- Whether the microphone starts enabled.
- Whether the camera starts enabled.
You can also provide your own participantId so it maps to a user in your application. If you omit it, VideoSDK generates one automatically.
- React
- JavaScript
- React Native
- Flutter
- Android
- iOS
import {
MeetingProvider,
useMeeting,
} from "@videosdk.live/react-sdk";
function App() {
return (
<MeetingProvider
config={{
meetingId: roomId,
name: "C.V. Raman",
micEnabled: true,
webcamEnabled: true,
}}
token={token}
>
<MeetingView />
</MeetingProvider>
);
}
function MeetingView() {
const {
join,
localParticipant,
participants,
} = useMeeting({
onMeetingJoined: () => {
console.log("joined");
},
});
return (
<button onClick={() => join()}>
Join
</button>
);
}
Set joinWithoutUserInteraction on MeetingProvider if you want the participant to join automatically instead of explicitly calling join().
After joining:
localParticipantrepresents the current participant.participantscontains the remote participants, keyed by participant ID.onParticipantJoinedandonParticipantLeftreport participant changes.onPresenterChangedreports screen-share changes.useParticipant(participantId)exposesonStreamEnabledandonStreamDisabled.
See Participant events, Media events, and Meeting events.
window.VideoSDK.config(token);
const meeting = window.VideoSDK.initMeeting({
meetingId: roomId,
name: "Thomas Edison",
micEnabled: true,
webcamEnabled: true,
});
meeting.on("meeting-joined", () => {
// meeting.localParticipant and meeting.participants are ready
});
await meeting.join();
join() resolves when the join request is accepted. Wait for meeting-joined before calling other meeting methods.
After joining:
meeting.localParticipantrepresents the current participant.meeting.participantscontains remote participants keyed by participant ID.participant-joinedandparticipant-leftreport participant changes.stream-enabledandstream-disabledreport media changes.presenter-changedreports screen-share changes.
See Participant events, Stream events, and Meeting events.
import {
MeetingProvider,
useMeeting,
} from "@videosdk.live/react-native-sdk";
function App() {
return (
<MeetingProvider
config={{
meetingId: roomId,
name: "Test User",
micEnabled: true,
webcamEnabled: true,
defaultCamera: "front",
}}
token={token}
>
<MeetingView />
</MeetingProvider>
);
}
function MeetingView() {
const {
join,
participants,
} = useMeeting({});
return (
<Button
title="Join"
onPress={() => join()}
/>
);
}
After joining:
localParticipantrepresents the current participant.participantscontains remote participants keyed by participant ID.onParticipantJoinedandonParticipantLeftreport participant changes.onPresenterChangedreports screen-share changes.useParticipant(participantId)exposesonStreamEnabledandonStreamDisabled.
See Participant events, Media events, and Meeting events.
import 'package:videosdk/videosdk.dart';
final Room room = VideoSDK.createRoom(
roomId: roomId,
token: token,
displayName: "John Doe",
micEnabled: true,
camEnabled: true,
defaultCameraIndex: kIsWeb ? 0 : 1,
);
room.on(Events.roomJoined, () {
// room.localParticipant and room.participants are ready
});
room.join();
After joining:
room.localParticipantrepresents the current participant.room.participantscontains remote participants keyed by participant ID.Events.participantJoinedandEvents.participantLeftreport participant changes.Events.streamEnabledandEvents.streamDisabledreport media changes.Events.presenterChangedreports screen-share changes.
See Participant events, Media events, and Room events.
Initialize VideoSDK once when the application starts, then configure and create a meeting for each room.
// once, in Application.onCreate()
VideoSDK.initialize(applicationContext)
// per meeting
VideoSDK.config(token)
val meeting = VideoSDK.initMeeting(
this,
roomId,
"John Doe",
micEnabled,
webcamEnabled,
null,
null,
false,
null,
null
)
meeting.addEventListener(
object : MeetingEventListener() {
override fun onMeetingJoined() {
// meeting.localParticipant and meeting.participants are ready
}
}
)
meeting.join()
After joining:
meeting.getLocalParticipant()represents the current participant.meeting.getParticipants()contains remote participants keyed by participant ID.MeetingEventListenerreceives participant and presenter events.ParticipantEventListenerreceives stream events.
See Participant events, Media events, and Meeting events.
import VideoSDKRTC
VideoSDK.config(token: token)
let meeting = VideoSDK.initMeeting(
meetingId: roomId,
participantName: "John Doe",
micEnabled: true,
webcamEnabled: true
)
meeting.addEventListener(self)
meeting.join()
Implement MeetingEventListener to know when the participant has joined:
extension MeetingViewController: MeetingEventListener {
func onMeetingJoined() {
// meeting.localParticipant and meeting.participants are ready
}
}
After joining:
meeting.localParticipantrepresents the current participant.meeting.participantscontains remote participants keyed by participant ID.MeetingEventListenerreports participant events.ParticipantEventListenerreports media stream events.
See Participant events, Media events, and Meeting events.
Respond to room changes
After joining, your application should listen for room events rather than repeatedly polling participant or media state.
The most commonly used events are:
| Event | Use it for |
|---|---|
| Participant joined | Add the participant to your UI. |
| Participant left | Remove the participant from your UI. |
| Stream enabled | Render newly published microphone, camera, or screen-share media. |
| Stream disabled | Remove or update the corresponding media element. |
| Presenter changed | Update the UI when screen sharing starts or stops. |
| Connection state changed | Show connecting, connected, or reconnecting state. |
| Error | Handle authentication, device, or SDK failures. |
See Participant management and Stream management for detailed participant and media handling.
Leave a room
Call leave() when the local participant wants to disconnect.
The local client receives onMeetingLeft, while the remaining participants receive onParticipantLeft.
Use end() instead when you want to end the active session for everyone in the room.
leave();
Different exit conditions include a reason code so your application can distinguish between a normal departure and a forced or network-related disconnect.
| Reason | Code | Meaning |
|---|---|---|
WEBSOCKET_DISCONNECTED | 1001 | The socket disconnected, typically because a network interruption could not be recovered. |
REMOVE_PEER | 1002 | A moderator or server removed the participant. |
REMOVE_PEER_VIEWER_MODE_CHANGED | 1003 | The participant was removed because the viewer mode changed. |
REMOVE_PEER_MEDIA_RELAY_STOP | 1004 | The participant was removed because a media relay stopped. |
SWITCH_ROOM | 1005 | The participant switched to a different room. |
Handle connection states
Use the SDK's connection-state events to keep your interface synchronized with the participant's connection to the room.
For React, onMeetingStateChanged reports the following states:
| State | What it means | Recommended UI |
|---|---|---|
CONNECTING | The SDK is attempting to join the room. | Show a connecting indicator. |
CONNECTED | Signalling is established and the required media channels are active. | Show the call interface. |
RECONNECTING | The network connection was interrupted or became unstable. The SDK is attempting to reconnect automatically. | Show a reconnecting message while keeping the existing call layout visible. |
DISCONNECTED | The room connection has closed because the participant left or reconnection failed. | Show the leave screen or a retry action. |
FAILED | The initial connection attempt failed. | Show an error with a retry option. |
const { meetingId } = useMeeting({
onMeetingStateChanged: ({ state }) => {
// "CONNECTING"
// "CONNECTED"
// "RECONNECTING"
// "DISCONNECTED"
// "FAILED"
},
});
Handle errors separately
Connection state and SDK errors represent different conditions and should be handled independently.
For example:
- A temporary Wi-Fi interruption may move the meeting to
RECONNECTING. - An invalid access token is reported through
onError. - Camera or microphone failures are also reported through
onError.
onError provides a code and message that you can use to determine the appropriate response.
See the error codes reference for the complete list.
Next steps
Room management
Create, retrieve, validate, list, and manage rooms and sessions from your server.
Participant management
Access participants, change modes, and moderate users from your client or server.
Server SDK
Manage rooms, tokens, participants, recording, telephony, and other server-side operations.

