Skip to main content

livekit_api/services/
livekit_api.rs

1// Copyright 2026 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::time::Duration;
16
17use super::agent_dispatch::AgentDispatchClient;
18use super::connector::ConnectorClient;
19use super::egress::EgressClient;
20use super::ingress::IngressClient;
21use super::room::RoomClient;
22use super::sip::SIPClient;
23use super::{ServiceBase, ServiceResult};
24use crate::get_env_keys;
25use crate::http_client;
26
27/// A single entry point to every LiveKit server API, exposing each service
28/// through an accessor (`room()`, `egress()`, `ingress()`, `sip()`,
29/// `agent_dispatch()`, `connector()`).
30///
31/// Construct it with an API key and secret ([`with_api_key`](Self::with_api_key),
32/// or [`new`](Self::new) to read them from the environment) for backend use, or
33/// with a pre-signed token ([`with_token`](Self::with_token)) for client-side use
34/// where the API secret must not be exposed.
35#[derive(Debug)]
36pub struct LiveKitApi {
37    room: RoomClient,
38    egress: EgressClient,
39    ingress: IngressClient,
40    sip: SIPClient,
41    agent_dispatch: AgentDispatchClient,
42    connector: ConnectorClient,
43}
44
45impl LiveKitApi {
46    pub fn with_api_key(host: &str, api_key: &str, api_secret: &str) -> Self {
47        // One HTTP client shared across every service, so they reuse a single
48        // connection pool instead of each opening its own.
49        let http = http_client::Client::new();
50        let base = || ServiceBase::with_api_key(api_key, api_secret);
51        Self {
52            room: RoomClient::build(host, base(), http.clone()),
53            egress: EgressClient::build(host, base(), http.clone()),
54            ingress: IngressClient::build(host, base(), http.clone()),
55            sip: SIPClient::build(host, base(), http.clone()),
56            agent_dispatch: AgentDispatchClient::build(host, base(), http.clone()),
57            connector: ConnectorClient::build(host, base(), http),
58        }
59    }
60
61    /// Reads the key and secret from the `LIVEKIT_API_KEY` and
62    /// `LIVEKIT_API_SECRET` environment variables.
63    pub fn new(host: &str) -> ServiceResult<Self> {
64        let (api_key, api_secret) = get_env_keys()?;
65        Ok(Self::with_api_key(host, &api_key, &api_secret))
66    }
67
68    /// Authenticates with a pre-signed token, sent verbatim on every request.
69    /// The token's grants must cover the calls made through this client.
70    pub fn with_token(host: &str, token: &str) -> Self {
71        // One HTTP client shared across every service (see `with_api_key`).
72        let http = http_client::Client::new();
73        let base = || ServiceBase::with_token(token);
74        Self {
75            room: RoomClient::build(host, base(), http.clone()),
76            egress: EgressClient::build(host, base(), http.clone()),
77            ingress: IngressClient::build(host, base(), http.clone()),
78            sip: SIPClient::build(host, base(), http.clone()),
79            agent_dispatch: AgentDispatchClient::build(host, base(), http.clone()),
80            connector: ConnectorClient::build(host, base(), http),
81        }
82    }
83
84    /// Enables or disables region failover on every service (enabled by
85    /// default). Failover only engages for LiveKit Cloud hosts.
86    pub fn with_failover(mut self, enabled: bool) -> Self {
87        self.room = self.room.with_failover(enabled);
88        self.egress = self.egress.with_failover(enabled);
89        self.ingress = self.ingress.with_failover(enabled);
90        self.sip = self.sip.with_failover(enabled);
91        self.agent_dispatch = self.agent_dispatch.with_failover(enabled);
92        self.connector = self.connector.with_failover(enabled);
93        self
94    }
95
96    /// Overrides the default per-request timeout (10s) on every service.
97    pub fn with_request_timeout(mut self, timeout: Duration) -> Self {
98        self.room = self.room.with_request_timeout(timeout);
99        self.egress = self.egress.with_request_timeout(timeout);
100        self.ingress = self.ingress.with_request_timeout(timeout);
101        self.sip = self.sip.with_request_timeout(timeout);
102        self.agent_dispatch = self.agent_dispatch.with_request_timeout(timeout);
103        self.connector = self.connector.with_request_timeout(timeout);
104        self
105    }
106
107    /// Injects a mock-control header on every service (see the mock test server's
108    /// X-Lk-Mock protocol). Test-only, since the service methods don't expose
109    /// per-call headers.
110    #[cfg(test)]
111    pub(crate) fn with_mock(mut self, mock: &str) -> Self {
112        let mut headers = http::HeaderMap::new();
113        headers.insert(
114            http::HeaderName::from_static("x-lk-mock"),
115            http::HeaderValue::from_str(mock).unwrap(),
116        );
117        self.room = self.room.with_default_headers(headers.clone());
118        self.egress = self.egress.with_default_headers(headers.clone());
119        self.ingress = self.ingress.with_default_headers(headers.clone());
120        self.sip = self.sip.with_default_headers(headers.clone());
121        self.agent_dispatch = self.agent_dispatch.with_default_headers(headers.clone());
122        self.connector = self.connector.with_default_headers(headers);
123        self
124    }
125
126    pub fn room(&self) -> &RoomClient {
127        &self.room
128    }
129
130    pub fn egress(&self) -> &EgressClient {
131        &self.egress
132    }
133
134    pub fn ingress(&self) -> &IngressClient {
135        &self.ingress
136    }
137
138    pub fn sip(&self) -> &SIPClient {
139        &self.sip
140    }
141
142    pub fn agent_dispatch(&self) -> &AgentDispatchClient {
143        &self.agent_dispatch
144    }
145
146    pub fn connector(&self) -> &ConnectorClient {
147        &self.connector
148    }
149}