const call = client.video.call("default", "call-id");
const response = await call.queryCallParticipantSessions({
session: "<session-id>",
limit: 25,
});Call Attendance
The QueryCallParticipantSessions endpoint retrieves a paginated list of participant sessions for a given call session. Each entry describes an individual join/leave event for a user within that session. This data is not real-time — stats may be delayed or incomplete during an active call. The complete and final data becomes available after the call ends and the call.stats_report_ready event is received.
Response overview
call_type: Type of the call.call_id: ID of the call.call_session_id: ID of the call session being queried.total_participant_sessions: Total number of participant sessions in the call session.total_participant_duration: Sum of all participant durations in seconds.participants_sessions: Array of participant session details. Available for 90 days after the call session ends — after that, this array will be empty while all other response fields remain available:user_id: ID of the user.user_session_id: ID of the user's session.joined_at: Timestamp when the participant joined.left_at: Timestamp when the participant left.duration_in_seconds: Duration of the participant's session in seconds.publisher_type: Type of publisher (webrtc,rtmp,srt, etc.).roles: Roles assigned to the participant.
next/prev: Cursors for pagination.
var call = client.video().call("default", "call-id");
var response = call.queryCallParticipantSessions(
"<session-id>",
QueryCallParticipantSessionsRequest.builder().limit(25).build()
);Filtering
You can narrow down results using filter_conditions. Filters follow the same syntax as other query endpoints. Note that filters only affect the participants_sessions list — aggregated fields such as total_participant_sessions and total_participant_duration always reflect the full call session.
var response = call.queryCallParticipantSessions(
"<session-id>",
QueryCallParticipantSessionsRequest.builder()
.filterConditions(Map.of("user_id", Map.of("$eq", "alice")))
.build()
);To compute aggregated values (such as total duration or session count) for a filtered subset of participants, paginate through all pages and accumulate the results manually:
String cursor = null;
long totalDuration = 0;
int totalSessions = 0;
do {
var response = call.queryCallParticipantSessions(
"<session-id>",
QueryCallParticipantSessionsRequest.builder()
.limit(100)
.next(cursor)
.filterConditions(Map.of("user_id", Map.of("$eq", "alice")))
.build()
);
for (var s : response.getData().getParticipantsSessions()) {
totalDuration += s.getDurationInSeconds();
totalSessions++;
}
cursor = response.getData().getNext();
} while (cursor != null);Pagination
Use next and prev cursors from the response to paginate through results.
String cursor = null;
do {
var response = call.queryCallParticipantSessions(
"<session-id>",
QueryCallParticipantSessionsRequest.builder().limit(25).next(cursor).build()
);
cursor = response.getData().getNext();
} while (cursor != null);