Skip to main content
Quick Reference for AI Agents & Developers
// Install: npm install @cometchat/calls-sdk-javascript

// Initialize Calls SDK (after Chat SDK init)
const callSettings = new CometChatCalls.CallAppSettingsBuilder()
  .setAppId(APP_ID)
  .setRegion(REGION)
  .build();
await CometChatCalls.init(callSettings);

// Initiate a call
const call = new CometChat.Call(
  "receiver_uid",
  CometChat.CALL_TYPE.VIDEO,  // or AUDIO
  CometChat.RECEIVER_TYPE.USER  // or GROUP
);
const outgoingCall = await CometChat.initiateCall(call);

// Accept incoming call
const acceptedCall = await CometChat.acceptCall(sessionId);

// Reject/Cancel call
await CometChat.rejectCall(sessionId, CometChat.CALL_STATUS.REJECTED);

// End call
CometChatCalls.endSession();
await CometChat.endCall(sessionId);

// Listen for calls
CometChat.addCallListener("CALL_LISTENER", new CometChat.CallListener({
  onIncomingCallReceived: (call) => { /* show incoming UI */ },
  onOutgoingCallAccepted: (call) => { /* start session */ },
  onOutgoingCallRejected: (call) => { /* hide call UI */ },
  onIncomingCallCancelled: (call) => { /* hide incoming UI */ }
}));
CometChat provides real-time voice and video calling capabilities for your web application. Build 1:1 calls, group calls, screen sharing, and more.
Available via: SDK | UI Kits

How Calling Works

CometChat calling uses two SDKs working together:
SDKPurposeRequired
Chat SDKCall signaling (initiate, accept, reject, end)Yes
Calls SDKMedia handling (audio, video, screen share)Yes
The Chat SDK handles the “phone ringing” part, while the Calls SDK handles the actual audio/video streams.

Prerequisites

1

Chat SDK Installed

Complete the Setup Guide first.
2

Install Calls SDK

npm install @cometchat/calls-sdk-javascript
3

Initialize Calls SDK

Initialize after the Chat SDK is ready:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatCalls } from "@cometchat/calls-sdk-javascript";

// After CometChat.init() succeeds
const callAppSettings = new CometChatCalls.CallAppSettingsBuilder()
  .setAppId(APP_ID)
  .setRegion(REGION)
  .build();

CometChatCalls.init(callAppSettings).then(
  () => console.log("Calls SDK initialized"),
  (error) => console.log("Calls SDK init failed:", error)
);
For detailed setup, see the Calls SDK Setup Guide.

Choose Your Implementation

Which Should I Use?

Use CaseRecommended Approach
Standard app with chat + callingRinging Flow
Video conferencing / scheduled callsDirect Call
Calling without chat featuresStandalone
Custom call UI with own notificationsDirect Call

Quick Start: Ringing Flow

Here’s a complete example of implementing voice/video calls with the ringing flow:
import { CometChat } from "@cometchat/chat-sdk-javascript";

// Initiate a video call to a user
async function startCall(receiverUID, callType = CometChat.CALL_TYPE.VIDEO) {
  const call = new CometChat.Call(
    receiverUID,
    callType,
    CometChat.RECEIVER_TYPE.USER
  );

  try {
    const outgoingCall = await CometChat.initiateCall(call);
    console.log("Call initiated:", outgoingCall);
    // Show outgoing call UI
    return outgoingCall;
  } catch (error) {
    console.error("Call initiation failed:", error);
    throw error;
  }
}

// Start a video call
startCall("user123", CometChat.CALL_TYPE.VIDEO);

// Start an audio call
startCall("user123", CometChat.CALL_TYPE.AUDIO);

Call Types

TypeConstantDescription
AudioCometChat.CALL_TYPE.AUDIOVoice-only call
VideoCometChat.CALL_TYPE.VIDEOVideo call with camera
Receiver TypeConstantDescription
UserCometChat.RECEIVER_TYPE.USER1:1 call
GroupCometChat.RECEIVER_TYPE.GROUPGroup call

Group Calls

Initiate a call to a group:
const groupCall = new CometChat.Call(
  "group-guid",
  CometChat.CALL_TYPE.VIDEO,
  CometChat.RECEIVER_TYPE.GROUP
);

CometChat.initiateCall(groupCall).then(
  (call) => console.log("Group call initiated:", call),
  (error) => console.log("Failed:", error)
);
In group calls, all online members receive the incoming call notification. The call continues as long as at least one participant remains.

Call Status Constants

