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

# Standalone Calling

> Implement audio and video calling using only the CometChat Calls SDK, without the Chat SDK — ideal for apps that need calling without full chat infrastructure.

<Info>
  **Quick Reference** - Generate token and start a standalone call session:

  ```javascript theme={null}
  // Generate call token (auth token from REST API, not Chat SDK)
  const callToken = await CometChatCalls.generateToken(sessionId, userAuthToken);

  // Configure and render
  const callSettings = new CometChatCalls.CallSettingsBuilder()
    .enableDefaultLayout(true)
    .setIsAudioOnlyCall(false)
    .build();

  // <CometChatCalls.Component callSettings={callSettings} callToken={callToken} />
  ```
</Info>

<Note>
  **Available via:** SDK | UI Kits
</Note>

## Overview

This section demonstrates how to implement calling functionality using only the CometChat Calls SDK, without requiring the Chat SDK. This is ideal for applications that need video/audio calling capabilities without the full chat infrastructure.

<Note>
  Before you begin, ensure you have completed the [Calls SDK setup](/sdk/react-native/calling-setup).
</Note>

## User Authentication

To start a call session, you need a user auth token. Since this implementation doesn't use the Chat SDK, you'll need to obtain the auth token via the CometChat REST API.

<Note>
  To understand user authentication in CometChat, see the [User Auth](/fundamentals/user-auth) documentation.
</Note>

You can obtain the auth token using one of these REST API endpoints:

* [Create Auth Token](/rest-api/auth-tokens/create) — Creates a new auth token for a user
* [Get Auth Token](/rest-api/auth-tokens/get) — Retrieves an existing auth token

<Warning>
  Auth tokens grant access to call sessions on behalf of a user. Never expose auth tokens in client-side code in production. Use a secure backend to generate and deliver tokens to your app.
</Warning>

