Builds and signs LiveKit access tokens.
Tokens are built with an immutable, pipeline-friendly API and signed with HS256 using the API secret:
iex> {:ok, jwt} =
...> LiveKit.AccessToken.new(
...> api_key: "api-key",
...> api_secret: "api-secret",
...> identity: "user-123"
...> )
...> |> LiveKit.AccessToken.with_name("Alice")
...> |> LiveKit.AccessToken.with_metadata(~s({"role":"host"}))
...> |> LiveKit.AccessToken.with_video_grant(%LiveKit.Grants.Video{
...> room_join: true,
...> room: "support-room"
...> })
...> |> LiveKit.AccessToken.to_jwt()
iex> is_binary(jwt)
trueClaims
The signed payload contains the registered claims iss (the API key), sub
(the identity, when set), iat, nbf and exp, alongside the LiveKit
claims produced by LiveKit.Grants.to_claims/1. The API secret is only ever
used as the signing key and never appears in the payload.
Time
The default TTL is 21600 seconds (6 hours), matching the Go and JavaScript SDKs. TTLs must be positive. Time is read through an injectable clock so tests can be deterministic:
LiveKit.AccessToken.new(
api_key: "k",
api_secret: "s",
clock: fn -> 1_700_000_000 end
)
Summary
Functions
The default token lifetime in seconds.
Starts building a token.
Builds the full claim map that would be signed, including registered claims.
Signs the token and returns the encoded JWT.
Same as to_jwt/1 but raises LiveKit.Error on failure.
Sets the agent grant.
Sets the participant attributes.
Sets the participant identity, encoded as the sub claim.
Sets the participant metadata string.
Sets the participant display name.
Sets the sha256 claim used by LiveKit webhook tokens.
Sets the sip grant.
Sets the token lifetime in seconds.
Sets the video grant.
Types
Functions
@spec default_ttl() :: pos_integer()
The default token lifetime in seconds.
Examples
iex> LiveKit.AccessToken.default_ttl()
21_600
Starts building a token.
Options
:api_key- LiveKit API key, used as theissclaim.:api_secret- LiveKit API secret, used as the HS256 signing key.:identity- participant identity, encoded assub.:name- participant display name.:metadata- participant metadata string.:attributes- map of string key/value participant attributes.:ttl- lifetime in seconds. Defaults to21_600.:clock- zero-arity function returning the current Unix time in seconds. Defaults toSystem.system_time(:second).
Credentials are validated when the token is signed, not here, so building is never fallible.
Examples
iex> token = LiveKit.AccessToken.new(api_key: "k", api_secret: "s", identity: "u1")
iex> {token.identity, token.ttl}
{"u1", 21_600}
@spec to_claims(t()) :: {:ok, map()} | {:error, LiveKit.Error.t()}
Builds the full claim map that would be signed, including registered claims.
Examples
iex> {:ok, claims} =
...> LiveKit.AccessToken.new(api_key: "k", api_secret: "s", identity: "u1", clock: fn -> 1_700_000_000 end)
...> |> LiveKit.AccessToken.with_video_grant(%LiveKit.Grants.Video{room_list: true})
...> |> LiveKit.AccessToken.to_claims()
iex> {claims["iss"], claims["sub"], claims["exp"] - claims["iat"]}
{"k", "u1", 21_600}
@spec to_jwt(t()) :: {:ok, String.t()} | {:error, LiveKit.Error.t()}
Signs the token and returns the encoded JWT.
Examples
iex> {:ok, jwt} =
...> LiveKit.AccessToken.new(api_key: "k", api_secret: "s")
...> |> LiveKit.AccessToken.with_video_grant(%LiveKit.Grants.Video{room_list: true})
...> |> LiveKit.AccessToken.to_jwt()
iex> length(String.split(jwt, "."))
3
iex> {:error, error} = LiveKit.AccessToken.new(api_key: "k", api_secret: "s") |> LiveKit.AccessToken.with_ttl(0) |> LiveKit.AccessToken.to_jwt()
iex> error.type
:validation
Same as to_jwt/1 but raises LiveKit.Error on failure.
Examples
iex> jwt =
...> LiveKit.AccessToken.new(api_key: "k", api_secret: "s")
...> |> LiveKit.AccessToken.with_video_grant(%LiveKit.Grants.Video{room_list: true})
...> |> LiveKit.AccessToken.to_jwt!()
iex> is_binary(jwt)
true
@spec with_agent_grant(t(), LiveKit.Grants.Agent.t()) :: t()
Sets the agent grant.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_agent_grant(%LiveKit.Grants.Agent{admin: true})
iex> token.claims.agent.admin
true
Sets the participant attributes.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_attributes(%{"tier" => "pro"})
iex> token.claims.attributes
%{"tier" => "pro"}
Sets the participant identity, encoded as the sub claim.
Examples
iex> LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_identity("user-1") |> Map.fetch!(:identity)
"user-1"
Sets the participant metadata string.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_metadata(~s({"role":"host"}))
iex> token.claims.metadata
~s({"role":"host"})
Sets the participant display name.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_name("Alice")
iex> token.claims.name
"Alice"
Sets the sha256 claim used by LiveKit webhook tokens.
The value is the Base64-encoded SHA-256 digest of the raw webhook body.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_sha256("abc=")
iex> token.claims.sha256
"abc="
@spec with_sip_grant(t(), LiveKit.Grants.SIP.t()) :: t()
Sets the sip grant.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_sip_grant(%LiveKit.Grants.SIP{admin: true})
iex> token.claims.sip.admin
true
Sets the token lifetime in seconds.
Invalid values are kept as-is and reported by to_jwt/1, so pipelines stay
free of tuple handling.
Examples
iex> LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_ttl(60) |> Map.fetch!(:ttl)
60
@spec with_video_grant(t(), LiveKit.Grants.Video.t()) :: t()
Sets the video grant.
Examples
iex> token = LiveKit.AccessToken.new() |> LiveKit.AccessToken.with_video_grant(%LiveKit.Grants.Video{room_list: true})
iex> token.claims.video.room_list
true