The token server is for development and testing only. It's not suitable for production, since any frontend app can request a token with any permissions and no restrictions.
Overview
LiveKit Cloud's development token server generates tokens for you with no backend code required. When you're ready for production, migrate to endpoint token generation.
LiveKit Sandbox is deprecated, but the token server remains available as a standalone project setting. Some SDK APIs still refer to Sandbox and related terms because the token server was originally part of Sandbox.
Enable the token server
Open your project's Settings page in LiveKit Cloud.
Find the Development token server toggle and switch it on. LiveKit Cloud automatically creates a token server for your project.
- Copy the Token server ID displayed below the toggle. Use this value in your frontend code.
Use a token server TokenSource
Configure a token server TokenSource in your application with your sandbox ID:
The token server accepts agent_name in token requests, along with an optional deployment. When using Session APIs, you can provide the agent name and deployment at runtime, and they're automatically included in token requests. Leave the deployment empty to target the production deployment. See the Authentication overview for more information.
import { Room, TokenSource } from 'livekit-client';// Create the TokenSourceconst tokenSource = TokenSource.developmentTokenServer("<your development token server id>");// Fetch a token (cached and automatically refreshed as needed)// For agent applications, include agentName in the fetch optionsconst { serverUrl, participantToken } = await tokenSource.fetch({roomName: "room name to join",agentName: "my-agent-name", // Optional: for agent dispatch// deployment: "staging", // Optional; empty = production});// Use the generated token to connect to a roomconst room = new Room();room.connect(serverUrl, participantToken);
import { TokenSource } from 'livekit-client';import { useSession, SessionProvider } from '@livekit/components-react';// Create the TokenSourceconst tokenSource = TokenSource.developmentTokenServer("<your development token server id>");export const MyPage = () => {const session = useSession(tokenSource, {roomName: "room name to join",agentName: "my-agent-name" // Optional: for agent dispatch});// Start the session when the component mounts, and end the session when the component unmountsuseEffect(() => {session.start();return () => {session.end();};}, []);return (<SessionProvider session={session}><MyComponent /></SessionProvider>)}export const MyComponent = () => {// Access the session available via the context to build your app// ie, show a list of all camera tracks:const cameraTracks = useTracks([Track.Source.Camera], {onlySubscribed: true});return (<>{cameraTracks.map((trackReference) => {return (<VideoTrack {...trackReference} />)})}</>)}
import LiveKitComponents@mainstruct SessionApp: App {let session = Session.withAgent("my-agent", tokenSource: DevelopmentTokenSource(id: "<your development token server id>"))var body: some Scene {WindowGroup {ContentView().environmentObject(session).alert(session.error?.localizedDescription ?? "Error", isPresented: .constant(session.error != nil)) {Button(action: session.dismissError) { Text("OK") }}.alert(session.agent.error?.localizedDescription ?? "Error", isPresented: .constant(session.agent.error != nil)) {AsyncButton(action: session.end) { Text("OK") }}}}}struct ContentView: View {@EnvironmentObject var session: Sessionvar body: some View {if session.isConnected {AsyncButton(action: session.end) {Text("Disconnect")}Text(String(describing: session.agent.agentState))} else {AsyncButton(action: session.start) {Text("Connect")}}}}
val tokenSource = remember {TokenSource.fromDevelopmentTokenServer("<your development token server id>").cached()}val session = rememberSession(tokenSource = tokenSource,options = SessionOptions(tokenRequestOptions = TokenRequestOptions(agentName = "my-agent-name") // Optional: for agent dispatch))Column {SessionScope(session = session) { session ->val coroutineScope = rememberCoroutineScope()var shouldConnect by remember { mutableStateOf(false) }LaunchedEffect(shouldConnect) {if (shouldConnect) {val result = session.start()// Handle if the session fails to connect.if (result.isFailure) {Toast.makeText(context, "Error connecting to the session.", Toast.LENGTH_SHORT).show()shouldConnect = false}} else {session.end()}}Button(onClick = { shouldConnect = !shouldConnect }) {Text(if (shouldConnect) {"Disconnect"} else {"Connect"})}}}
import 'package:livekit_client/livekit_client.dart' as sdk;final tokenSource = sdk.DevelopmentTokenSource(sandboxId: "<your development token server id>");final session = sdk.Session.withAgent("my-agent-name", tokenSource: tokenSource);/* ... */await session.start();// Use session to further build out your application.
import { TokenSource } from 'livekit-client';import { useSession, SessionProvider } from '@livekit/components-react';// Create the TokenSourceconst tokenSource = TokenSource.developmentTokenServer("<your development token server id>");export const MyPage = () => {const session = useSession(tokenSource, {roomName: "room name to join",agentName: "my-agent-name" // Optional: for agent dispatch});// Start the session when the component mounts, and end the session when the component unmountsuseEffect(() => {session.start();return () => {session.end();};}, []);return (<SessionProvider session={session}>{/* render the rest of your application here */}</SessionProvider>)}
let token_server_id = "<your development token server id>".to_string();let options = TokenSourceFetchOptions::new().with_agent_name("my-agent-name");let development_token_server =livekit_token_source::development_token_server(token_server_id.clone());let response = match development_token_server.fetch(&options).await {Ok(response) => response,Err(error) => {eprintln!("development token server fetch failed: {error}");return;}};let room_options = RoomOptions::default();let (room, mut room_events) =match Room::connect(&response.server_url, &response.participant_token, room_options).await{Ok(connection) => connection,Err(error) => {eprintln!("failed to connect to room: {error}");return;}};println!("connected to room: {}", room.name());
auto token_source = livekit::DevelopmentTokenSource::create("<your development token server id>");livekit::TokenRequestOptions request_options;request_options.agent_name = "my-agent-name";const auto credentials = token_source->fetch(request_options).get();if (!credentials) {std::cerr << "Failed to fetch credentials: " << credentials.error().message << "\n";return false;}livekit::Room room;if (!room.connect(credentials.value().server_url, credentials.value().participant_token, livekit::RoomOptions())) {std::cerr << "Failed to connect to room\n";return false;}std::cout << "Connected to room: " << room.roomInfo().name << " (development token source)\n";
IEnumerator ConnectToRoom(Room room){var tokenSource = TokenSource.DevelopmentTokenServer("<your development token server id>");var fetch = tokenSource.FetchConnectionDetails(new TokenSourceFetchOptions());yield return fetch;var details = fetch.Result;yield return room.Connect(details.ServerUrl, details.ParticipantToken, new RoomOptions());}