StatusConstantDescription
InitiatedCometChat.CALL_STATUS.INITIATEDCall started, waiting for response
OngoingCometChat.CALL_STATUS.ONGOINGCall in progress
UnansweredCometChat.CALL_STATUS.UNANSWEREDNo answer (timeout)
RejectedCometChat.CALL_STATUS.REJECTEDReceiver rejected
BusyCometChat.CALL_STATUS.BUSYReceiver is on another call
CancelledCometChat.CALL_STATUS.CANCELLEDCaller cancelled
EndedCometChat.CALL_STATUS.ENDEDCall ended normally

Features


Call Listener Events

EventDescription
onIncomingCallReceivedSomeone is calling you
onOutgoingCallAcceptedYour call was accepted
onOutgoingCallRejectedYour call was rejected
onIncomingCallCancelledCaller cancelled before you answered
onCallEndedMessageReceivedCall ended
CometChat.addCallListener(
  "CALL_LISTENER",
  new CometChat.CallListener({
    onIncomingCallReceived: (call) => {
      // Show incoming call UI
    },
    onOutgoingCallAccepted: (call) => {
      // Start call session
    },
    onOutgoingCallRejected: (call) => {
      // Show "call rejected" message
    },
    onIncomingCallCancelled: (call) => {
      // Hide incoming call UI
    },
    onCallEndedMessageReceived: (call) => {
      // Clean up call UI
    }
  })
);

End a Call

import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatCalls } from "@cometchat/calls-sdk-javascript";

async function endCall(sessionId) {
  try {
    // End the call session
    CometChatCalls.endSession();
    
    // Notify CometChat
    await CometChat.endCall(sessionId);
    console.log("Call ended successfully");
  } catch (error) {
    console.error("End call failed:", error);
  }
}

React Implementation Example

import { useEffect, useState, useCallback } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatCalls } from "@cometchat/calls-sdk-javascript";

export function useCall() {
  const [incomingCall, setIncomingCall] = useState(null);
  const [activeCall, setActiveCall] = useState(null);

  useEffect(() => {
    const listenerID = "CALL_LISTENER";

    CometChat.addCallListener(
      listenerID,
      new CometChat.CallListener({
        onIncomingCallReceived: (call) => {
          setIncomingCall(call);
        },
        onOutgoingCallAccepted: (call) => {
          setActiveCall(call);
          setIncomingCall(null);
        },
        onOutgoingCallRejected: () => {
          setActiveCall(null);
        },
        onIncomingCallCancelled: () => {
          setIncomingCall(null);
        },
        onCallEndedMessageReceived: () => {
          setActiveCall(null);
          setIncomingCall(null);
        }
      })
    );

    return () => {
      CometChat.removeCallListener(listenerID);
    };
  }, []);

  const initiateCall = useCallback(async (receiverUID, callType) => {
    const call = new CometChat.Call(
      receiverUID,
      callType,
      CometChat.RECEIVER_TYPE.USER
    );
    const outgoingCall = await CometChat.initiateCall(call);
    setActiveCall(outgoingCall);
    return outgoingCall;
  }, []);

  const acceptCall = useCallback(async () => {
    if (!incomingCall) return;
    const call = await CometChat.acceptCall(incomingCall.getSessionId());
    setActiveCall(call);
    setIncomingCall(null);
    return call;
  }, [incomingCall]);

  const rejectCall = useCallback(async () => {
    if (!incomingCall) return;
    await CometChat.rejectCall(
      incomingCall.getSessionId(),
      CometChat.CALL_STATUS.REJECTED
    );
    setIncomingCall(null);
  }, [incomingCall]);

  const endCall = useCallback(async () => {
    if (!activeCall) return;
    CometChatCalls.endSession();
    await CometChat.endCall(activeCall.getSessionId());
    setActiveCall(null);
  }, [activeCall]);

  return {
    incomingCall,
    activeCall,
    initiateCall,
    acceptCall,
    rejectCall,
    endCall
  };
}

Best Practices

Request camera and microphone permissions before initiating calls. Handle permission denied gracefully.
async function checkPermissions() {
  try {
    await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
    return true;
  } catch (error) {
    console.error("Permission denied:", error);
    return false;
  }
}
Always remove call listeners when components unmount to prevent memory leaks and duplicate events.
Implement reconnection logic and show appropriate UI when network quality degrades.
Test calling on different browsers and devices. WebRTC behavior can vary.

Troubleshooting

  • Verify both Chat SDK and Calls SDK are initialized
  • Check that both users are logged in
  • Ensure call listeners are registered before initiating calls
  • Check browser permissions for camera/microphone
  • Verify the call type matches expected media (audio vs video)
  • Test with navigator.mediaDevices.getUserMedia() directly
  • Ensure startSession() is called after call is accepted
  • Verify the auth token is valid
  • Check for errors in the call listener

Next Steps