Generate an access token for Analytics requests
Analytics API requests are authorized with a LiveKit token. This is generated by a server side SDK,much like generating a token for joining Rooms, except that the token needs the roomList grant.
Analytics API is only available to LiveKit Cloud customers with a Scale plan or higher.
lk token create \--api-key $LIVEKIT_API_KEY \--api-secret $LIVEKIT_SECRET_KEY \--list \--valid-for 24h
To streamline your workflow with the CLI, add your projects using the command lk project add. This approach spares you from repeatedly entering your --url, --api-key, and --api-secret for each command you execute.
const at = new AccessToken(apiKey, apiSecret, { ttl: 60 * 60 * 24 });at.addGrant({ roomList: true });
List sessions
To make a request, you'll need to know your project id, which you can see in the URL for your project dashboard. It's the part after /projects/ that starts with p_.
curl -H "Authorization: Bearer $TOKEN" \"https://cloud-api.livekit.io/api/project/$PROJECT_ID/sessions"
async function listLiveKitSessions() {const endpoint = `https://cloud-api.livekit.io/api/project/${PROJECT_ID}/sessions/`;try {const response = await fetch(endpoint, {method: 'GET',headers: {Authorization: `Bearer ${token}`,'Content-Type': 'application/json',},});if (!response.ok) throw new Error('Network response was not ok');const data = await response.json();console.log(data); // or do whatever you like here} catch (error) {console.log('There was a problem:', error.message);}}listLiveKitSessions();
This will return a JSON object like this:
{sessions: [{sessionId, // stringroomName, // stringcreatedAt, // TimestampendedAt, // TimestamplastActive, // TimestampbandwidthIn, // bytes of bandwidth uploadedbandwidthOut, // bytes of bandwidth downloadedegress, // 0 = never started, 1 = active, 2 = endednumParticipants, // intnumActiveParticipants, // intconnectionCounts: {attempts, // intsuccess // int},},// ...]}
Query parameters
You can limit the number of returned sessions by adding the limit query parameter like ?limit=100.
Higher limit values may result in a timeout from the Analytics API.
You can page through the results by adding ?page=n&limit=100 to the endpoint URL to get the nth page of results with 100 sessions per page. Pagination starts from 0.
Specify the start date for the request time range in the format YYYY-MM-DD. Sessions starting on the specified start date will be included in the response.
The start date must be within 7 days of the current date.
Specify the end date for the request time range using the format YYYY-MM-DD. Sessions up to and including this end date will be included in the response.
Examples
# Get the first page and limit the number of sessions to 100.curl -H "Authorization: Bearer $TOKEN" \"https://cloud-api.livekit.io/api/project/$PROJECT_ID/sessions\?page=0&limit=100"# Fetch sessions from a specified time range.curl -H "Authorization: Bearer $TOKEN" \"https://cloud-api.livekit.io/api/project/$PROJECT_ID/sessions\?start=2024-01-12&end=2024-01-13"
List session details
To get more details about a specific session, you can use the session_id returned from the list sessions request.
curl -H "Authorization: Bearer $TOKEN" \"cloud-api.livekit.io/api/project/$PROJECT_ID/sessions/$SESSION_ID"
async function getLiveKitSessionDetails() {const endpoint = `https://cloud-api.livekit.io/api/project/${PROJECT_ID}/sessions/${SESSION_ID}`;try {const response = await fetch(endpoint, {method: 'GET',headers: {Authorization: `Bearer ${token}`,'Content-Type': 'application/json',},});if (!response.ok) throw new Error('Network response was not ok');const data = await response.json();console.log(data); // or do whatever you like here} catch (error) {console.log('There was a problem:', error.message);}}getLiveKitSessionDetails();
This will return a JSON object like this:
{roomId, // stringroomName, // stringbandwidth, // billable bytes of bandwidth usedstartTime, // Timestamp (e.g., "2025-09-29T13:59:40Z")endTime, // Timestamp (e.g., "2025-09-29T14:59:40Z")numParticipants, // intconnectionMinutes, // int: billable number of connection minutes for this sessionquality: [{timestamp: // Timestamp (e.g., "2025-09-25T16:46:00Z")value: // int},// ...],publishBps: [{timestamp: // Timestamp (e.g., "2025-09-25T16:46:00Z")value: // int},// ...]participants: [{participantIdentity, // stringparticipantName, // stringroomId, // stringjoinedAt, // Timestamp (e.g., "2025-09-29T13:59:40Z")leftAt, // Timestamp (e.g., "2025-09-29T14:59:40Z")location, // stringregion, // stringconnectionType, // string (e.g., "UDP")connectionTimeMs, // intdeviceModel, // string (e.g., "Mac")os, // string (e.g., "mac os x 10.15.7")browser, // string (e.g., "Chrome 140.0.0")sdkVersion, // string (e.g., "JS 2.15.7")publishedSources: {cameraTrack, // booleanmicrophoneTrack, // booleanscreenShareTrack, // booleanscreenShareAudio, // boolean},sessions: [{participantId, // stringjoinedAt, // Timestamp (e.g., "2025-09-29T13:59:40Z")leftAt, // Timestamp (e.g., "2025-09-29T14:59:40Z")},// ...],},// ...]}
Timestamp objects are Protobuf Timestamps.