<Note>
  For testing or POC purposes, you can create an auth token directly from the [CometChat Dashboard](https://app.cometchat.com). Navigate to **Users & Groups → Users**, select a user, and click **+ Create Auth Token**.
</Note>

Store the auth token securely in your application for use when generating call tokens.

## Generate Call Token

A call token is required for secure access to a call session. Each token is unique to a specific session and user combination, ensuring that only authorized users can join the call.

You can generate the token just before starting the call, or generate and store it ahead of time based on your use case.

Use the `generateToken()` method to create a call token:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const sessionId = "UNIQUE_SESSION_ID"; // Generate a unique session ID
    const userAuthToken = "USER_AUTH_TOKEN"; // Obtained from REST API

    CometChatCalls.generateToken(sessionId, userAuthToken).then(
      (callToken) => {
        console.log("Call token generated:", callToken.token);
        // Use callToken to start the session
      },
      (error) => {
        console.log("Token generation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sessionId: string = "UNIQUE_SESSION_ID"; // Generate a unique session ID
    const userAuthToken: string = "USER_AUTH_TOKEN"; // Obtained from REST API

    CometChatCalls.generateToken(sessionId, userAuthToken).then(
      (callToken: GenerateToken) => {
        console.log("Call token generated:", callToken.token);
        // Use callToken to start the session
      },
      (error: CometChat.CometChatException) => {
        console.log("Token generation failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

| Parameter       | Description                                                                                                         |
| --------------- | ------------------------------------------------------------------------------------------------------------------- |
| `sessionId`     | A unique session ID for the call. Generate this yourself or use a shared ID for participants to join the same call. |
| `userAuthToken` | The user auth token obtained from the CometChat REST API.                                                           |

<Accordion title="Response">
  **On Success** — `generateToken()` returns a `GenerateToken` object containing the session ID and JWT token:

  <span id="generate-token-object" style={{scrollMarginTop: '100px'}} />

  **GenerateToken Object:**

  | Parameter   | Type   | Description                                   | Sample Value                                                                       |
  | ----------- | ------ | --------------------------------------------- | ---------------------------------------------------------------------------------- |
  | `sessionId` | string | Unique identifier for the call session        | `"v1.in.2748663902141719.1772095292a49c6a5198e07f9096447749e87124204d95cfc8"`      |
  | `token`     | string | JWT token for authenticating the call session | `"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImNjcHJvX2p3dF9yczI1Nl9rZXkxIn0..."` |
</Accordion>

## Start Call Session

Use the `CometChatCalls.Component` to render the call UI. This component requires a call token (generated in the previous step) and a `CallSettings` object that configures the call UI and behavior.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const callListener = new CometChatCalls.OngoingCallListener({
      onUserJoined: (user) => {
        console.log("User joined:", user);
      },
      onUserLeft: (user) => {
        console.log("User left:", user);
      },
      onUserListUpdated: (userList) => {
        console.log("User list updated:", userList);
      },
      onCallEnded: () => {
        console.log("Call ended");
        CometChatCalls.endSession();
        // Close calling screen
      },
      onCallEndButtonPressed: () => {
        console.log("End call button pressed");
        CometChatCalls.endSession();
        // Close calling screen
      },
      onError: (error) => {
        console.log("Call error:", error);
      },
      onAudioModesUpdated: (audioModes) => {
        console.log("Audio modes updated:", audioModes);
      },
      onCallSwitchedToVideo: (event) => {
        console.log("Call switched to video:", event);
      },
      onUserMuted: (event) => {
        console.log("User muted:", event);
      },
      onSessionTimeout: () => {
        console.log("Session timed out");
      }
    });

    const callSettings = new CometChatCalls.CallSettingsBuilder()
      .enableDefaultLayout(true)
      .setIsAudioOnlyCall(false)
      .setCallEventListener(callListener)
      .build();

    // In your render method
    return (
      <View style={{ height: '100%', width: '100%', position: 'relative' }}>
        <CometChatCalls.Component callSettings={callSettings} callToken={callToken} />
      </View>
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const callListener = new CometChatCalls.OngoingCallListener({
      onUserJoined: (user: CometChat.User) => {
        console.log("User joined:", user);
      },
      onUserLeft: (user: CometChat.User) => {
        console.log("User left:", user);
      },
      onUserListUpdated: (userList: CometChat.User[]) => {
        console.log("User list updated:", userList);
      },
      onCallEnded: () => {
        console.log("Call ended");
        CometChatCalls.endSession();
        // Close calling screen
      },
      onCallEndButtonPressed: () => {
        console.log("End call button pressed");
        CometChatCalls.endSession();
        // Close calling screen
      },
      onError: (error: CometChat.CometChatException) => {
        console.log("Call error:", error);
      },
      onAudioModesUpdated: (audioModes: string[]) => {
        console.log("Audio modes updated:", audioModes);
      },
      onCallSwitchedToVideo: (event: any) => {
        console.log("Call switched to video:", event);
      },
      onUserMuted: (event: any) => {
        console.log("User muted:", event);
      },
      onSessionTimeout: () => {
        console.log("Session timed out");
      }
    });

    const callSettings = new CometChatCalls.CallSettingsBuilder()
      .enableDefaultLayout(true)
      .setIsAudioOnlyCall(false)
      .setCallEventListener(callListener)
      .build();

    // In your render method
    return (
      <View style={{ height: '100%', width: '100%', position: 'relative' }}>
        <CometChatCalls.Component callSettings={callSettings} callToken={callToken} />
      </View>
    );
    ```
  </Tab>
</Tabs>

| Parameter      | Description                                                          |
| -------------- | -------------------------------------------------------------------- |
| `callToken`    | The `GenerateToken` object received from `generateToken()` onSuccess |
| `callSettings` | Object of `CallSettings` class configured via `CallSettingsBuilder`  |

### Call Settings

Configure the call experience using the following `CallSettingsBuilder` methods:

| Method                                                    | Description                                                                                                                                                                                         |
| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enableDefaultLayout(boolean)`                            | Enables or disables the default call UI layout with built-in controls. `true` shows the default layout with end call, mute, video toggle buttons. `false` hides the button layout. Default: `true`  |
| `setIsAudioOnlyCall(boolean)`                             | Sets whether the call is audio-only or audio-video. `true` for audio-only, `false` for audio-video. Default: `false`                                                                                |
| `setCallEventListener(OngoingCallListener)`               | Sets the listener to receive call events. See [Call Listeners](#call-listeners) for available callbacks.                                                                                            |
| `setMode(string)`                                         | Sets the call UI layout mode. Available: `CometChat.CALL_MODE.DEFAULT` (grid), `CometChat.CALL_MODE.SPOTLIGHT` (active speaker), `CometChat.CALL_MODE.SINGLE` (one participant). Default: `DEFAULT` |
| `setAvatarMode(string)`                                   | Sets how avatars are displayed when video is off. Available: `circle`, `square`, `fullscreen`. Default: `circle`                                                                                    |
| `setDefaultAudioMode(string)`                             | Sets the initial audio output device. Available: `SPEAKER`, `EARPIECE`, `BLUETOOTH`, `HEADPHONES`                                                                                                   |
| `startWithAudioMuted(boolean)`                            | Starts the call with the microphone muted. Default: `false`                                                                                                                                         |
| `startWithVideoMuted(boolean)`                            | Starts the call with the camera turned off. Default: `false`                                                                                                                                        |
| `showEndCallButton(boolean)`                              | Shows or hides the end call button in the default layout. Default: `true`                                                                                                                           |
| `showSwitchCameraButton(boolean)`                         | Shows or hides the switch camera button (front/back). Default: `true`                                                                                                                               |
| `showMuteAudioButton(boolean)`                            | Shows or hides the mute audio button. Default: `true`                                                                                                                                               |
| `showPauseVideoButton(boolean)`                           | Shows or hides the pause video button. Default: `true`                                                                                                                                              |
| `showAudioModeButton(boolean)`                            | Shows or hides the audio mode selection button. Default: `true`                                                                                                                                     |
| `showSwitchToVideoCallButton(boolean)`                    | Shows or hides the button to upgrade an audio call to video. Default: `true`                                                                                                                        |
| `setMainVideoContainerSetting(MainVideoContainerSetting)` | Customizes the main video container. See [Video View Customization](/sdk/react-native/video-view-customisation).                                                                                    |
| `enableVideoTileClick(boolean)`                           | Enables or disables click interactions on video tiles in Spotlight mode. Default: `true`                                                                                                            |
| `enableVideoTileDrag(boolean)`                            | Enables or disables drag functionality for video tiles in Spotlight mode. Default: `true`                                                                                                           |
| `setIdleTimeoutPeriod(number)`                            | Sets idle timeout in seconds. Warning appears 60 seconds before auto-termination. Default: `180` seconds. *v4.2.0+*                                                                                 |

## Call Listeners

The `OngoingCallListener` provides real-time callbacks for call session events, including participant changes, call state updates, and error conditions.

You can register listeners in two ways:

1. **Via CallSettingsBuilder:** Use `.setCallEventListener(listener)` when building call settings
2. **Via addCallEventListener:** Use `CometChatCalls.addCallEventListener(listenerId, listener)` to add multiple listeners

Each listener requires a unique `listenerId` string. This ID is used to:

* **Prevent duplicate registrations** — Re-registering with the same ID replaces the existing listener
* **Enable targeted removal** — Remove specific listeners without affecting others

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    useEffect(() => {
      const listenerId = "UNIQUE_LISTENER_ID";
      
      CometChatCalls.addCallEventListener(listenerId, {
        onUserJoined: (user) => {
          console.log("User joined:", user);
        },
        onUserLeft: (user) => {
          console.log("User left:", user);
        },
        onUserListUpdated: (userList) => {
          console.log("User list updated:", userList);
        },
        onCallEnded: () => {
          console.log("Call ended");
          CometChatCalls.endSession();
          // Close calling screen
        },
        onCallEndButtonPressed: () => {
          console.log("End call button pressed");
          CometChatCalls.endSession();
          // Close calling screen
        },
        onError: (error) => {
          console.log("Call error:", error);
        },
        onAudioModesUpdated: (audioModes) => {
          console.log("Audio modes updated:", audioModes);
        },
        onCallSwitchedToVideo: (event) => {
          console.log("Call switched to video:", event);
        },
        onUserMuted: (event) => {
          console.log("User muted:", event);
        },
        onSessionTimeout: () => {
          console.log("Session timed out");
        }
      });

      // Cleanup on unmount
      return () => CometChatCalls.removeCallEventListener(listenerId);
    }, []);
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    useEffect(() => {
      const listenerId: string = "UNIQUE_LISTENER_ID";
      
      CometChatCalls.addCallEventListener(listenerId, {
        onUserJoined: (user: CometChat.User) => {
          console.log("User joined:", user);
        },
        onUserLeft: (user: CometChat.User) => {
          console.log("User left:", user);
        },
        onUserListUpdated: (userList: CometChat.User[]) => {
          console.log("User list updated:", userList);
        },
        onCallEnded: () => {
          console.log("Call ended");
          CometChatCalls.endSession();
          // Close calling screen
        },
        onCallEndButtonPressed: () => {
          console.log("End call button pressed");
          CometChatCalls.endSession();
          // Close calling screen
        },
        onError: (error: CometChat.CometChatException) => {
          console.log("Call error:", error);
        },
        onAudioModesUpdated: (audioModes: string[]) => {
          console.log("Audio modes updated:", audioModes);
        },
        onCallSwitchedToVideo: (event: any) => {
          console.log("Call switched to video:", event);
        },
        onUserMuted: (event: any) => {
          console.log("User muted:", event);
        },
        onSessionTimeout: () => {
          console.log("Session timed out");
        }
      });

      // Cleanup on unmount
      return () => CometChatCalls.removeCallEventListener(listenerId);
    }, []);
    ```
  </Tab>
</Tabs>

<Warning>
  Always remove call event listeners when the component unmounts using `CometChatCalls.removeCallEventListener(listenerId)`. Failing to remove listeners can cause memory leaks and duplicate event handling.
</Warning>

### Events

| Event                             | Description                                                                                                                                         |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onCallEnded()`                   | Invoked when the call session terminates for a 1:1 call. Both participants receive this callback. Only fires for calls with exactly 2 participants. |
| `onSessionTimeout()`              | Invoked when the call is auto-terminated due to inactivity (default: 180 seconds). Warning appears 60 seconds before. *v4.2.0+*                     |
| `onCallEndButtonPressed()`        | Invoked when the local user taps the end call button. Call `CometChatCalls.endSession()` to leave the session.                                      |
| `onUserJoined(user)`              | Invoked when a remote participant joins. The `user` contains UID, name, and avatar.                                                                 |
| `onUserLeft(user)`                | Invoked when a remote participant leaves the call session.                                                                                          |
| `onUserListUpdated(userList)`     | Invoked whenever the participant list changes (join or leave events).                                                                               |
| `onAudioModesUpdated(audioModes)` | Invoked when available audio devices change (e.g., Bluetooth connected).                                                                            |
| `onCallSwitchedToVideo(event)`    | Invoked when an audio call is upgraded to a video call.                                                                                             |
| `onUserMuted(event)`              | Invoked when a participant's mute state changes.                                                                                                    |
| `onScreenShareStarted()`          | Invoked when the local user starts sharing a screen.                                                                                                |
| `onScreenShareStopped()`          | Invoked when the local user stops sharing a screen.                                                                                                 |
| `onError(error)`                  | Invoked when an error occurs during the call session.                                                                                               |

<Accordion title="onUserJoined Response">
  **On Event** — `onUserJoined` returns a user object when a participant joins the call:

  <span id="on-user-joined-object" style={{scrollMarginTop: '100px'}} />

  **User Object:**

  | Parameter      | Type    | Description                                 | Sample Value                                                            |
  | -------------- | ------- | ------------------------------------------- | ----------------------------------------------------------------------- |
  | `uid`          | string  | Unique identifier of the user               | `"cometchat-uid-6"`                                                     |
  | `name`         | string  | Display name of the user                    | `"Ronald Jerry"`                                                        |
  | `avatar`       | string  | URL to user's avatar image                  | `"https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-6.webp"` |
  | `id`           | string  | Internal session participant ID             | `"cd530243"`                                                            |
  | `joinedAt`     | string  | Unix timestamp when user joined (as string) | `"1772095303043"`                                                       |
  | `isVideoMuted` | boolean | Whether user's video is muted               | `true`                                                                  |
  | `isAudioMuted` | boolean | Whether user's audio is muted               | `false`                                                                 |
  | `isLocalUser`  | boolean | Whether this is the local user              | `false`                                                                 |
</Accordion>

<Accordion title="onUserLeft Response">
  **On Event** — `onUserLeft` returns a user object when a participant leaves the call:

  <span id="on-user-left-object" style={{scrollMarginTop: '100px'}} />

  **User Object:**

  | Parameter      | Type    | Description                                 | Sample Value                                                            |
  | -------------- | ------- | ------------------------------------------- | ----------------------------------------------------------------------- |
  | `uid`          | string  | Unique identifier of the user               | `"cometchat-uid-6"`                                                     |
  | `name`         | string  | Display name of the user                    | `"Ronald Jerry"`                                                        |
  | `avatar`       | string  | URL to user's avatar image                  | `"https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-6.webp"` |
  | `id`           | string  | Internal session participant ID             | `"cd530243"`                                                            |
  | `joinedAt`     | string  | Unix timestamp when user joined (as string) | `"1772095303043"`                                                       |
  | `isVideoMuted` | boolean | Whether user's video was muted              | `true`                                                                  |
  | `isAudioMuted` | boolean | Whether user's audio was muted              | `false`                                                                 |
</Accordion>

<Accordion title="onUserListUpdated Response">
  **On Event** — `onUserListUpdated` returns an array of all current participants in the call:

  <span id="on-user-list-updated-array" style={{scrollMarginTop: '100px'}} />

  **User Array:**

  | Parameter | Type  | Description           | Sample Value                                     |
  | --------- | ----- | --------------------- | ------------------------------------------------ |
  | (array)   | array | Array of user objects | [See below ↓](#on-user-list-updated-user-object) |

  <span id="on-user-list-updated-user-object" style={{scrollMarginTop: '100px'}} />

  **User Object (each item in array):**

  | Parameter | Type   | Description                   | Sample Value                                                            |
  | --------- | ------ | ----------------------------- | ----------------------------------------------------------------------- |
  | `uid`     | string | Unique identifier of the user | `"cometchat-uid-7"`                                                     |
  | `name`    | string | Display name of the user      | `"Henry Marino"`                                                        |
  | `avatar`  | string | URL to user's avatar image    | `"https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-7.webp"` |
</Accordion>

<Accordion title="onAudioModesUpdated Response">
  **On Event** — `onAudioModesUpdated` returns an array of available audio output modes:

  <span id="on-audio-modes-updated-array" style={{scrollMarginTop: '100px'}} />

  **Audio Modes Array:**

  | Parameter | Type  | Description                 | Sample Value                                       |
  | --------- | ----- | --------------------------- | -------------------------------------------------- |
  | (array)   | array | Array of audio mode objects | [See below ↓](#on-audio-modes-updated-mode-object) |

  <span id="on-audio-modes-updated-mode-object" style={{scrollMarginTop: '100px'}} />

  **Audio Mode Object (each item in array):**

  | Parameter  | Type    | Description                             | Sample Value |
  | ---------- | ------- | --------------------------------------- | ------------ |
  | `type`     | string  | Type of audio output device             | `"SPEAKER"`  |
  | `selected` | boolean | Whether this mode is currently selected | `true`       |
</Accordion>

<Accordion title="onCallSwitchedToVideo Response">
  **On Event** — `onCallSwitchedToVideo` is invoked when an audio call is upgraded to video. This event may not include additional data.
</Accordion>

## End Call Session

To end the call session and release all media resources (camera, microphone, network connections), call `CometChatCalls.endSession()` in the `onCallEndButtonPressed()` callback.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    onCallEndButtonPressed: () => {
      CometChatCalls.endSession();
      // Close the calling screen
    }
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    onCallEndButtonPressed: () => {
      CometChatCalls.endSession();
      // Close the calling screen
    }
    ```
  </Tab>
</Tabs>

## Methods

These methods are available for performing custom actions during an active call session. Use them to build custom UI controls or implement specific behaviors based on your use case.

<Note>
  These methods can only be called when a call session is active.
</Note>

### Switch Camera

Toggles between the front and rear camera during a video call. Useful for allowing users to switch their camera view without leaving the call.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.switchCamera();
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.switchCamera();
    ```
  </Tab>
</Tabs>

### Mute Audio

Controls the local audio stream transmission. When muted, other participants cannot hear the local user.

* `true` — Mutes the microphone, stops transmitting audio
* `false` — Unmutes the microphone, resumes audio transmission

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.muteAudio(true);
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.muteAudio(true);
    ```
  </Tab>
</Tabs>

### Pause Video

Controls the local video stream transmission. When paused, other participants see a frozen frame or avatar instead of live video.

* `true` — Pauses the camera, stops transmitting video
* `false` — Resumes the camera, continues video transmission

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.pauseVideo(true);
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.pauseVideo(true);
    ```
  </Tab>
</Tabs>

### Set Audio Mode

Routes the audio output to a specific device. Use this to let users choose between speaker, earpiece, or connected audio devices.

**Available modes:**

* `CometChat.AUDIO_MODE.SPEAKER` — Device speaker (loudspeaker)
* `CometChat.AUDIO_MODE.EARPIECE` — Phone earpiece
* `CometChat.AUDIO_MODE.BLUETOOTH` — Connected Bluetooth device
* `CometChat.AUDIO_MODE.HEADPHONES` — Wired headphones

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.setAudioMode(CometChat.AUDIO_MODE.EARPIECE);
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.setAudioMode(CometChat.AUDIO_MODE.EARPIECE);
    ```
  </Tab>
</Tabs>

### Switch To Video Call

Upgrades an ongoing audio call to a video call. This enables the camera and starts transmitting video to other participants. The remote participant receives the `onCallSwitchedToVideo()` callback.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.switchToVideoCall();
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.switchToVideoCall();
    ```
  </Tab>
</Tabs>

### Get Audio Output Modes

Returns the list of available audio output devices. Use this to display audio options to the user and then set the selected mode using `setAudioMode()`.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.getAudioOutputModes().then(
      (modes) => {
        console.log("Available audio modes:", modes);
        // Each mode has: mode (string) and isSelected (boolean)
      },
      (error) => {
        console.log("Failed to get audio modes:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.getAudioOutputModes().then(
      (modes: CometChat.AudioMode[]) => {
        console.log("Available audio modes:", modes);
        // Each mode has: mode (string) and isSelected (boolean)
      },
      (error: CometChat.CometChatException) => {
        console.log("Failed to get audio modes:", error);
      }
    );
    ```
  </Tab>
</Tabs>

<Accordion title="Response">
  **On Success** — `getAudioOutputModes()` returns an object containing an array of available audio modes:

  <span id="get-audio-modes-object" style={{scrollMarginTop: '100px'}} />

  **Response Object:**

  | Parameter | Type  | Description                           | Sample Value                                |
  | --------- | ----- | ------------------------------------- | ------------------------------------------- |
  | `modes`   | array | Array of available audio output modes | [See below ↓](#get-audio-modes-mode-object) |

  <span id="get-audio-modes-mode-object" style={{scrollMarginTop: '100px'}} />

  **Mode Object (each item in `modes` array):**

  | Parameter  | Type    | Description                             | Sample Value |
  | ---------- | ------- | --------------------------------------- | ------------ |
  | `type`     | string  | Type of audio output device             | `"SPEAKER"`  |
  | `selected` | boolean | Whether this mode is currently selected | `true`       |
</Accordion>

### End Call

Terminates the current call session and releases all media resources (camera, microphone, network connections). After calling this method, the call view should be closed.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    CometChatCalls.endSession();
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    CometChatCalls.endSession();
    ```
  </Tab>
</Tabs>

## Best Practices

<AccordionGroup>
  <Accordion title="Generate call tokens just before use">
    Call tokens are session-specific and time-limited. Generate them right before starting the call session rather than caching them for extended periods. This ensures the token is fresh and reduces the chance of token expiry errors.
  </Accordion>

  <Accordion title="Use a shared session ID for participants">
    All participants who need to join the same call must use the same `sessionId` when generating their call tokens. Share this ID through your backend or signaling mechanism so both parties can join the same session.
  </Accordion>

  <Accordion title="Secure your auth tokens">
    Since standalone calling uses REST API auth tokens instead of the Chat SDK login flow, ensure tokens are generated server-side and delivered securely to the client. Never hardcode auth tokens in your app bundle.
  </Accordion>

  <Accordion title="Clean up listeners on component unmount">
    Always remove call event listeners in your component's cleanup function (e.g., the return function of `useEffect`). Orphaned listeners can cause memory leaks, duplicate event handling, and unexpected behavior when navigating between screens.
  </Accordion>

  <Accordion title="Wrap the call component in a full-screen container">
    The `CometChatCalls.Component` should be rendered inside a `View` with `height: '100%'`, `width: '100%'`, and `position: 'relative'`. This ensures the call UI fills the screen correctly and overlays render in the right position.
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Call token generation fails">
    Verify the auth token is valid and hasn't expired. Auth tokens obtained from the REST API or Dashboard have an expiry — generate a fresh one if needed. Also confirm the `sessionId` is a non-empty string.
  </Accordion>

  <Accordion title="Call UI does not render">
    Ensure the `CometChatCalls.Component` is wrapped in a `View` with explicit dimensions (`height: '100%'`, `width: '100%'`). Also confirm that both `callSettings` and `callToken` props are provided and not `null` or `undefined`.
  </Accordion>

  <Accordion title="Participants can't join the same call">
    Both participants must use the exact same `sessionId` when generating their call tokens. Double-check that the session ID is being shared correctly between devices.
  </Accordion>

  <Accordion title="Listeners not firing">
    Check that the listener is registered before the call session starts. If using `addCallEventListener`, ensure the `listenerId` is unique and hasn't been overwritten by another registration. Also verify that the Calls SDK has been initialized via `CometChatCalls.init()`.
  </Accordion>

  <Accordion title="Audio or video not working after call starts">
    Check device permissions for camera and microphone. On React Native, request `CAMERA` and `RECORD_AUDIO` permissions on Android, and add `NSCameraUsageDescription` and `NSMicrophoneUsageDescription` to `Info.plist` on iOS.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Calls SDK Setup" icon="gear" href="/sdk/react-native/calling-setup">
    Install dependencies, configure permissions, and initialize the Calls SDK
  </Card>

  <Card title="Recording" icon="circle-dot" href="/sdk/react-native/recording">
    Record call sessions for playback and compliance
  </Card>

  <Card title="Video View Customisation" icon="sliders" href="/sdk/react-native/video-view-customisation">
    Customize the main video container and participant tiles
  </Card>

  <Card title="Call Session" icon="video" href="/sdk/react-native/direct-call">
    Full call session management with the Chat SDK integration
  </Card>
</CardGroup>
