> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-ios-v5-calls-corrections.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Call Logs

> Display CometChat Calls SDK v5 call logs on iOS with call history, participants, call type, duration, and status details.

Retrieve call history for your application. Call logs provide detailed information about past calls including duration, participants, recordings, and status.

## Fetch Call Logs

Use `CallLogsRequest` to fetch call logs with pagination support. The builder pattern allows you to filter results by various criteria.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let callLogRequest = CallLogsRequest.CallLogsBuilder()
        .set(limit: 30)
        .build()

    callLogRequest.fetchNext(onSuccess: { callLogs in
        for callLog in callLogs {
            print("Session: \(callLog.sessionID)")
            print("Duration: \(callLog.totalDuration)")
            print("Status: \(callLog.status.value)")
        }
    }, onError: { error in
        print("Error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    CallLogsBuilder *builder = [[CallLogsBuilder alloc] init];
    CallLogsRequest *callLogRequest = [[builder setWithLimit:30] build];

    [callLogRequest fetchNextOnSuccess:^(NSArray<CallLog *> * callLogs) {
        for (CallLog *callLog in callLogs) {
            NSLog(@"Session: %@", callLog.sessionID);
            NSLog(@"Duration: %@", callLog.totalDuration);
        }
    } onError:^(CometChatCallException * error) {
        NSLog(@"Error: %@", error.errorDescription);
    }];
    ```
  </Tab>
</Tabs>

## CallLogsBuilder

Configure the request using the builder methods:

| Method                              | Type          | Description                                                        |
| ----------------------------------- | ------------- | ------------------------------------------------------------------ |
| `set(limit: Int)`                   | Int           | Number of call logs to fetch per request (default: 30, max: 100)   |
| `set(callType: SessionType)`        | SessionType   | Filter by call type: `.video` or `.voice`                          |
| `set(callStatus: CallStatus)`       | CallStatus    | Filter by call status                                              |
| `set(hasRecording: Bool)`           | Bool          | Filter calls that have recordings                                  |
| `set(hasTranscriptions: Bool)`      | Bool          | Filter calls that have transcripts, and attach them to each log    |
| `set(callCategory: CallCategory)`   | CallCategory  | Filter by category: `.call`, `.meet`, `.presenter` or `.broadcast` |
| `set(callDirection: CallDirection)` | CallDirection | Filter by direction: `.incoming` or `.outgoing`                    |
| `set(uid: String)`                  | String        | Filter calls with a specific user                                  |
| `set(guid: String)`                 | String        | Filter calls with a specific group                                 |

<Note>
  In Objective-C these are `setWithLimit:`, `setWithCallType:`, `setWithHasTranscriptions:` and so on, and the builder is instantiated directly as `[[CallLogsBuilder alloc] init]`.
</Note>

### Filter Examples

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    // Fetch only video calls
    let videoCallsRequest = CallLogsRequest.CallLogsBuilder()
        .set(callType: .video)
        .set(limit: 20)
        .build()

    // Fetch calls with recordings
    let recordedCallsRequest = CallLogsRequest.CallLogsBuilder()
        .set(hasRecording: true)
        .build()

    // Fetch calls with transcripts
    let transcribedCallsRequest = CallLogsRequest.CallLogsBuilder()
        .set(hasTranscriptions: true)
        .build()

    // Fetch missed incoming calls
    let missedCallsRequest = CallLogsRequest.CallLogsBuilder()
        .set(callStatus: .missed)
        .set(callDirection: .incoming)
        .build()

    // Fetch calls with a specific user
    let userCallsRequest = CallLogsRequest.CallLogsBuilder()
        .set(uid: "user_id")
        .build()
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    // Fetch only video calls
    CallLogsRequest *videoCallsRequest = [[[[[CallLogsBuilder alloc] init]
        setWithCallType:SessionTypeVideo]
        setWithLimit:20]
        build];

    // Fetch calls with recordings
    CallLogsRequest *recordedCallsRequest = [[[[CallLogsBuilder alloc] init]
        setWithHasRecording:YES]
        build];

    // Fetch calls with transcripts
    CallLogsRequest *transcribedCallsRequest = [[[[CallLogsBuilder alloc] init]
        setWithHasTranscriptions:YES]
        build];

    // Fetch missed incoming calls
    CallLogsRequest *missedCallsRequest = [[[[[CallLogsBuilder alloc] init]
        setWithCallStatus:CallStatusMissed]
        setWithCallDirection:CallDirectionIncoming]
        build];

    // Fetch calls with a specific user
    CallLogsRequest *userCallsRequest = [[[[CallLogsBuilder alloc] init]
        setWithUid:@"user_id"]
        build];
    ```
  </Tab>
</Tabs>

## Pagination

Use `fetchNext` and `fetchPrevious` for pagination. `fetchPrevious` takes an optional `authToken`; pass `nil` to use the logged-in user's stored token:

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    // Fetch next page
    callLogRequest.fetchNext(onSuccess: { callLogs in
        // Handle next page
    }, onError: { error in
        print("Error: \(error?.errorDescription ?? "")")
    })

    // Fetch previous page
    callLogRequest.fetchPrevious(authToken: nil, onSuccess: { callLogs in
        // Handle previous page
    }, onError: { error in
        print("Error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    // Fetch next page
    [callLogRequest fetchNextOnSuccess:^(NSArray<CallLog *> * callLogs) {
        // Handle next page
    } onError:^(CometChatCallException * error) {
        NSLog(@"Error: %@", error.errorDescription);
    }];

    // Fetch previous page
    [callLogRequest fetchPreviousWithAuthToken:nil
        onSuccess:^(NSArray<CallLog *> * callLogs) {
            // Handle previous page
        } onError:^(CometChatCallException * error) {
            NSLog(@"Error: %@", error.errorDescription);
        }];
    ```
  </Tab>
</Tabs>

## CallLog Object

Each `CallLog` object contains detailed information about a call:

| Property                 | Type           | Description                                                                                         |
| ------------------------ | -------------- | --------------------------------------------------------------------------------------------------- |
| `sessionID`              | String         | Unique identifier for the call session                                                              |
| `mid`                    | String         | Meeting identifier                                                                                  |
| `initiator`              | CallEntity     | User who initiated the call                                                                         |
| `receiver`               | CallEntity     | User or group that received the call                                                                |
| `receiverType`           | CallEntityType | `.callUser` or `.callGroup`                                                                         |
| `type`                   | SessionType    | Call type: `.video` or `.voice`                                                                     |
| `status`                 | CallStatus     | Final status of the call                                                                            |
| `mode`                   | CallCategory   | Category: `.call`, `.meet`, `.presenter` or `.broadcast`                                            |
| `initiatedAt`            | Int            | Timestamp when call was initiated                                                                   |
| `startedAt`              | Int?           | Timestamp when call started                                                                         |
| `endedAt`                | Int?           | Timestamp when call ended                                                                           |
| `totalDuration`          | String         | Human-readable duration (e.g., "5:30")                                                              |
| `totalDurationInMinutes` | Double         | Duration in minutes                                                                                 |
| `totalAudioMinutes`      | Double         | Audio duration in minutes                                                                           |
| `totalVideoMinutes`      | Double         | Video duration in minutes                                                                           |
| `totalParticipants`      | Int            | Number of participants                                                                              |
| `participants`           | \[Participant] | List of participants who joined                                                                     |
| `hasRecording`           | Bool           | Whether the call was recorded                                                                       |
| `recordings`             | \[Recording]   | List of recording objects                                                                           |
| `transcriptions`         | \[Transcript]  | List of transcript objects. Populated only when the request opted in with `set(hasTranscriptions:)` |

## Access Recordings

If a call has recordings, access them through the `recordings` property:

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    callLogRequest.fetchNext(onSuccess: { callLogs in
        for callLog in callLogs {
            if callLog.hasRecording {
                for recording in callLog.recordings {
                    print("Recording ID: \(recording.rid ?? "")")
                    print("Recording URL: \(recording.recordingURL ?? "")")
                    print("Duration: \(recording.duration ?? 0) seconds")
                }
            }
        }
    }, onError: { error in
        print("Error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    [callLogRequest fetchNextOnSuccess:^(NSArray<CallLog *> * callLogs) {
        for (CallLog *callLog in callLogs) {
            if (callLog.hasRecording) {
                for (Recording *recording in callLog.recordings) {
                    NSLog(@"Recording ID: %@", recording.rid);
                    NSLog(@"Recording URL: %@", recording.recordingURL);
                    NSLog(@"Duration: %f seconds", recording.duration);
                }
            }
        }
    } onError:^(CometChatCallException * error) {
        NSLog(@"Error: %@", error.errorDescription);
    }];
    ```
  </Tab>
</Tabs>

## Access Transcripts

*Available since v5.0.4*

Opting in with `set(hasTranscriptions: true)` restricts the list to transcribed calls **and** makes the server attach each call's transcripts to the log:

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let callLogRequest = CallLogsRequest.CallLogsBuilder()
        .set(limit: 30)
        .set(hasTranscriptions: true)
        .build()

    callLogRequest.fetchNext(onSuccess: { callLogs in
        for callLog in callLogs {
            for transcript in callLog.transcriptions {
                print("Transcript ID: \(transcript.tid)")
                print("Transcript URL: \(transcript.transcriptUrl)")
            }
        }
    }, onError: { error in
        print("Error: \(error?.errorDescription ?? "")")
    })
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    CallLogsRequest *callLogRequest = [[[[[CallLogsBuilder alloc] init]
        setWithLimit:30]
        setWithHasTranscriptions:YES]
        build];

    [callLogRequest fetchNextOnSuccess:^(NSArray<CallLog *> * callLogs) {
        for (CallLog *callLog in callLogs) {
            for (Transcript *transcript in callLog.transcriptions) {
                NSLog(@"Transcript ID: %@", transcript.tid);
                NSLog(@"Transcript URL: %@", transcript.transcriptUrl);
            }
        }
    } onError:^(CometChatCallException * error) {
        NSLog(@"Error: %@", error.errorDescription);
    }];
    ```
  </Tab>
</Tabs>

`transcriptions` is an empty array when the server omitted transcripts, so it never needs a nil check. To page through a single session's transcripts directly, use [`TranscriptsRequest`](/calls/ios/transcription#retrieving-transcripts).

<Accordion title="Call Status Values">
  | Status       | Description                         |
  | ------------ | ----------------------------------- |
  | `ongoing`    | Call is currently in progress       |
  | `busy`       | Receiver was busy                   |
  | `rejected`   | Call was rejected                   |
  | `cancelled`  | Call was cancelled by initiator     |
  | `ended`      | Call ended normally                 |
  | `missed`     | Call was missed                     |
  | `initiated`  | Call was initiated but not answered |
  | `unanswered` | Call was not answered               |
</Accordion>

<Accordion title="Call Category Values">
  | Category | Description               |
  | -------- | ------------------------- |
  | `call`   | Direct call between users |
  | `meet`   | Meeting/conference call   |
</Accordion>

<Accordion title="Call Direction Values">
  | Direction  | Description                |
  | ---------- | -------------------------- |
  | `incoming` | Call received by the user  |
  | `outgoing` | Call initiated by the user |
</Accordion>

## Related Documentation

* [Transcription](/calls/ios/transcription)
* [Recording](/calls/ios/recording)
