> ## Documentation Index
> Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ringing

> CometChat Calling SDK v4 - Stable Release - Ringing for JavaScript

## Overview

This section explains how to implement a complete calling workflow with ringing functionality, including incoming/outgoing call UI, call acceptance, rejection, and cancellation. Previously known as **Default Calling**.

<Note>
  After the call is accepted, you need to start the call session. See the [Call Session](/calls/v4/javascript/call-session#start-call-session) guide for details on starting and managing the actual call.
</Note>

**Call Flow:**

1. **Caller** initiates a call using `initiateCall()`
2. **Receiver** gets notified via `onIncomingCallReceived()` callback
3. **Receiver** can either:
   * Accept the call using `acceptCall()`
   * Reject the call using `rejectCall()` with status `CALL_STATUS_REJECTED`
4. **Caller** can cancel the call using `rejectCall()` with status `CALL_STATUS_CANCELLED`
5. Once accepted, both participants call `startSession()` to join the call

## Initiate Call

The `initiateCall()` method sends a call request to a user or a group. On success, the receiver gets an `onIncomingCallReceived()` callback.

<Tabs>
  <Tab title="User Call (JavaScript)">
    ```javascript theme={null}
    const receiverID = "UID";
    const callType = CometChat.CALL_TYPE.VIDEO;
    const receiverType = CometChat.RECEIVER_TYPE.USER;

    const call = new CometChat.Call(receiverID, callType, receiverType);

    CometChat.initiateCall(call).then(
      (outgoingCall) => {
        console.log("Call initiated:", outgoingCall);
        // Show outgoing call UI
        // Store outgoingCall.getSessionId() for later use
      },
      (error) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="Group Call (JavaScript)">
    ```javascript theme={null}
    const receiverID = "GUID";
    const callType = CometChat.CALL_TYPE.VIDEO;
    const receiverType = CometChat.RECEIVER_TYPE.GROUP;

    const call = new CometChat.Call(receiverID, callType, receiverType);

    CometChat.initiateCall(call).then(
      (outgoingCall) => {
        console.log("Call initiated:", outgoingCall);
        // Show outgoing call UI
      },
      (error) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="User Call (TypeScript)">
    ```typescript theme={null}
    const receiverID: string = "UID";
    const callType: string = CometChat.CALL_TYPE.VIDEO;
    const receiverType: string = CometChat.RECEIVER_TYPE.USER;

    const call: CometChat.Call = new CometChat.Call(receiverID, callType, receiverType);

    CometChat.initiateCall(call).then(
      (outgoingCall: CometChat.Call) => {
        console.log("Call initiated:", outgoingCall);
      },
      (error: CometChat.CometChatException) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="Group Call (TypeScript)">
    ```typescript theme={null}
    const receiverID: string = "GUID";
    const callType: string = CometChat.CALL_TYPE.VIDEO;
    const receiverType: string = CometChat.RECEIVER_TYPE.GROUP;

    const call: CometChat.Call = new CometChat.Call(receiverID, callType, receiverType);

    CometChat.initiateCall(call).then(
      (outgoingCall: CometChat.Call) => {
        console.log("Call initiated:", outgoingCall);
      },
      (error: CometChat.CometChatException) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

| Parameter      | Description                                                       |
| -------------- | ----------------------------------------------------------------- |
| `receiverID`   | The UID or GUID of the recipient                                  |
| `receiverType` | `CometChat.RECEIVER_TYPE.USER` or `CometChat.RECEIVER_TYPE.GROUP` |
| `callType`     | `CometChat.CALL_TYPE.AUDIO` or `CometChat.CALL_TYPE.VIDEO`        |

On success, a `Call` object is returned containing the call details including a unique `sessionId` required for starting the call session.

By default, an unanswered call automatically cancels after 45 seconds. You can customize this duration by passing an optional `timeout` parameter (in seconds) as the second argument to `initiateCall()`.

<Tabs>
  <Tab title="User Call (JavaScript)">
    ```javascript theme={null}
    const receiverID = "UID";
    const callType = CometChat.CALL_TYPE.VIDEO;
    const receiverType = CometChat.RECEIVER_TYPE.USER;

    const call = new CometChat.Call(receiverID, callType, receiverType);

    // Set a custom timeout of 60 seconds
    CometChat.initiateCall(call, 60).then(
      (outgoingCall) => {
        console.log("Call initiated with 60s timeout:", outgoingCall);
      },
      (error) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="Group Call (JavaScript)">
    ```javascript theme={null}
    const receiverID = "GUID";
    const callType = CometChat.CALL_TYPE.VIDEO;
    const receiverType = CometChat.RECEIVER_TYPE.GROUP;

    const call = new CometChat.Call(receiverID, callType, receiverType);

    // Set a custom timeout of 60 seconds
    CometChat.initiateCall(call, 60).then(
      (outgoingCall) => {
        console.log("Call initiated with 60s timeout:", outgoingCall);
      },
      (error) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="User Call (TypeScript)">
    ```typescript theme={null}
    const receiverID: string = "UID";
    const callType: string = CometChat.CALL_TYPE.VIDEO;
    const receiverType: string = CometChat.RECEIVER_TYPE.USER;

    const call: CometChat.Call = new CometChat.Call(receiverID, callType, receiverType);

    // Set a custom timeout of 60 seconds
    CometChat.initiateCall(call, 60).then(
      (outgoingCall: CometChat.Call) => {
        console.log("Call initiated with 60s timeout:", outgoingCall);
      },
      (error: CometChat.CometChatException) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="Group Call (TypeScript)">
    ```typescript theme={null}
    const receiverID: string = "GUID";
    const callType: string = CometChat.CALL_TYPE.VIDEO;
    const receiverType: string = CometChat.RECEIVER_TYPE.GROUP;

    const call: CometChat.Call = new CometChat.Call(receiverID, callType, receiverType);

    // Set a custom timeout of 60 seconds
    CometChat.initiateCall(call, 60).then(
      (outgoingCall: CometChat.Call) => {
        console.log("Call initiated with 60s timeout:", outgoingCall);
      },
      (error: CometChat.CometChatException) => {
        console.log("Call initiation failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

| Parameter | Type     | Description                                                                                                    |
| --------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `call`    | `Call`   | The call object created with receiver ID, call type, and receiver type.                                        |
| `timeout` | `number` | Optional. The ringing duration in seconds before an unanswered call is automatically cancelled. Default: `45`. |

## Call Listeners

Register the `CallListener` to receive real-time call events. Each listener requires a unique `listenerId` string to prevent duplicate registrations and enable targeted removal.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const listenerId = "UNIQUE_LISTENER_ID";

    // Register listener
    CometChat.addCallListener(
      listenerId,
      new CometChat.CallListener({
        onIncomingCallReceived: (call) => {
          console.log("Incoming call:", call);
          // Show incoming call UI
        },
        onOutgoingCallAccepted: (call) => {
          console.log("Outgoing call accepted:", call);
          // Receiver accepted, start the call session
        },
        onOutgoingCallRejected: (call) => {
          console.log("Outgoing call rejected:", call);
          // Receiver rejected, dismiss outgoing call UI
        },
        onIncomingCallCancelled: (call) => {
          console.log("Incoming call cancelled:", call);
          // Caller cancelled, dismiss incoming call UI
        },
        onCallEndedMessageReceived: (call) => {
          console.log("Call ended message:", call);
          // Call ended by remote participant
        }
      })
    );

    // Unregister listener when done
    CometChat.removeCallListener(listenerId);
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const listenerId: string = "UNIQUE_LISTENER_ID";

    // Register listener
    CometChat.addCallListener(
      listenerId,
      new CometChat.CallListener({
        onIncomingCallReceived: (call: CometChat.Call) => {
          console.log("Incoming call:", call);
        },
        onOutgoingCallAccepted: (call: CometChat.Call) => {
          console.log("Outgoing call accepted:", call);
        },
        onOutgoingCallRejected: (call: CometChat.Call) => {
          console.log("Outgoing call rejected:", call);
        },
        onIncomingCallCancelled: (call: CometChat.Call) => {
          console.log("Incoming call cancelled:", call);
        },
        onCallEndedMessageReceived: (call: CometChat.Call) => {
          console.log("Call ended message:", call);
        }
      })
    );

    // Unregister listener when done
    CometChat.removeCallListener(listenerId);
    ```
  </Tab>
</Tabs>

### Events

| Event                              | Description                                                                                                                              |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `onIncomingCallReceived(call)`     | Invoked when an incoming call is received. The `call` contains caller details, session ID, and call type. Display incoming call UI here. |
| `onOutgoingCallAccepted(call)`     | Invoked on the caller's device when the receiver accepts. Generate call token and start the session here.                                |
| `onOutgoingCallRejected(call)`     | Invoked on the caller's device when the receiver rejects the call. Dismiss outgoing call UI here.                                        |
| `onIncomingCallCancelled(call)`    | Invoked on the receiver's device when the caller cancels before answering. Dismiss incoming call UI here.                                |
| `onCallEndedMessageReceived(call)` | Invoked when a call ends. The `call` contains final status and duration. Update call history here.                                       |

## Accept Call

When an incoming call is received via `onIncomingCallReceived()`, use `acceptCall()` to accept it. On success, start the call session.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const sessionId = call.getSessionId(); // From onIncomingCallReceived

    CometChat.acceptCall(sessionId).then(
      (call) => {
        console.log("Call accepted:", call);
        // Call accepted, now start the call session
        // Generate token and call startSession()
      },
      (error) => {
        console.log("Accept call failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sessionId: string = call.getSessionId(); // From onIncomingCallReceived

    CometChat.acceptCall(sessionId).then(
      (call: CometChat.Call) => {
        console.log("Call accepted:", call);
      },
      (error: CometChat.CometChatException) => {
        console.log("Accept call failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

## Reject Call

Use `rejectCall()` to reject an incoming call. Set the status to `CALL_STATUS_REJECTED`.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const sessionId = call.getSessionId();
    const status = CometChat.CALL_STATUS.REJECTED;

    CometChat.rejectCall(sessionId, status).then(
      (call) => {
        console.log("Call rejected:", call);
        // Dismiss incoming call UI
      },
      (error) => {
        console.log("Reject call failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sessionId: string = call.getSessionId();
    const status: string = CometChat.CALL_STATUS.REJECTED;

    CometChat.rejectCall(sessionId, status).then(
      (call: CometChat.Call) => {
        console.log("Call rejected:", call);
      },
      (error: CometChat.CometChatException) => {
        console.log("Reject call failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

## Cancel Call

The caller can cancel an outgoing call before it's answered using `rejectCall()` with status `CALL_STATUS_CANCELLED`.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const sessionId = call.getSessionId();
    const status = CometChat.CALL_STATUS.CANCELLED;

    CometChat.rejectCall(sessionId, status).then(
      (call) => {
        console.log("Call cancelled:", call);
        // Dismiss outgoing call UI
      },
      (error) => {
        console.log("Cancel call failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sessionId: string = call.getSessionId();
    const status: string = CometChat.CALL_STATUS.CANCELLED;

    CometChat.rejectCall(sessionId, status).then(
      (call: CometChat.Call) => {
        console.log("Call cancelled:", call);
      },
      (error: CometChat.CometChatException) => {
        console.log("Cancel call failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

## Start Call Session

Once the call is accepted, both participants need to start the call session.

**Caller flow:** In the `onOutgoingCallAccepted()` callback, generate a token and start the session.

**Receiver flow:** In the `acceptCall()` success callback, generate a token and start the session.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const sessionId = call.getSessionId();
    const loggedInUser = await CometChat.getLoggedinUser();
    const authToken = loggedInUser.getAuthToken();

    // Step 1: Generate call token
    CometChatCalls.generateToken(sessionId, authToken).then(
      (callToken) => {
        // Step 2: Configure call settings
        const callListener = new CometChatCalls.OngoingCallListener({
          onCallEnded: () => {
            CometChat.clearActiveCall();
            CometChatCalls.endSession();
            // Close calling screen
          },
          onCallEndButtonPressed: () => {
            CometChat.endCall(sessionId).then(
              () => {
                CometChat.clearActiveCall();
                CometChatCalls.endSession();
                // Close calling screen
              },
              (error) => console.log("End call failed:", error)
            );
          },
          onUserJoined: (user) => console.log("User joined:", user),
          onUserLeft: (user) => console.log("User left:", user),
          onError: (error) => console.log("Call error:", error)
        });

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

        // Step 3: Start the session
        const htmlElement = document.getElementById("call-container");
        CometChatCalls.startSession(callToken, callSettings, htmlElement);
      },
      (error) => {
        console.log("Token generation failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sessionId: string = call.getSessionId();
    const loggedInUser = await CometChat.getLoggedinUser();
    const authToken: string = loggedInUser.getAuthToken();

    // Step 1: Generate call token
    CometChatCalls.generateToken(sessionId, authToken).then(
      (callToken: any) => {
        // Step 2: Configure call settings
        const callListener = new CometChatCalls.OngoingCallListener({
          onCallEnded: () => {
            CometChat.clearActiveCall();
            CometChatCalls.endSession();
            // Close calling screen
          },
          onCallEndButtonPressed: () => {
            CometChat.endCall(sessionId).then(
              () => {
                CometChat.clearActiveCall();
                CometChatCalls.endSession();
                // Close calling screen
              },
              (error: CometChat.CometChatException) => console.log("End call failed:", error)
            );
          },
          onUserJoined: (user: any) => console.log("User joined:", user),
          onUserLeft: (user: any) => console.log("User left:", user),
          onError: (error: any) => console.log("Call error:", error)
        });

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

        // Step 3: Start the session
        const htmlElement = document.getElementById("call-container") as HTMLElement;
        CometChatCalls.startSession(callToken, callSettings, htmlElement);
      },
      (error: CometChat.CometChatException) => {
        console.log("Token generation failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>

For more details on call settings and customization, see the [Call Session](/calls/v4/javascript/call-session#start-call-session) guide.

## End Call

To end an active call in the ringing flow, the process differs based on who ends the call.

**User who ends the call:**

When the user clicks the end call button, the `onCallEndButtonPressed()` callback is triggered. Inside this callback, call `CometChat.endCall()` to notify other participants. On success, call `CometChat.clearActiveCall()` and `CometChatCalls.endSession()` to release resources.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    onCallEndButtonPressed: () => {
      CometChat.endCall(sessionId).then(
        (call) => {
          console.log("Call ended successfully");
          CometChat.clearActiveCall();
          CometChatCalls.endSession();
          // Close the calling screen
        },
        (error) => {
          console.log("End call failed:", error);
        }
      );
    }
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    onCallEndButtonPressed: () => {
      CometChat.endCall(sessionId).then(
        (call: CometChat.Call) => {
          console.log("Call ended successfully");
          CometChat.clearActiveCall();
          CometChatCalls.endSession();
          // Close the calling screen
        },
        (error: CometChat.CometChatException) => {
          console.log("End call failed:", error);
        }
      );
    }
    ```
  </Tab>
</Tabs>

**Remote participant** (receives `onCallEnded()` callback):

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

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

For more details, see the [End Call Session](/calls/v4/javascript/call-session#end-call-session) guide.

## Busy Call Handling

If the receiver is already on another call, you can reject the incoming call with `CALL_STATUS_BUSY` status.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const sessionId = call.getSessionId();
    const status = CometChat.CALL_STATUS.BUSY;

    CometChat.rejectCall(sessionId, status).then(
      (call) => {
        console.log("Busy status sent:", call);
      },
      (error) => {
        console.log("Busy rejection failed:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sessionId: string = call.getSessionId();
    const status: string = CometChat.CALL_STATUS.BUSY;

    CometChat.rejectCall(sessionId, status).then(
      (call: CometChat.Call) => {
        console.log("Busy status sent:", call);
      },
      (error: CometChat.CometChatException) => {
        console.log("Busy rejection failed:", error);
      }
    );
    ```
  </Tab>
</Tabs>
