Skip to main content
Call logs provide a history of calls made through your application. You can retrieve call logs using the CometChat Chat SDK’s call log APIs.
Call logs are managed by the CometChat Chat SDK, not the Calls SDK. Ensure you have the Chat SDK integrated to access call history.

Prerequisites

To use call logs, you need:
  1. CometChat Chat SDK integrated (@cometchat/chat-sdk-react-native)
  2. User authenticated with the Chat SDK

Retrieve Call Logs

Use the CallLogRequestBuilder from the Chat SDK to fetch call logs:
import { CometChat } from '@cometchat/chat-sdk-react-native';

async function fetchCallLogs() {
  const callLogRequest = new CometChat.CallLogRequestBuilder()
    .setLimit(30)
    .setCallStatus('all') // 'all', 'initiated', 'ongoing', 'ended', 'cancelled', 'rejected', 'busy', 'unanswered'
    .build();

  try {
    const callLogs = await callLogRequest.fetchNext();
    console.log('Call logs:', callLogs);
    return callLogs;
  } catch (error) {
    console.error('Error fetching call logs:', error);
    throw error;
  }
}

CallLogRequestBuilder Options

MethodTypeDescription
setLimit(limit)numberMaximum number of logs to fetch (default: 30, max: 100)
setCallStatus(status)stringFilter by call status
setCallType(type)stringFilter by call type (audio or video)
setCallCategory(category)stringFilter by category (call for direct calls)
setAuthToken(token)stringAuth token for the request

Call Status Values

StatusDescription
allAll call logs
initiatedCalls that were initiated
ongoingCurrently active calls
endedCompleted calls
cancelledCalls cancelled by the initiator
rejectedCalls rejected by the receiver
busyCalls where receiver was busy
unansweredCalls that weren’t answered

Call Log Object

Each call log contains:
PropertyTypeDescription
sessionIdstringUnique session identifier
initiatorUserUser who initiated the call
receiverUser/GroupCall recipient
callStatusstringFinal status of the call
callTypestringaudio or video
initiatedAtnumberTimestamp when call was initiated
joinedAtnumberTimestamp when call was joined
endedAtnumberTimestamp when call ended
durationnumberCall duration in seconds
participantsarrayList of participants
recordingsarrayList of recordings (if any)

Filter by User

Get call logs for a specific user:
const callLogRequest = new CometChat.CallLogRequestBuilder()
  .setLimit(30)
  .setUid('user_uid')
  .build();

Filter by Group

Get call logs for a specific group:
const callLogRequest = new CometChat.CallLogRequestBuilder()
  .setLimit(30)
  .setGuid('group_guid')
  .build();

Pagination

Fetch call logs in pages:
import { CometChat } from '@cometchat/chat-sdk-react-native';

class CallLogManager {
  private callLogRequest: CometChat.CallLogRequest;

  constructor() {
    this.callLogRequest = new CometChat.CallLogRequestBuilder()
      .setLimit(30)
      .build();
  }

  async fetchNextPage() {
    try {
      const callLogs = await this.callLogRequest.fetchNext();
      return callLogs;
    } catch (error) {
      console.error('Error fetching call logs:', error);
      throw error;
    }
  }
}

// Usage
const manager = new CallLogManager();

// First page
const page1 = await manager.fetchNextPage();

// Next page
const page2 = await manager.fetchNextPage();

Complete Example

import React, { useState, useEffect, useCallback } from 'react';
import { View, FlatList, Text, StyleSheet, ActivityIndicator } from 'react-native';
import { CometChat } from '@cometchat/chat-sdk-react-native';

interface CallLog {
  sessionId: string;
  initiator: { uid: string; name: string };
  receiver: { uid: string; name: string };
  callStatus: string;
  callType: string;
  initiatedAt: number;
  duration: number;
}

function CallLogsScreen() {
  const [callLogs, setCallLogs] = useState<CallLog[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [callLogRequest, setCallLogRequest] = useState<CometChat.CallLogRequest | null>(null);

  useEffect(() => {
    const request = new CometChat.CallLogRequestBuilder()
      .setLimit(30)
      .build();
    setCallLogRequest(request);
    fetchCallLogs(request);
  }, []);

  const fetchCallLogs = async (request: CometChat.CallLogRequest) => {
    try {
      const logs = await request.fetchNext();
      setCallLogs(logs);
    } catch (error) {
      console.error('Error fetching call logs:', error);
    } finally {
      setLoading(false);
    }
  };

  const loadMore = useCallback(async () => {
    if (!callLogRequest || loadingMore) return;

    setLoadingMore(true);
    try {
      const moreLogs = await callLogRequest.fetchNext();
      setCallLogs((prev) => [...prev, ...moreLogs]);
    } catch (error) {
      console.error('Error loading more:', error);
    } finally {
      setLoadingMore(false);
    }
  }, [callLogRequest, loadingMore]);

  const formatDuration = (seconds: number) => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  };

  const formatDate = (timestamp: number) => {
    return new Date(timestamp * 1000).toLocaleString();
  };

  const renderCallLog = ({ item }: { item: CallLog }) => (
    <View style={styles.callLogItem}>
      <View style={styles.callInfo}>
        <Text style={styles.participantName}>
          {item.initiator.name}{item.receiver.name}
        </Text>
        <Text style={styles.callDetails}>
          {item.callType}{item.callStatus}
        </Text>
        <Text style={styles.callTime}>{formatDate(item.initiatedAt)}</Text>
      </View>
      <Text style={styles.duration}>
        {item.duration > 0 ? formatDuration(item.duration) : '-'}
      </Text>
    </View>
  );

  if (loading) {
    return (
      <View style={styles.centered}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  return (
    <FlatList
      data={callLogs}
      keyExtractor={(item) => item.sessionId}
      renderItem={renderCallLog}
      onEndReached={loadMore}
      onEndReachedThreshold={0.5}
      ListFooterComponent={
        loadingMore ? <ActivityIndicator style={styles.footer} /> : null
      }
      ListEmptyComponent={
        <View style={styles.centered}>
          <Text style={styles.emptyText}>No call logs</Text>
        </View>
      }
    />
  );
}

const styles = StyleSheet.create({
  centered: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  callLogItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  callInfo: {
    flex: 1,
  },
  participantName: {
    fontSize: 16,
    fontWeight: '600',
  },
  callDetails: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  callTime: {
    fontSize: 12,
    color: '#999',
    marginTop: 4,
  },
  duration: {
    fontSize: 14,
    color: '#333',
  },
  footer: {
    padding: 16,
  },
  emptyText: {
    fontSize: 16,
    color: '#999',
  },
});

export default CallLogsScreen;