# Source: https://docs.livekit.io/home/server/generating-tokens.md

LiveKit docs › Server APIs › Token generation

---

# Generating tokens

> Generate tokens for your frontend

In order for frontend apps to connect to LiveKit rooms, they need a token generated by your backend server. In this guide, we'll walk through how to set up a server to generate tokens for your frontend.

## 1. Install LiveKit Server SDK

**Go**:

```shell
go get github.com/livekit/server-sdk-go/v2

```

---

**Node.js**:

```shell
# yarn:
yarn add livekit-server-sdk

# npm:
npm install livekit-server-sdk --save

```

---

**Ruby**:

```ruby
# Add to your Gemfile
gem 'livekit-server-sdk'

```

---

**Python**:

```shell
uv add livekit-api

```

---

**Rust**:

```toml
# Cargo.toml
[package]
name = "example_server"
version = "0.1.0"
edition = "2021"

[dependencies]
livekit-api = "0.2.0"
# Remaining deps are for the example server
warp = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }

```

---

**PHP**:

```shell
composer require agence104/livekit-server-sdk

```

## 2. Keys and Configuration

Create a new file at `development.env` and with your API Key and Secret:

```shell
export LIVEKIT_API_KEY=%{apiKey}%
export LIVEKIT_API_SECRET=%{apiSecret}%

```

## 3. Make an endpoint that returns a token

Create a server:

**Go**:

```go
// server.go
import (
	"net/http"
	"log"
	"time"
	"os"

	"github.com/livekit/protocol/auth"
)

func getJoinToken(room, identity string) string {
	at := auth.NewAccessToken(os.Getenv("LIVEKIT_API_KEY"), os.Getenv("LIVEKIT_API_SECRET"))
	grant := &auth.VideoGrant{
		RoomJoin: true,
		Room: room,
	}
	at.AddGrant(grant).
		SetIdentity(identity).
		SetValidFor(time.Hour)

	token, _ := at.ToJWT()
	return token
}

func main() {
	http.HandleFunc("/getToken", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(getJoinToken("my-room", "identity")))
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}

```

---

**Node.js**:

```js
// server.js
import express from 'express';
import { AccessToken } from 'livekit-server-sdk';

const createToken = async () => {
  // If this room doesn't exist, it'll be automatically created when the first
  // participant joins
  const roomName = 'quickstart-room';
  // Identifier to be used for participant.
  // It's available as LocalParticipant.identity with livekit-client SDK
  const participantName = 'quickstart-username';

  const at = new AccessToken(process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET, {
    identity: participantName,
    // Token to expire after 10 minutes
    ttl: '10m',
  });
  at.addGrant({ roomJoin: true, room: roomName });

  return await at.toJwt();
};

const app = express();
const port = 3000;

app.get('/getToken', async (req, res) => {
  res.send(await createToken());
});

app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

```

---

**Ruby**:

```ruby
# server.rb
require 'livekit'
require 'sinatra'

def createToken()
  token = LiveKit::AccessToken.new(api_key: ENV['LIVEKIT_API_KEY'], api_secret: ENV['LIVEKIT_API_SECRET'])
  token.identity = 'quickstart-identity'
  token.name = 'quickstart-name'
  token.add_grant(roomJoin: true, room: 'room-name')

  token.to_jwt
end

get '/getToken' do
  createToken
end

```

---

**Python**:

```python
# server.py
import os
from livekit import api
from flask import Flask

app = Flask(__name__)

@app.route('/getToken')
def getToken():
  token = api.AccessToken(os.getenv('LIVEKIT_API_KEY'), os.getenv('LIVEKIT_API_SECRET')) \
    .with_identity("identity") \
    .with_name("my name") \
    .with_grants(api.VideoGrants(
        room_join=True,
        room="my-room",
    ))
  return token.to_jwt()

```

---

**Rust**:

```rust
// src/main.rs

use livekit_api::access_token;
use warp::Filter;
use serde::{Serialize, Deserialize};
use std::env;

#[tokio::main]
async fn main() {
    // Define the route
    let create_token_route = warp::path("create-token")
        .map(|| {
            let token = create_token().unwrap();
            warp::reply::json(&TokenResponse { token })
        });

    // Start the server
    warp::serve(create_token_route).run(([127, 0, 0, 1], 3030)).await;
}

// Token creation function
fn create_token() -> Result<String, access_token::AccessTokenError> {
   let api_key = env::var("LIVEKIT_API_KEY").expect("LIVEKIT_API_KEY is not set");
   let api_secret = env::var("LIVEKIT_API_SECRET").expect("LIVEKIT_API_SECRET is not set");

   let token = access_token::AccessToken::with_api_key(&api_key, &api_secret)
      .with_identity("identity")
      .with_name("name")
      .with_grants(access_token::VideoGrants {
         room_join: true,
         room: "my-room".to_string(),
         ..Default::default()
      })
      .to_jwt();
   return token
}

// Response structure
#[derive(Serialize, Deserialize)]
struct TokenResponse {
    token: String,
}

```

---

**PHP**:

```php
// If this room doesn't exist, it'll be automatically created when the first
// participant joins.
$roomName = 'name-of-room';
// The identifier to be used for participant.
$participantName = 'user-name';

// Define the token options.
$tokenOptions = (new AccessTokenOptions())
  ->setIdentity($participantName);

// Define the video grants.
$videoGrant = (new VideoGrant())
  ->setRoomJoin()
  ->setRoomName($roomName);

// Initialize and fetch the JWT Token.
$token = (new AccessToken(getenv('LIVEKIT_API_KEY'), getenv('LIVEKIT_API_SECRET')))
  ->init($tokenOptions)
  ->setGrant($videoGrant)
  ->toJwt();

```

Load the environment variables and run the server:

**Go**:

```shell
$ source development.env
$ go run server.go

```

---

**Node.js**:

```shell
$ source development.env
$ node server.js

```

---

**Ruby**:

```shell
$ source development.env
$ ruby server.rb

```

---

**Python**:

```shell
$ source development.env
$ python server.py

```

---

**Rust**:

```shell
$ source development.env
$ cargo r src/main.rs

```

---

**PHP**:

```shell
$ source development.env
$ php server.php

```

> ℹ️ **Note**
> 
> See the [Authentication](https://docs.livekit.io/home/get-started/authentication.md) page for more information on how to generate tokens with custom permissions.

## 4. Create a frontend app to connect

Create a frontend app that fetches a token from the server we just made, then uses it to connect to a LiveKit room:

- [iOS](https://docs.livekit.io/home/quickstarts/swift.md)
- [Android](https://docs.livekit.io/home/quickstarts/android.md)
- [Flutter](https://docs.livekit.io/home/quickstarts/flutter.md)
- [React Native](https://docs.livekit.io/home/quickstarts/react-native.md)
- [React](https://docs.livekit.io/home/quickstarts/react.md)
- [Unity (web)](https://docs.livekit.io/home/quickstarts/unity-web.md)
- [JavaScript](https://docs.livekit.io/home/quickstarts/javascript.md)

---

This document was rendered at 2025-11-18T23:54:55.801Z.
For the latest version of this document, see [https://docs.livekit.io/home/server/generating-tokens.md](https://docs.livekit.io/home/server/generating-tokens.md).

To explore all LiveKit documentation, see [llms.txt](https://docs.livekit.io/llms.txt).