# Chat & Messaging Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-call Add real-time chat, voice & video calling to your apps in minutes. Choose your path: UI Kits, SDKs, or Widgets. {/* Hero Section */}

Chat & Calling

Add real-time chat and calls to your app in minutes. Choose the approach that fits your needs.

Chat & Messaging UI Preview

Step 1

Add CometChat to Your Frontend

Use our pre-built UI kits or SDKs to add chat to your website or mobile app instantly.

{/* Chat Builder Section */}

UI Kits - Chat Builder

   RECOMMENDED

Get a fully functional chat interface in minutes. Configure via our chat builder—no complex setup required.

{/* */} Toggle mentions, reactions, media sharing, and more through our visual interface. Get production-ready React code that plugs directly into your existing app. It's based on our UI Kits—edit layouts, styles, or workflows as needed. No manual component wiring required. User/group info, moderation, and more included by default. Same powerful UI Kits under the hood. } href="/chat-builder/react/overview" horizontal /> } href="/chat-builder/nextjs/overview" horizontal /> } href="/chat-builder/react-router/overview" horizontal /> } href="/chat-builder/ios/overview" horizontal /> {/* } href="/chat-builder/android/overview" horizontal /> */} } href="/chat-builder/android/overview" horizontal /> {/* } href="/ui-kit/react-native/overview" horizontal /> } href="/ui-kit/flutter/overview" horizontal /> */}
{/* UI Kits Section */}

UI Kits - Components

Build your own chat interface using individual components. Each component includes built-in chat logic.

{/* */} Choose only what you need from the comprehensive UI Kit. Compose your desired layout; apply custom styling or theming. Each component includes its own chat logic—no SDK wiring per part. No manual component wiring required. User/group info, moderation, and more included by default. Same powerful UI Kits under the hood. } href="/ui-kit/react/react-js-integration" horizontal /> } href="/ui-kit/react/next-js-integration" horizontal /> } href="/ui-kit/react/react-router-integration" horizontal /> } href="/ui-kit/angular/overview" horizontal /> } href="/ui-kit/vue/overview" horizontal /> } href="/ui-kit/ios/overview" horizontal /> } href="/ui-kit/android/overview" horizontal /> } href="/ui-kit/android/overview" horizontal /> } href="/ui-kit/react-native/overview" horizontal /> } href="/ui-kit/flutter/overview" horizontal />
{/* SDKs Section */}

SDKs

Build your own UI from scratch with our complete SDK feature set.

{/* */} Initialize and connect to CometChat in your frontend application. Create UI and flows from the ground up—exactly how you want them. Full control over every aspect of the chat experience. Live in minutes, not days. No framework lock‑in or build steps. Configure without code; theme when needed. } href="/sdk/javascript/overview" horizontal /> } href="/sdk/react-native/overview" horizontal /> } href="/sdk/ios/overview" horizontal /> } href="/sdk/android/overview" horizontal /> } href="/sdk/flutter/overview" horizontal /> } href="/sdk/ionic/overview" horizontal />
{/* Widgets Section */}

Chat Widgets

Add chat to any website with a simple script tag. Perfect for customer support and community chat.

{/* */} Paste a single script into your site or CMS. Toggle features, colors, and behavior from CometChat. The widget appears instantly across your pages. Live in minutes, not days. No framework lock‑in or build steps. Configure without code; theme when needed. } href="/widget/html/integration" horizontal /> } href="/widget/wordpress/integration" horizontal /> } href="/widget/squarespace/integration" horizontal /> } href="/widget/wix/integration" horizontal /> } href="/widget/webflow/integration" horizontal />

Step 2

Sync Your Users

Sync your user database with CometChat for a seamless experience.

  • Add users directly from the CometChat Dashboard.
  • Ideal for quick testing or small teams.
  • Create users via the SDK methods.
  • Perfect for auto-provisioning during sign-up or login.
  • Create users using the REST API.
  • Best for batch imports or admin workflows.
{/* Sample Apps Section */}

Sample Apps & Demos

See CometChat in action. Clone these sample apps to get started quickly.

{/* Footer */}
2025 © CometChat
LinkedIn Twitter GitHub
# Conversation Starter Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/ai-user-copilot/conversation-starter **Conversation Starter** enables you to retrieve an initial message in a new conversation, often used to set the context for the conversation that is about to begin. This can be particularly useful for guiding users on how to interact within the chat or for delivering automated messages that engage users when they initiate a chat. ## Before you begin 1. Set up the AI settings through the CometChat dashboard as detailed in the [Overview section](/fundamentals/ai-user-copilot/overview). 2. Navigate to Chat > Features, under **AI User Copilot**, enable **Conversation Starter**. 3. Implement the chat functionality in your applications using [CometChat's **v4** Chat SDKs](/sdk/javascript/overview). ## How does it work? CometChat AI analyzes the user's tone and writing style by reviewing recent messages sent by that user within the application. The SDK includes a method for retrieving conversation starters in a chat. This method returns an array containing three potential starters for the conversation. The number of messages to be fetched to generate relevant conversation starter is configurable. By default the CometChat AI takes the latest `1000` messages. This can be configured to specific timestamps as well. | Configuration | Value | | ------------- | ------------------------------------------------------ | | lastNMessages | This will fetch specific number of messages. | | fromTimestamp | This will fetch messages from a particular timestamp. | | toTimestamp | This will fetch messages until a particular timestamp. | While using any configuration mentioned above a maximum of **only** `1000` messages will be fetched. ## Implementation ### SDKs To implement Conversation Starter in the platform of your choice, you may utilize the following code samples: ```js const receiverId = 'UID/GUID'; const receiverType = 'user/group'; const configuration = {lastNMessages: 100}; CometChat.getConversationStarter(receiverId, receiverType, configuration).then( (conversation-starter) => { console.log("Conversation Starter", conversation-starter); }, (error) => { console.log("An error occurred while fetching conversation starter", error); } ); ``` ```java String receiveId = ""; String receiverType = CometChatConstants.RECEIVER_TYPE_USER; JSONObject configuration = new JSONObject(); try { configuration.put("lastNMessages", 100); } catch (JSONException e) { throw new RuntimeException(e); } CometChat.getConversationStarter(receiveId, receiverType, configuration, new CometChat.CallbackListener>() { @Override public void onSuccess(List strings) { Log.e(TAG, strings.toString()); } @Override public void onError(CometChatException e) { Log.e(TAG, e.getMessage()); } }); ``` ```kotlin val receiveId = "" val receiverType: String = CometChatConstants.RECEIVER_TYPE_USER val configuration = JSONObject() try { configuration.put("lastNMessages", 100) } catch (e: JSONException) { throw RuntimeException(e) } CometChat.getConversationStarter( receiveId, receiverType, configuration, object : CallbackListener?>() { fun onSuccess(strings: List) { Log.e(SplashActivity.TAG, strings.toString()) } override fun onError(e: CometChatException) { Log.e(SplashActivity.TAG, e.getMessage()) } } ) ``` ```dart String receiveId = ""; String receiverType = CometChatConversationType.user; Map configuration = { "lastNMessages": 100 }; CometChat.getConversationStarter("cometchat-uid-2", "user", configuration: configuration, onSuccess: (List starters) { debugPrint("getConversationStarter Sucess: $starters"); }, onError: (CometChatException e) { debugPrint("getConversationStarter Error: $e"); }); ``` ```swift let receiverId = "" let receiverType = CometChat.ReceiverType.group let configuration = [ "lastNMessages": 100 ] CometChat.getConversationStarter(receiverId: "cometchat-uid-1", receiverType: .user, configuration: configuration) { startersReplies in print("getConversationStarter success: \(startersReplies)") } onError: { error in print("getConversationStarter error: \(error?.errorDescription)") } ``` ### UI Kits Assuming the necessary prerequisites are met, Conversation Starter functions seamlessly starting from v4 of the Chat UI Kits. Similarly, Conversation Starter is triggered automatically when there are no messages in a conversation. # Conversation Summary Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/ai-user-copilot/conversation-summary **Conversation Summary** enables the summarization of conversations using AI. ## Before you begin 1. Set up the AI settings through the CometChat dashboard as detailed in the [Overview section](/fundamentals/ai-user-copilot/overview). 2. Navigate to Chat > Features, under **AI User Copilot**, enable **Conversation Summary**. 3. Implement the chat functionality in your applications using [CometChat's **v4** Chat SDKs](/sdk/javascript/overview). ## How does it work? CometChat AI goes through the messages of a conversation to understand the context of a conversation & provide a short summary of the conversation. The CometChat SDK has a method to fetch the conversation summary. It returns the conversation summary as a string. The number of messages to be fetched to generate relevant summaries is configurable. By default the CometChat AI takes the latest `1000` messages. This can be configured to specific timestamps as well. | Configuration | Value | | ------------- | ------------------------------------------------------ | | lastNMessages | This will fetch specific number of messages. | | fromTimestamp | This will fetch messages from a particular timestamp. | | toTimestamp | This will fetch messages until a particular timestamp. | | unreadOnly | This will fetch only the unread messages. | While using any configuration mentioned above a maximum of **only** `1000` messages will be fetched. ## Implementation ### SDKs To implement Conversation Summary in the platform of your choice, you may utilize the following code samples: ```js const receiverId = "UID/GUID"; const receiverType = "user/group"; const configuration = { lastNMessages: 100 }; CometChat.getConversationSummary(receiverId, receiverType, configuration).then( (conversationSummary) => { console.log("Conversation Summary:", conversationSummary); }, (error) => { console.log( "An error occurred while fetching conversation summary.", error ); } ); ``` ```java String receiverId = 'UID/GUID'; String receiverType = CometChatConstants.RECEIVER_TYPE_USER; //'user/group' JSONObject configuration = new JSONObject(); try { configuration.put("lastNMessages", 100); } catch (JSONException e) { throw new RuntimeException(e); } CometChat.getConversationSummary(receiverId, receiverType,c onfiguration, new CometChat.CallbackListener() { @Override public void onSuccess(String s) { Logger.error(TAG, s); } @Override public void onError(CometChatException e) { Logger.error(TAG, e.getMessage()); } }); ``` ```kotlin val receiverId = "UID/GUID" val receiverType = CometChatConstants.RECEIVER_TYPE_USER // 'user/group' val configuration = JSONObject() try { configuration.put("lastNMessages", 100) } catch (e: JSONException) { throw RuntimeException(e) } CometChat.getConversationSummary(receiverId, receiverType, configuration, object : CometChat.CallbackListener() { override fun onSuccess(s: String) { Log.e(TAG, s) } override fun onError(e: CometChatException) { Log.e(TAG, e.localizedMessage) } }) ``` ```swift let receiverId = "" let receiverType = CometChat.ReceiverType.group let configuration = [ "lastNMessages": 100 ] CometChat.getConversationSummary(receiverId: receiverId, receiverType: receiverType, configuration: configuration) { summary in print("getConversationSummary success: \(summary)") } onError: { error in print("getConversationSummary error: \(error?.errorDescription)") } ``` ```dart String receiveId = ""; String receiverType = CometChatConversationType.user; Map configuration = { "lastNMessages": 100 }; CometChat.getConversationSummary(receiveId, receiverType, configuration: configuration, onSuccess:(String summary) { debugPrint("getConversationSummary Success: $summary"); }, onError: (CometChatException e) { debugPrint("getConversationSummary error: $e"); }); ``` ### UI Kits Assuming the necessary prerequisites are met, Conversation Summary functions seamlessly starting from v4 of the Chat UI Kits. The placement of the AI icon may vary based on the version. Clicking on the icon will display the Conversation Summary. # AI User Copilot Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/ai-user-copilot/overview ## AI-Enabled Messaging Experience Picture a chat that effortlessly starts and flows, like catching up with your best buddy over a cup of coffee. With CometChat AI, we're making that a reality! Introducing **Conversation Starter** and **Smart Replies** that ignite natural and organic conversations. Say goodbye to awkward silences and hello to chat-filled adventures! For those who require a concise overview of their discussions, the **Conversation Summary** feature is available to provide a succinct recap. ## Pre-requisite * Login to your [CometChat dashboard](https://app.cometchat.com/login) and choose your app. * Navigate to **AI Chatbot** > **Settings** in the left-hand menu. ### Set the GPT Model Enter the name of the Open AI ChatGPT model that you intend to use. ### Save the Open AI Key You can get the Open AI Key from your [Open AI Account](https://platform.openai.com/account/api-keys). This will be used by CometChat to interact with the Open AI APIs. ### Set a Custom Instruction Custom Instruction is an information which gets added in each and every ChatGPT prompt made by the CometChat AI. Custom Instruction is app-level information you can add to describe your use-case & inform what kind of responses you need from the CometChat AI. ### Set the Temperature The API is non-deterministic by default. This means that you might get a slightly different completion every time you call it, even if your prompt stays the same. Setting temperature to 0 will make the outputs mostly deterministic, but a small amount of variability will remain. Lower values for temperature result in more consistent outputs, while higher values generate more diverse and creative results. Select a temperature value based on the desired trade-off between coherence and creativity for your specific application. ### Enable AI Toggle on AI. # Smart Replies Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/ai-user-copilot/smart-replies **Smart Replies** enable the retrieval of an AI-generated response message within a conversation. ## Before you begin 1. Configure the AI settings through the CometChat dashboard as detailed in the [Overview section](/fundamentals/ai-user-copilot/overview). 2. Navigate to Chat > Features, under **AI User Copilot**, enable **Smart Replies**. 3. Implement the chat functionality in your applications using [CometChat's **v4** Chat SDKs](/sdk/javascript/overview). ## How does it work? CometChat AI goes through the messages of a conversation to understand the context of a conversation & provide relevant replies. It returns three replies: `positive, negative & neutral`. The CometChat SDK has a method to fetch the smart replies in a conversation. It returns an object of three replies with keys: `positive, negative & neutral`. The number of messages to be fetched to generate relevant Smart Replies is configurable. By default the CometChat AI takes the latest `1000` messages. This can be configured to specific timestamps as well. | Configuration | Value | | ------------- | ------------------------------------------------------ | | lastNMessages | This will fetch specific number of messages. | | fromTimestamp | This will fetch messages from a particular timestamp. | | toTimestamp | This will fetch messages until a particular timestamp. | | unreadOnly | This will fetch only the unread messages. | While using any configuration mentioned above a maximum of **only** `1000` messages will be fetched. ## Implementation ### SDKs To implement Smart Replies in the platform of your choice, you may utilize the following code samples: ```js const receiverId = "UID/GUID"; const receiverType = "user/group"; const configuration = { lastNMessages: 100 }; CometChat.getSmartReplies(receiverId, receiverType, configuration).then( (smartReplies) => { const { positive, negative, neutral } = smartReplies; console.log("Positive Reply", positive); console.log("Negative Reply", negative); console.log("Neutral Reply", neutral); }, (error) => { console.log("An error occurred while fetching smart replies", error); } ); ``` ```java String receiverId = 'UID/GUID'; String receiverType = 'user/group'; JSONObject configuration = new JSONObject(); try { configuration.put("lastNMessages", 100); } catch (JSONException e) { throw new RuntimeException(e); } CometChat.getSmartReplies(receiverId, CometChatConstants.RECEIVER_TYPE_USER, configuration, new CometChat.CallbackListener>() { @Override public void onSuccess(HashMap smartReplies) { Iterator iterator = smartReplies.keySet().iterator(); for (String s : smartReplies.keySet()) { Log.e(TAG, "Smart Reply : " + iterator.next() + " " + smartReplies.get(s)); } } @Override public void onError(CometChatException e) { Logger.error(TAG, e.getMessage()); } }); ``` ```kotlin val receiverId: String = 'UID/GUID' val receiverType: String = 'user/group' val configuration = JSONObject() try { configuration.put("lastNMessages", 100) } catch (e: JSONException) { throw RuntimeException(e) } CometChat.getSmartReplies( receiverId, CometChatConstants.RECEIVER_TYPE_USER, configuration, object : CallbackListener>() { override fun onSuccess(smartReplies: HashMap) { val iterator: Iterator = smartReplies.keys.iterator() for (s in smartReplies.keys) { Log.e(TAG, "Smart Reply : " + iterator.next() + " " + smartReplies[s]) } } override fun onError(e: CometChatException) { Logger.error(TAG, e.message) } } ) ``` ```swift let receiverId = "" let receiverType = CometChat.ReceiverType.user let configuration = [ "lastNMessages": 100 ] CometChat.getSmartReplies(receiverId: receiverId, receiverType: receiverType, configuration: configuration) { smartRepliesMap in print("GetSmartReplies success: \(smartRepliesMap)") } onError: { error in print("GetSmartReplies error: \(error?.errorDescription)") } ``` ```dart String receiveId = ""; String receiverType = CometChatConversationType.user; Map configuration = { "lastNMessages": 100 }; CometChat.getSmartReplies(receiveId, receiverType, configuration: configuration, onSuccess: (HashMap map) { debugPrint("getSmartReplies Success: $map"); }, onError: (CometChatException e) { debugPrint("getSmartReplies Error: $e"); }); ``` ### UI Kits Assuming the necessary prerequisites are met, Smart Replies function seamlessly starting from v4 of the Chat UI Kits. In v4, Smart Replies are accessible manually, whereas in v5, they work automatically. # Avatars (Deprecated) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/avatars Deprecated: This extension is no longer maintained and will not receive further updates. This extension allows the end-users to upload an avatar image for their profile. With the Avatars Extension, your users can upload your end-users' avatar directly in CometChat. This extension is useful when you do not have a user profile management feature in your website or mobile app. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Avatars extension. ## How does it work? This extension allows the users to select an image for their avatar on CometChat. Once the image file is selected for the avatar, it needs to be uploaded in the `base64` format. The extension hosts the image and updates its URL in the avatar section of the user's profile. Also, the avatar URL is sent back in the success response for being updated in your backend. Image formats allowed by the extension are: `jpg`, `jpeg`, `png`, svg. Make use of the `callExtension` method provided by the CometChat SDK as shown below. Max size limit The size of the Avatar image file is limited to 2 MB. Please validate the size of the image before uploading it to CometChat via this extension. ```js CometChat.callExtension( 'avatar', 'POST', 'v1/upload', { avatar: 'data:image/jpeg;base64,abcd', } ).then(response => { // { avatarURL: "https://data-eu.cometchat.io/avatars/photo123.jpg" } }).catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); // bytes refer to the selected image bytes String imageString = Base64.encodeToString(bytes, Base64.NO_WRAP); // The image type can image/jpg, image/png, etc. // based on the image file under consideration. body.put("avatar", "data:image/png;base64,abcd"+imageString); CometChat.callExtension("avatar", "POST", "/v1/upload", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // {avatarURL: "https://data-us.cometchat.io/avatars/1a2b3c.jpg"} } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "avatar", type: .post, endPoint: "/v1/upload", body: ["avatar": "data:image/png;base64,abcd", onSuccess: { (response) in // { avatarURL: "https://data-eu.cometchat.io/avatars/1a2b3c.jpg" } }) { (error) in // Some error occured } } ``` # Bitly Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/bitly *Learn how to minify the long website links in your text messages using Bitly.* ## Before you begin 1. Sign up with [Bitly](https://bitly.com/). 2. Once you have logged in, click on the Account name displayed in the top right corner. 3. Click on Settings and in the left navigation pane, select API. 4. Click on Generate Token to create a new Access Token. 5. Using the above Access Token, fetch the GUID for your group using their [Get Groups API](https://dev.bitly.com/api-reference#getGroups). 6. The Access Token and Bitly Group's GUID are required in extension settings. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Bitly extension. 3. Open the settings for this extension. 4. Enter your Bitly Access Token and Group's GUID. 5. Save your settings. ## How does it work? This extension uses the `callExtension` method provided by the CometChat SDK. You can call the extension as follows: ```js CometChat.callExtension("url-shortener-bitly", "POST", "v1/shorten", { text: "Your message with URL https://yourdomain.com/very/very/long/url", }) .then((response) => { // minifiedText in response }) .catch((error) => { // Error occured }); ``` ```java String URL = "/v1/shorten"; JSONObject body=new JSONObject(); body.put("text", "Your message with URL https://yourdomain.com/very/very/long/url"); CometChat.callExtension("url-shortener-bitly", "POST", URL, body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // minifiedText from the extension } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "url-shortener-bitly", type: .post, endPoint: "v1/shorten", body: ["text": "Your message with URL https://yourdomain.com/very/very/long/url"], onSuccess: { (response) in // minifiedText from the extension }) { (error) in // Some error occured } } ``` # Chatwoot Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/chatwoot The Chatwoot extension makes customer support seamless for your users. Instead of having two interfaces- one for chat between users and one for chat with your support team, you can use CometChat as a front-end for your customer support use case as well! ## Before you begin 1. You may have an existing account created with Chatwoot. If not, sign up with [Chatwoot](https://app.chatwoot.com/app/auth/signup). 2. Do the following mandatory setup on Chatwoot: 1. To add Agent(s): [Click here](https://www.chatwoot.com/docs/user-guide/add-agent-settings) 2. To create a Channel and Inbox: [Click here](https://www.chatwoot.com/docs/product/channels/api/create-channel) 3. Only mention the name of the channel for now. The webhook URL can be skipped. 3. Get your Chatwoot Access token: 1. Once you have logged in, click on your avatar in the bottom left corner. 2. Scroll to the bottom of the Account settings section that opens up. 3. You should find the Access token. 4. Get the inbox id: 1. Once you have logged in, click on the Settings icon in the left bar. 2. Click on the "Inboxes" in the navigation. 3. Click on the Inbox that you want to set up for the CometChat support. 4. Copy the Inbox ID from the URL. For eg, if the URL is: `https://app.chatwoot.com/app/accounts/123/settings/inboxes/12128` then the Inbox ID is `12128.` 5. Get the Account ID: 1. While you have the settings open, click on the Account Settings in the navigation bar 2. Copy the Account ID from there. 6. The above details will be required during the Extension's settings. ## Extension settings #### **On CometChat Dashboard** 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Chatwoot extension. 3. Open the Settings for this extension. 4. Enter the following details about your Chatwoot account (copied earlier): 1. Chatwoot Access token 2. Chatwoot Account ID 3. Chatwoot Inbox ID 5. Enter the user's UID on CometChat who's going to be the Customer Support contact. 6. Once you save the settings, a webhook URL will be generated for you. #### On Chatwoot Dashboard 1. Go to the Settings and the Inboxes section. 2. Click on the settings icon for the inbox in use. 3. Paste the above copied URL in the Webhook URL section. ## How does it work? * The end users of your app can send queries to the Customer Support user that you have set in the extension's settings. * These queries will be forwarded to the configured Chatwoot inbox. * When an agent replies to the queries, those will be sent over to CometChat and received by your end user. * With this, your end users can communicate with each other as well as your Customer support team using the same Chat interface. # Collaborative Document Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/collaborative-document Learn how to collaborate using a document. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Collaborative Document extension. ## How does it work? ### Initiating the session Using the Collaborative Document extension is pretty straight-forward. As an initiator, you only have to create a session. The extension will handle the following for you: 1. Provide you with a link for collaboration. 2. Forward the link as an invitation to the receivers. You can initiate the session in either one-on-one chat or a group chat. The session can be shared by simply submitting the `receiver` (uid/guid) and `receiverType` (user/group). This extension uses the `callExtension` method provided by our SDKs. ```js CometChat.callExtension("document", "POST", "v1/create", { "receiver": "UID/GUID", "receiverType": "user/group" }).then(response => { // Response with document url }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("receiverType", "user/group"); body.put("receiver", "uid/guid"); CometChat.callExtension("document", "POST", "/v1/create", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // The document link to join as an initiator. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "document", type: .post, endPoint: "v1/create", body: ["receiverType":"user/group", "receiver":"uid/guid"], onSuccess: { (response) in // Success response }) { (error) in // Some error occured } ``` ### Receiving the details #### As an initiator You will be receiving the `document_url` of the session in the success callback of the `callExtension` method as shown in the above code sample. #### As a collaborator The receiver (can be a user or group) will get a message with the following properties: 1. category: `custom` 2. type: `extension_document` You have to implement the Custom message listener to get the message. Please check out our [Receive Messages](/sdk/javascript/receive-message) documentation under the SDK of your choice. By default, the unread count is not incremented for Custom Messages. Hence, the `metadata`contains `incrementUnreadCount` with value as `true`. Use this for incrementing the unread count every time a Collaborative Document's custom message is received. ### Document metadata The metadata section will have the details about the `document_url`. ```json "metadata": { "incrementUnreadCount": true, "@injected": { "extensions": { "document": { "document_url": "https://document.cometchat.io/p/uniqdocid" } } } } ``` You can make use of the getMetadata() method for extracting the details. Refer the code samples below: ```js if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("document") ) { var documentExtension = extensionsObject["document"]; var document_url = documentExtension["document_url"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("document")) { JSONObject documentObj = extensionsObject.getJSONObject("document"); String board_url = documentObj.getString("document_url"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject != null && extensionsObject.has("document")) { val documentObj = extensionsObject.getJSONObject("document") val document_url = documentObj.getString("document_url") } } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["document"] != nil { var documentObj = extensionsObject?["document"] as! [String : Any] let document_url = documentObj["document_url"] as! String } } } ``` ### Start collaborating The Collaborative document has the following editing features: 1. Bold 2. Italic 3. Underline 4. Strikethrough 5. Numbered list 6. Bulleted list 7. Indent and Outdent You can export your document as: 1. Etherpad 2. HTML 3. Plain text # Collaborative Whiteboard Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/collaborative-whiteboard Connect with other users of the app and collaborate using a Whiteboard. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Collaborative Whiteboard extension. ## How does it work? ### Initiating the session Using the Collaborative Whiteboard extension is pretty straight-forward. As an initiator, you only have to create a session. The extension will handle the following for you: 1. Provide you with a link for collaboration. 2. Forward the link as an invitation to the receivers. You can initiate a whiteboard in either one-on-one chat or a group chat. The session can be shared by simply submitting the `receiver` (uid/guid) and `receiverType` (user/group). This extension uses the `callExtension` method provided by our SDKs. ```js CometChat.callExtension("whiteboard", "POST", "v1/create", { receiver: "UID/GUID", receiverType: "user/group", }) .then((response) => { // Response with board_url }) .catch((error) => { // Some error occured }); ``` ```ts CometChat.callExtension("whiteboard", "POST", "v1/create", { receiver: "UID/GUID", receiverType: "user/group", }) .then((response: any) => { // Response with board_url }) .catch((error: any) => { // Some error occurred }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("receiverType", "user/group"); body.put("receiver", "uid/guid"); CometChat.callExtension("whiteboard", "POST", "/v1/create", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // The whiteboard link to join as an initiator. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "whiteboard", type: .post, endPoint: "v1/create", body: ["receiverType":"user/group", "receiver":"uidguid"], onSuccess: { (response) in // Success response }) { (error) in // Some error occured } ``` ```dart Map body = { 'receiverType': 'user/group', 'receiver': 'uid/guid', }; CometChat.callExtension("whiteboard", "POST", "/v1/create", body, onSuccess: (map) { }, onError: (e) { }); ``` ### Receiving the details #### As an initiator You will be receiving the `board_url` of the whiteboard session in the success callback of the `callExtension` method as shown in the above code sample. #### As a collaborator The receiver (a user or group) will get a message with the following properties: 1. category: `custom` 2. type: `extension_whiteboard` You have to implement the Custom message listener to get the message. Please check out our [Receive Messages](/sdk/javascript/receive-message) documentation under the SDK of your choice. By default, the unread count is not incremented for Custom Messages. Hence, the `metadata`contains `incrementUnreadCount` with value as `true`. Use this for incrementing the unread count every time a Collaborative whiteboard's custom message is received. ### Append username to the Whiteboard URL On the whiteboard screen, the mouse pointers of the collaborating users can be identified with the help of usernames. This username can be appended to the whiteboard URL before opening it. You can use `CometChat.getLoggedinUser()` method to get the details about the logged-in user. Refer to our [Retrieve Users](/sdk/javascript/retrieve-users) documentation for retrieving the details about the logged-in user. The following is for your reference: ```js CometChat.getLoggedinUser().then( (user) => { // Replace spaces with underscore let username = user.name.split(" ").join("_"); // Append the username to the board_url board_url = board_url + "&username=" + username; }, (error) => { console.log("error getting details:", { error }); } ); ``` ```ts CometChat.getLoggedinUser().then( (user: CometChat.User | null) => { // Replace spaces with underscore let username = user!.getName().split(" ").join("_"); // Append the username to the board_url board_url += "&username=" + username; }, (error: any) => { console.log("error getting details:", { error }); } ); ``` ```java User user = CometChat.getLoggedInUser(); if (user != null) { String username = user.getName().replace(" ", "_"); String boardUrl = "your_board_url_here"; // replace with your actual URL boardUrl = boardUrl + "&username=" + username; Log.i(TAG, "boardUrl" + boardUrl); // or use the URL as needed } ``` ```swift if let loggedInUser = CometChat.getLoggedInUser() { let userName = loggedInUser.name let boardUrl = "your_board_url_here"; // replace with your actual URL boardUrl = "\(boardUrl)&username=\(username)" print(boardUrl) } ``` ```dart CometChat.getLoggedInUser().then((user) { if(user != null) { String username = user.name.replaceAll(' ', '_'); String boardUrl = 'your_board_url_here'; // replace with your actual URL boardUrl = '$boardUrl&username=$username'; debugPrint(boardUrl); // or use the URL as needed } }).catchError((error) { debugPrint('Error getting details: $error'); }); ``` ### Whiteboard metadata The metadata section will have the details about the `board_url`. ```json "metadata": { "@injected": { "extensions": { "whiteboard": { "board_url": "https://whiteboard-.cometchat.io?whiteboardid=abc" } } } } ``` You can make use of the getMetadata() method for extracting the details. Refer the code samples below: ```js if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("whiteboard") ) { var whiteboardObject = extensionsObject["whiteboard"]; var board_url = whiteboardObject["board_url"]; } } } ``` ```ts if (metadata != null) { const injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { const extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("whiteboard") ) { const whiteboardObject = extensionsObject["whiteboard"]; const board_url = whiteboardObject["board_url"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("whiteboard")) { JSONObject whiteboardObject = extensionsObject.getJSONObject("whiteboard"); String board_url = whiteboardObject.getString("board_url"); } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["whiteboard"] != nil { var whiteboardObject = extensionsObject?["whiteboard"] as! [String : Any] let board_url = whiteboardObject["board_url"] as! String } } } ``` ```dart if (metadata != null) { if (metadata.containsKey('@injected')) { Map? injectedJSONObject = metadata['@injected']; if (injectedJSONObject.containsKey('extensions')) { Map? extensionsObject = injectedJSONObject['extensions']; if (extensionsObject != null && extensionsObject.containsKey('whiteboard')) { Map? whiteboardObject = extensionsObject['whiteboard']; if (whiteboardObject != null && whiteboardObject.containsKey('board_url')) { String boardUrl = whiteboardObject['board_url']; debugPrint(boardUrl); // or use the boardUrl as needed } } } } } ``` ### Start collaborating Our whiteboard implementation provides the following features: 1. **Edit** a. Clear board b. Undo c. Redo 2. **Tools** a. Mouse pointer b. Select an area c. Pen d. Line e. Rectangle f. Circle g. Text h. Eraser 3. **Tool properties** a. Thickness b. Color 4. **Upload image to whiteboard** 5. **Export whiteboard as image** # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/data-import-and-migration-overview Data import and migration, in the context of CometChat, involves transferring your existing chat-related data from your own servers or another chat service provider to the CometChat platform. This process typically encompasses the migration of users, their messages, any chat groups, and the list of members within those groups. The goal of migration is to ensure a seamless transition and continuity of the chat service for your users. CometChat offers the follow ways to migrate your data: ### 1. [Import historical data](/fundamentals/import-historical-data) This process is designed to transfer all of your pre-existing data at rest, that is, the data that is stored and not currently in transit, from your existing database to the CometChat database. This transfer is made possible through the use of CometChat's Data Import APIs, which are designed to handle the ingestion of large volumes of historical chat data, including users, messages, and group information. ### 2. [Live data migration](/fundamentals/live-data-migration) Live data migration is a process designed to minimize service disruption during the transition from one chat system to CometChat. It ensures that users who have updated their applications and are now on the new system (CometChat) can still communicate seamlessly with users who have not yet updated their applications and are on the old system. This approach is crucial for maintaining uninterrupted communication between all users throughout the migration period. # Disappearing Messages Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/disappearing-messages The Disappearing Messages extension allows end-users to send messages that disappear after a certain interval of time. This extension works for both private (one-on-one) and group messages. This extension is also known as exploding messages on some platforms. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Disappearing messages extension. ## How does it work? Once the messages are sent, you can immediately schedule them for deletion using the disappearing messages extension. The message with the mentioned `msgId` gets deleted at `timeInMS`. The value of timeInMS should strictly be less than 1 year This extension uses the `callExtension` method provided by the CometChat SDK. ```js CometChat.sendMessage(textMessage) // Can be any type of message .then(message => { CometChat.callExtension('disappearing-messages','DELETE','v1/disappear',{ msgId: message.id, // The id of the message that was just sent timeInMS: 1633521809051 // Time in milliseconds. Should be a time from the future. }).then(response => { // Successfully scheduled for deletion }) // Logic to display the sent message on the screen. // ... }).catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", ID_OF_THE_SENT_MESSAGE); body.put("timeInMS", 1633521809051); // Change to a future timestamp // Once the message is sent successfully, call this. CometChat.callExtension("disappearing-messages", "DELETE", "/v1/disappear", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Will disappear successfully. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift // Once a message is sent successfully, call this. // Change the timeInMS to a future timestamp. CometChat.callExtension(slug: "disappearing-messages", type: .delete, endPoint: "v1/disappear", body: ["msgId":SENT_MESSAGE_ID, "timeInMS": 1633521809051], onSuccess: { (response) in // Will disappear successfully }) { (error) in // Some error occured } ``` # Email Replies (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/email-replies **Legacy Notice**: This extension is considered legacy and is scheduled for deprecation in the near future. It is no longer recommended for new integrations. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. ## About the extension The Email Replies adds extra functionality to the Email Notifications extension by enabling the receiver of the Email Notification to respond to the conversation by directly replying to the email. ## Pre-requisite To start using Email Notifications with Replies, you need to first enable and save the settings for Email Notifications extension. [Learn more](/fundamentals/email-notifications). Once it is set up, you can come back and proceed from here. ## SendGrid Setup ### SendGrid Inbound parse webhook Once your Domain Authentication is successful, you need to set up the Inbound parse. You need to add the MX record to your Domain name provider. More details about Inbound parsing can be found [here](https://sendgrid.com/docs/for-developers/parsing-email/setting-up-the-inbound-parse-webhook/). The Webhook URL will be as follows: For apps in the US region: ``` https://email-notification-us.cometchat.io/v1/reply ``` For apps in the EU region: ``` https://email-notification-eu.cometchat.io/v1/reply ``` For apps in the IN region: ``` https://email-notification-in.cometchat.io/v1/reply ``` Before saving the Inbound Host and URL: 1. Uncheck **Spam Check** checkbox. 2. Uncheck **Send Raw** checkbox. ## Extension Settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Email replies extension. 3. Open up the settings page for this extension. 4. Select *Email replies* option and enter the sender Email ID. 5. Save your settings. When adding Sender's Email in the settings, please make sure that it does not have "+" in it. ## Save users' Email IDs You can use our to set private metadata for a user. We recommend adding this code where you call our . Alternatively, just for the sake of testing purposes, you can add this from the CometChat Dashboard as well. 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the "Users" section. 3. Select any user of your choice and select the "Profile" tab. 4. Paste the below JSON in the Metadata input box and hit Save. The Metadata is a JSON that should have the `@private` key present and should have the value `email` specified for the user. The format for the private metadata must be as follows: ```json { "@private": { "email":"abc@xyz.com" } } ``` ## Respond via Email Send a message to an offline user and watch them receive an email automagically. Reply to the Email and receive a response in your chat. ## Send Reply via Email Click on **Reply** button in your mailbox and the composer will open up. Type your message and hit send. Your message will be sent to the CometChat user as a response in the chat. Do not add any other Email ID in To, Cc, or Bcc fields while replying. # Emojis (Deprecated) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/emojis Deprecated: This extension is outdated as all the major browsers natively support emojis. # End To End Encryption (Deprecated) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/end-to-end-encryption Deprecated: This extension is no longer maintained and will not receive further updates. Ensure only your users can read what is sent and nobody in between. End-to-end encryption is intended to prevent data being read or modified by anyone but the sender and recipient(s). The messages are encrypted by the sender and decrypted by the recipient locally on their device. [Virgil Security](https://virgilsecurity.com/) is an industry leader in end-to-end encryption. I want to checkout the sample app End-to-end Encryption Sample app for Web (React) Follow the steps mentioned in the `README.md` file. Kindly, click on below button to download. [Sample app](https://github.com/cometchat/javascript-react-chat-end-to-end-encryption-app/archive/refs/tags/3.0.5-1.zip) [View on Github](https://github.com/cometchat/javascript-react-chat-end-to-end-encryption-app) ## Before you begin 1. Sign up or Log in to [https://dashboard.virgilsecurity.com/apps](https://dashboard.virgilsecurity.com/apps) 2. Create a New application. 3. Go to E3Kit section and create the .env file. Copy the following details: 1. `APP_ID` 2. `APP_KEY_ID` 3. `APP_KEY` ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the End-to-end encryption extension. 3. Open the Settings for this extension and save the following: 1. `APP_ID` 2. `APP_KEY_ID` 3. `APP_KEY` 4. Save your settings. ## How does it work? Virgil E3Kit uses the concept of Asymmetric key cryptography for achieving End-to-end encryption of messages. The process and code for encryption and decryption for your platform can be found at Virgil's documentation [here](https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/default/#sign-and-encrypt-data). CometChat users and groups are considered as `identities` on Virgil. ### Handled by the extension #### 1. Creation of Virgil token and identity `VIRGIL TOKEN` is required for initialization of E3Kit on the client-side. CometChat users and groups have `IDENTITIES` on Virgil. ```js CometChat.callExtension('e2ee', 'GET', '/v1/virgil-jwt', null) .then(response => { const { virgilToken, identity } = response; }) .catch(error => { // Error occured }); ``` ```java CometChat.callExtension("e2ee", "GET", "/v1/virgil-jwt", null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // virgilToken, identity } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "e2ee", type: .get, endPoint: "/v1/virgil-jwt", body: nil, onSuccess: { (response) in // virgilToken, identity }) { (error) in // Some error occured } } ``` #### 2. Fetching the identities for users and groups In order to encrypt and decrypt messages, the E3Kit requires the `IDENTITIES`. These can be cached in your app for reuse. ```js const uids = ['cometchat-uid-1']; const guids = ['cometchat-guid-1', 'anothergroup']; CometChat.callExtension('e2ee', 'POST', '/v1/get-identities', { uids, guids }) .then(response => { // userIdentities and groupIdentities are array of objects. // Each object has (g)uid as the key and the identity as its value. const { userIdentities, groupIdentities } = response; }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray uids = new JSONArray(); JSONArray guids = new JSONArray(); uids.add("cometchat-uid-1"); guids.add("cometchat-guid-1", "anothergroup"); body.put(uids); body.put(guids); CometChat.callExtension("e2ee", "POST", "/v1/get-identities", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // userIdentities, groupIdentities } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "e2ee", type: .post, endPoint: "v1/get-identities", body: ["uids":["cometchat-uid-1"], "guids":["cometchat-guid-1", "anothergroup"]] as [String : Any], onSuccess: { (response) in // userIdentities, groupIdentities }) { (error) in // Error occured } ``` #### 3. Group actions Group Management on Virgil is different from the Group Management on CometChat. Virgil groups have the following restrictions: 1. The creator of the group is called as the `GROUP OWNER.` 2. Only the `GROUP OWNER` can add members to or remove members from a Virgil group. 3. Group can be deleted only by the `GROUP OWNER`. Hence, to reduce the development efforts on the front-end, the following group actions are handled by the extension: 1. Create group 2. Delete group 3. Add member(s) to group 4. Kick a member from a group 5. Ban a member from a group 6. Member joins a group 7. Change in group owner/moderator/admin You will need the `GROUP OWNER` identity to list the groups followed by encrypting or decrypting messages from those groups. The `IDENTITY` for the `GROUP OWNER` is `2137f9ef75295ea`. Learn more about Virgil Group Encryption [here](https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/). ### To be handled on app #### Login 1. The user logs in to CometChat. 2. Your app makes a call to the extension to get the `VIRGIL TOKEN` and `VIRGIL IDENTITY` for the logged in user. 3. Logged in user is then registered on Virgil cloud using the client-side E3Kit. This step requires the `VIRGIL TOKEN` that was generated before. Learn more about setting up E3Kit client [here](https://developer.virgilsecurity.com/docs/e3kit/get-started/setup-client/). The `EThree.initialize` method takes a second parameter that is object with the following two keys: 1. `groupStorageName`: Pass the value as `.g_${current_timestamp}` 2. `storageName`: Pass the value as`.l_${current_timestamp}` 4. In this process of registration, a `CARD` is generated for the logged in user. It contains the `PUBLIC KEY` that is available for everyone else. 5. Also, a `PRIVATE KEY` is generated and stored locally for the logged in user. 6. This `PRIVATE KEY` is very important and must be backed up using E3Kit. This step requires the `VIRGIL IDENTITY` that was generated for the logged in user. #### Message encryption (Send a message) 1. The logged in user fetches the `VIRGIL IDENTITY` of the receiver by making a call to the extension. 2. This `VIRGIL IDENTITY` is then used for fetching the receiver's `CARD`. 3. This `CARD` is then used to encrypt the text message. 4. The encrypted message is then sent to the receiver using the CometChat SDK. #### Message decryption (Receive a message) 1. The encrypted message is received by the logged in user in the appropriate listener provided by CometChat SDK. 2. The logged in user decrypts the message using the `PRIVATE KEY` at his end to view the original text. Learn more about encryption and decryption of one-on-one messages [here](https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/default/).\ Learn more about encryption and decryption of group messages [here](https://developer.virgilsecurity.com/docs/e3kit/end-to-end-encryption/group-chat/#encrypt-and-decrypt-messages). #### Logout 1. Call the `cleanup()` method provided by the E3Kit to remove the Private key from the user's device. 2. Make sure that the back up was created during the Login process in **Step 1**. For implementation details on the platform of your choice, please refer to Virgil E3Kit [documentation](https://developer.virgilsecurity.com/docs/e3kit/). Private key backup It is very important that you take a backup of the Private key for the logged in users. If that is lost, a new CARD has to be generated on Virgil that leads to creation of new Private and Public key pair.\ Older messages cannot be decrypted using the new Private key. More details can be found [here](https://developer.virgilsecurity.com/docs/e3kit/key-backup/). #### Recommended Login flow The following flow is recommended to make sure that: 1. The `PRIVATE KEY` is backed up during the first time a user registers using Virgil's E3Kit. 2. Your users are able to restore the `PRIVATE KEY`, thus ensuring multi-device support and continued access to older messages. 3. Virgil Group actions can be performed on behalf of the user by the extension. CAVEATS 1. Other extensions will not work once the End-to-end encryption extension is enabled. As the messages will only be visible to your end users. 2. The extension needs to be enabled and correctly configured immediately after an app is created on the CometChat Dashboard. 3. Extension does not work for existing groups. 4. If the user loses the Private Key, they will not be able to decrypt older messages encrypted using the lost key pair. Hence, backup of Private key is very important. # Extensions Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/extensions-overview We believe that building a great chat product does not consist of just voice, video and text chat. It's much more than that. And Extensions are our answer to this. Extensions pickup where our core leaves. They help extend the functionality of CometChat. ### User Experience Extensions that help improve the user messaging experience. *Recommended for most apps.* [Pin message](/fundamentals/pin-message)\ [Bitly](/fundamentals/bitly)\ [Avatars](/fundamentals/avatars)\ [Message shortcuts](/fundamentals/message-shortcuts)\ [Link Preview](/fundamentals/link-preview)\ [Rich Media Preview](/fundamentals/rich-media-preview)\ [Save message](/fundamentals/save-message)\ [Thumbnail Generation](/fundamentals/thumbnail-generation)\ [TinyURL](/fundamentals/tinyurl)\ [Voice Transcription](/fundamentals/voice-transcription) ### User Engagement Extensions that help increase user engagement. *Recommended for advanced apps.* [Email replies](/fundamentals/email-replies)\ [Polls](/fundamentals/polls)\ [Giphy](/fundamentals/giphy)\ [Mentions](/fundamentals/mentions)\ [Message Translation](/fundamentals/message-translation)\ [Reactions](/fundamentals/reactions)\ [Smart Reply](/fundamentals/smart-replies)\ [Stickers](/fundamentals/stickers)\ [Stipop](/fundamentals/stickers-stipop)\ [Tenor](/fundamentals/tenor)\ [Reminders](/fundamentals/reminders)\ [Live Streaming by api.video](/fundamentals/video-broadcasting) ### Collaboration Extensions that help with collaboration. *Recommended for advanced apps.* [Collaborative Whiteboard](/fundamentals/collaborative-whiteboard)\ [Collaborative Document](/fundamentals/collaborative-document) ### Customer Support Extensions that help you add support to your app. *Recommended for advanced apps.* [Intercom](/fundamentals/intercom)\ [Chatwoot](/fundamentals/chatwoot) ### Notifications Extensions that help alert users of new messages. *Recommended for all apps.* [Push Notification](/notifications/web-push-notifications)\ [Email Notification](/notifications/email-notification-extension)\ [SMS Notification](/notifications/sms-notification-extension) ### Moderation *Extensions that help you to build a safe messaging environment.* *Recommended for live streaming and event apps.* [Slow mode](/moderation/slow-mode)\ [Report user](/moderation/report-user)\ [Report message](/moderation/report-message)\ [In-flight Message Moderation](/moderation/in-flight-message-moderation)\ [Image Moderation](/moderation/image-moderation)\ [Virus and Malware Scanner](/moderation/virus-malware-scanner)\ [Data Masking Filter](/moderation/data-masking-filter)\ [Profanity Filter](/moderation/profanity-filter)\ [Sentiment Analysis](/moderation/sentiment-analysis)\ [XSS Filter](/moderation/xss-filter) ### Security *Extensions that help you to build adding extra security to your apps.* *Recommended for live streaming and event apps.* [Disappearing messages](/fundamentals/disappearing-messages)\ [End to End Encryption](/fundamentals/end-to-end-encryption) # Core In App Messaging Features Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/features-core CometChat provides a powerful suite of messaging features. A subset of these features called 'Messaging Core' provide features which are bare minimum to build a good chat user experience. The following are some of the most used Core features: * User to User and Group chat: * This is the most basic form of messaging which can exists between two individual users or users that are a part of a group. For a developer's perspective, the actual chat works using the following delivery methods: * On the message sender's side, the messages are sent using CometChat UI Kits which use SDKs which act as an API wrapper. * On the message receiver's side, the messages are delivered using a Websocket connection to the CometChat plaform which is managed by the SDKs. * For more details on Websockets and its connectivity details, please visit [Managing Web Sockets](/sdk/javascript/managing-web-sockets-connections-manually) in the CometChat SDK. * By default, user and group messaging along with Web Socket implementation is available in the UI Kits. * Media sharing: * Sharing files, videos and other media types are the key in today's messaging world. You can implement media messages using SDKs or UI Kits as well as use [Extensions](/fundamentals/extensions-overview) for Gifs and Stickers. * By default, support for Media messages is available in the UI Kits. * Message Delivery and Read receipts: * Message delivery receipts indicate that a message has reached the message receiver. Message read receipt indicates that the message has been read by the message receiver. CometChat supports the following features from a message delivery and read indicator perspective: * Mark up to a message as delivered. * Mark up to a message as read. * Mark all messages after a particular message as unread. * To view these features, please visit [Delivery and Read receipts](/sdk/javascript/delivery-read-receipts#mark-messages-as-unread) in the SDK docs. * By default, support delivery and read receipts is available in the UI Kits. * Typing indicators: * Typing indicators in a conversation provide an indication to other users that a given user is typing a message. To implement typing indicators, visit the [Typing indicators](/sdk/javascript/typing-indicators) section of the SDK docs. * By default, support Typing indicators is available in the UI Kits. * Mentions (@username): * Mentions allow users to refer to a specific user in a conversation. This is done by sending a '@username' in the message to address that user. * To implement Mentions, please visit [Mentions](/sdk/javascript/mentions) section in the SDK docs. * By default, support for Mentions is available in the UI Kits. * Reactions: * Reactions on a message allow users to express their emotions using emojis. To implement Reactions, please visit the [Reactions](/sdk/javascript/reactions) section in the SDK docs. * By default, support for Reactions is available in the UI Kits. * Threaded Conversations: * Message threads allow users to branch off a conversation specific to a topic within a conversation in a sub-conversation. Such a conversation is called a Threaded conversation. To implement Threads in a conversation, please visit [Threaded Messages](/sdk/javascript/threaded-messages) section in the docs. * By default, support for Threaded conversations is available in the UI Kits. * User presence: * User presence helps users to understand if a particular user is online and hence available for chat. To implement User presence, please visit the [User Presence](/sdk/javascript/user-presence) section in the docs. * By default, support for User Presence is available in the UI Kits. # Gfycat (Deprecated) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/gfycat Deprecated: This extension is no longer maintained and will not receive further updates. Gfycat ceased their operations recently. This extension is no longer available. Please check out our [Giphy](/fundamentals/giphy) extension that is similar to Gfycat. # Giphy Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/giphy GIFs are a great way to change the tone or convey emotions in your conversations. Here's a guide which helps to implement Gifphy in an easy and quick way. Let's get started! ## Before you begin 1. Sign up at [Giphy](https://developers.giphy.com/dashboard/) and create a new app. 2. Select API and click on Next. 3. Enter your App name, description and click create. 4. Make note of the API key that has been created. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Giphy extension. 3. Click on the settings button and enter your Giphy API key and hit save. ## How does it work? This extension uses the `callExtension` method provided by the CometChat SDK. You can perform the following actions using this method: 1. Get trending GIFs 2. Search for GIFs ### Get Trending GIFs To list and show the most trending GIFs on Giphy, all you have to do is include the following parameters in your request. | key | Value | Description | | ------ | ------ | -------------------------------------------------------------------------------------------------------------- | | offset | number | Since you can get paginated results for trending GIFs, you can provide an offset and fetch results accordingly | | limit | number | The number of trending GIFs that you want to fetch | Once you have set the above parameters, you can make a call to the extension as follows: ```js const URL = "v1/trending?offset=1&limit=15"; CometChat.callExtension("gifs-giphy", "GET", URL, null) .then((response) => { // GIFs data from Giphy }) .catch((error) => { // Error occured }); ``` ```java String URL = "/v1/trending?offset=1&limit=15"; CometChat.callExtension("gifs-giphy", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // GIFs data from Giphy } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "gifs-giphy", type: .get, endPoint: "v1/trending?offset=10&limit=15", body: nil, onSuccess: { (response) in // GIFs data from Giphy }) { (error) in // Some error occured } } ``` ### Search for GIFs Apart from listing the trending ones, the extension also allows searching for a particular GIF using the following parameters: | key | value | Description | | ------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | offset | number | Since you can get paginated results for searches, you can provide an offset and fetch results accordingly. | | limit | number | The number of GIFs that you want to fetch as part of the search. | | lang | 2-letter ISO 639-1 language identifier | (Optional) Defaults to en. (Example values: es, fr, it.) | | query | string | Search term | Once you have all the above parameters, you can make a call to the extension as follows: ```js const URL = "v1/search?offset=1&limit=15&query=awesome"; CometChat.callExtension("gifs-giphy", "GET", URL, null) .then((response) => { // GIFs data from Giphy }) .catch((error) => { // Error occured }); ``` ```java String URL = "/v1/search?offset=1&limit=15&query=awesome"; CometChat.callExtension("gifs-giphy", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // GIFs data from Giphy } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "gifs-giphy", type: .get, endPoint: "v1/search?offset=10&limit=15&query=awesome", body: nil, onSuccess: { (response) in // GIFs data from Giphy }) { (error) in // Some error occured } } ``` # Implementation Checklist Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/implementation-checklist ### 1. Complete the Signup Process * [Create a free account](https://app.cometchat.com/signup) with CometChat. * Familiarize yourself with the [key concepts](/fundamentals/key-concepts). * Send invitations to other developers, product owners for collaboration. ### 2. Integrate the chosen UI Kit or SDK into your application * Choose to integration CometChat in your app either by using UI Kits or SDKs. * Have a look at our Sample apps for quickly checking out features and functionalities. * UI Kits: [React](/ui-kit/react/overview), [React Native](/ui-kit/react-native/overview), [iOS](/ui-kit/ios/overview), [Android](/ui-kit/android/overview), [Flutter](/ui-kit/flutter/overview), [Angular](/ui-kit/angular/overview), [Vue](/ui-kit/vue/overview)\ SDKs: [JavaScript](/sdk/javascript/overview), [React Native](/sdk/react-native/overview), [iOS](/sdk/ios/overview), [Android](/sdk/android/overview), [Flutter](/sdk/flutter/overview), [Ionic/Capacitor](/sdk/ionic/overview) & [Sample apps](https://github.com/cometchat) ### 3. Synchronize users and groups utilizing the APIs * This step involves the backend side of implementation. * When a new user signs up in your system, create the corresponding user's entry with CometChat using APIs. * Whenever a user's details are updated in your system, synchronize them with CometChat. * [Create users API](/rest-api/users/create) * [Update users API](/rest-api/users/update) ### 4. Enable necessary extensions * Enable extensions like [Thumbnail generator](/fundamentals/thumbnail-generation), [Message translation](/fundamentals/message-translation), etc. * Implement the frontend for these [extensions](/fundamentals/extensions-overview) in case the implementation does not exist. ### 5. Implement Push notifications * Drive user engagement in your applications through the integration of [Push Notifications](/notifications/push-overview). ### 6. Integrate CometChat AI * Ignite natural and organic converstaions between your users. * [CometChat AI](/fundamentals/ai-user-copilot/overview) ### 7. Set up bots * [Bots](/ai-chatbots/overview) are unique users capable of autonomously sending and receiving messages. You can define a bot's behaviour by implementing and exposing your business logic using Callback URLs. ### 7. Set up webhooks * [Webhooks](/fundamentals/webhooks-overview) faciliate real-time event-driven communication with your system, enabling you to receive HTTP POST requests from CometChat that carry details about different events. ### 9. Secure user logins with authentication tokens * Ensuring safe and secure authentication of users in CometChat is crucial. Achieve this by utilizing [auth tokens](https://api-explorer.cometchat.com/reference/create-authtoken). * Generate and retrieve the [auth token](https://api-explorer.cometchat.com/reference/create-authtoken) through your backend system, then supply it to the frontend. ### 10. Set up data import and migration * To seamlessly transition from your existing chat solution to CometChat's comprehensive solution, you will need to [import your existing data](/fundamentals/import-historical-data) as well as migrate the [live data](/fundamentals/live-data-migration) to CometChat. ### 11. Launch your applications with the new messaging capabilities * Delete default/test users and groups. * Select a correct billing plan. * Go live with your apps powered by CometChat. * [CometChat Dashboard](https://app.cometchat.com). # Import Historical Data Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/import-historical-data The CometChat message import API allows application owners and admins to import existing chat messages data from any source into CometChat. ## General Instructions: 1. The authentication mechanism for these APIs follows the same authentication as all public CometChat REST APIs. Please use your app REST API Key in the header. 2. The Base URL for the APIs is `https://.api-.cometchat.io/v3/data_import/` 3. The HTTP request data will be in JSON format. 4. The HTTP response from CometChat will also be in JSON format. ## Import Messages API Usage To import messages send post requests to the import api with bulk arrays of message records in chronological. To process large set of records multiple requests can be made. Each record in the array must contain a single message `data` record that conform with the restrictions as specified by the [Send Message APIs](https://api-explorer.cometchat.com/reference/send-message). The total message count of all imported messages must be within the limit shared in the import support ticket. Each record contains a unique message id referred to as `muid`. The array key and the `muid` value must be the same. The return status for each `muid` will be documented in the response messages under `data..success`. The value of this parameter can be: 1. `true`: indicating import execution success for that `muid`. 2. `false`: indicating import execution failure for that `muid`. In case of a failure, the error details will be noted in `data..error`. Please note that the request can have many messages to be imported, each with a separate `muid`. It is possible that a message may not be imported due to incorrect data supplied or a runtime error. In this case, its error code will be documented under its `muid` structure in the response. In case of such an error, correct the data being supplied in the API as per the error code indicated and resend the failed message data in a new API call. It is not expected to include the messages which were successfully imported in the preceding API call which resulted in the error for certain messages. Visit [Message Import API](https://api-explorer.cometchat.com/reference/import-messages) to start with your imports. ### Request Format ```json { "messages": { "1": { "id": "200", "muid": "123e4567-e89b-12d3-a456-426652340000", "sender": "", "receiverType": "user", "receiver": "", "type": "text", "category": "message", "data": { "text": "Hi there,", "attachments": [ { "name": "hi.png", "extension": "png", "size": "350.2", "mimeType": "image_png", "url": "https:__data-eu.cometchat.io_assets_images_avatars_cometchat-uid-1.webp" } ], "metad2ata": { "key": "value" }, "custodata": { "key": "value" } }, "sentAt": "1674104348", "deliveredAt": "1674224684", "readAt": "1674224684", "tags": [ "tag1" ] } } } ``` ### Response Format ```json { "data": { "201": { "success": true, "data": { "data": { "muid": "123e4567-e89b-12d3-a456-426652340000", "id": "201", "conversationId": "", "sender": "", "receiverType": "user", "receiver": "", "category": "message", "type": "text", "data": { "text": "Hi there!!", "entities": { "sender": { "entity": { "uid": "", "name": "", "avatar": "", "status": "offline", "role": "default", "createdAt": 1674211544 }, "entityType": "user" }, "receiver": { "entity": { "uid": "", "name": "", "avatar": "", "status": "offline", "role": "default", "createdAt": 1674211544 }, "entityType": "user" } } }, "sentAt": 1674104348, "deliveredAt": 1674224684, "readAt": 1674224684, "updatedAt": 1674104348, "tags": [ "tag1" ] } } } } } ``` ## Import Users API Usage To import users send post requests to the import api with bulk arrays of user records. To process large set of records multiple requests can be made. Each record in the array must contain a single user record. The array key and the `uid` value must be the same. The return status for each `uid` will be documented in the response messages under `data..success`. The value of this parameter can be: 1. `true` -> indicating import execution success for that `uid`. 2. `false` -> indicating import execution failure for that `uid`. In case of a failure, the error details will be noted in `data..error`. Please note that the request can have many users to be imported, each with a separate `uid`. It is possible that a user may not be imported due to incorrect data supplied or a runtime error. In this case, its error code will be documented under its `uid` structure in the response. In case of such an error, correct the data being supplied in the API as per the error code indicated and resend the failed user data in a new API call. It is not expected to include the users which were successfully imported in the preceding API call which resulted in the error for certain users. Visit [User Import API](https://api-explorer.cometchat.com/reference/import-users) to start with your imports. ### Request Format ```json { "users": { "": { "uid": "", "name": "", "role": "", "link": "", "avatar": "", "createdAt": "", "lasActiveAt": "", "metadata": { }, "tags": [], "deactivatedAt": "" } } } ``` ### Response Format ```json { "data": { "user33": { "success": true, "data": { "data": { "uid": "user33", "name": "user 31", "avatar": "https:__data-eu.cometchat.io_assets_images_avatars_cometchat-uid-1.webp", "metadata": { "key": "value" }, "status": "offline", "role": "default", "lastActiveAt": 1673421419, "deactivatedAt": 1673421419, "createdAt": 1673421419, "updatedAt": 1674155164 }, } } } } ``` ## Next steps To learn more about importing data in to CometChat, visit our [Data import API docs](https://api-explorer.cometchat.com/reference/data-import) # Intercom Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/intercom The Intercom extension makes customer support seamless for your users. Instead of having two interfaces- one for chat between users and one for chat with your support team, you can use CometChat as a front-end for your customer support use case as well! ## Before you begin 1. You may have an existing account created with Intercom. If not, sign up with [Intercom](https://intercom.com). 2. Create a test workspace by following these [steps](https://www.intercom.com/help/en/articles/188-create-a-test-workspace-in-intercom) from Intercom's documentation. 3. Once that is done, go back to the settings and expand the Developers section. 4. Click on DeveloperHub and create an app. 5. Select the newly created app and go to the Authentication section. 6. Copy the Access token as this will be required later. The integration works with Intercom API Verion `2.3 (2020-11-12)`. If there's a version mismatch, the extension won't work. ## Extension settings #### On CometChat Dashboard 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Intercom extension. 3. Open the Settings for this extension. 4. Enter the following and save your settings: 1. **Intercom Access token**: Copied earlier from the Intercom Developer Hub. 2. **Customer Support UID**: A user on CometChat that is your Customer Support user. 5. Once you save your settings, a Webhook URL will be auto generated for your app. #### On Intercom Developer Hub 1. Copy the above auto-generated Webhook URL and paste it in the Webhooks section on the Intercom Developer Hub. 2. From the Webhook Topics, select `conversation.admin.replied` ## How does it work? The end users of your app can send queries to the Custom Support user that you have set in the extension's settings. These queries will be forwarded to the Intercom dashboard. Similarly, messages sent from Intercom dashboard by the support team or admin will be sent over to CometChat and received by your end user. With this, your end users can communicate with each other as well as your Custom support team using the same Chat interface. # Key Concepts Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/key-concepts ## Dashboard * The CometChat Dashboard enables you to create new apps (projects) and manage your existing apps. * Ideally, you should create two apps - one for development and one for production. * Do not create separate apps for every platform; if you do, your users on different platforms will not be able to communicate with each other! * For every app, a unique App ID (`appId`) is generated. This `appId` will be required when integrating CometChat within your app. ## Users * In CometChat, a "user" refers to anyone who utilizes the service for communication. * Each user is uniquely identified using `uid`. * The `uid` is typically the primary ID of the user from your database. * A `uid` can be alphanumeric with underscore (`_`) and hyphen (`-`). Spaces, punctuation and other special characters are not allowed. ### User Roles * A role is a category for a group of similar users. * For example, you may want to group your premium users using the role "Premium". * You then use this to filter users or enable/disable features by writing conditional code. ### User List * The User List can be used to build the **Contacts** or **Who's Online** view in your app. * The list of users can be different based on the logged-in user. ## Authentication * For a user to engage with other users using CometChat, they must be authenticated and logged into CometChat's system, typically after they have logged into your application or website. * **CometChat does not take care of user management** tasks such as registration and login processes. These aspects must be managed within your own application or website. Once a user is logged into your service, you can then programmatically log them into CometChat, ensuring that users never have to log into CometChat directly. * Similarly, **CometChat does not manage friendships or contacts** within its platform. If your application requires a feature where users can add each other as friends, this must be handled on your end. After two users have established a mutual friend connection in your application, you can then reflect this relationship within CometChat, linking them as friends in the messaging system. ### Auth workflow | Your App | Your Server | CometChat | | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | | User registers in your app | You store the user information in your database (e.g. ID, name, email, phone, location etc. in `users` table) | You add the user to CometChat (only ID & name) using the Rest API | | User logs in to your app | You verify the credentials, login the user and retrieve the user ID | You log in the user to CometChat using the same user ID programmatically | | User sends a friend request | You display the request to the potential friend | No action required | | User accepts a friend request | You display the users as friends | You add both the users as friends using the Rest API | ### Auth & Rest API Keys * From the CometChat dashboard, you can generate two types of keys. * Each key serves a distinct purpose and provides different levels of access to the CometChat platform, ensuring that your application's interaction with CometChat is secure and appropriate permissions are maintained. | Type | Privileges | Recommended Use | | ------------ | ---------------------------------------------------------------- | --------------------------------------------- | | Auth Key | The Auth Key can be used to create & login users. | In your client-side code (during development) | | Rest API Key | The Rest API Key can be used to perform any CometChat operation. | In your server-side code | ### Auth token * Auth tokens are associated with users in CometChat. A single user can have multiple auth tokens. The auth tokens should be **per user per device**. * It should be generated by API call ideally, via server to server call. The auth token should then be given to CometChat for login. * An Auth Token can only be deleted via dashboard or using REST API. ## Groups * A group in CometChat is a feature that allows multiple users to engage in conversations about specific topics or shared interests. It facilitates collective communication and collaboration among its members. * Each group is uniquely identified using `guid`. * The `guid` is typically the primary ID of the group from your database. * If you do not store group information in your database, you can generate a random string for use as `guid`. * A `guid` can be alphanumeric with underscore (`_`) and hyphen (`-`). Spaces, punctuation and other special characters are not allowed. ### Group types CometChat supports three different types of groups. | Type | Visibility | Participation | | -------- | ---------------------------- | ------------------------------------------------- | | Public | All users | Any user can choose to join | | Password | All users | Any user with a valid password can choose to join | | Private | Only users part of the group | Invited users will be auto-joined | ### Group members * After joining a group on CometChat, a participant is considered a member of that group. * This membership is ongoing, meaning they will continue to receive messages, calls, and notifications from the group indefinitely. * If a member no longer wishes to receive these communications, they must actively leave the group or be removed by being kicked out or banned by a group administrator. CometChat supports three different types of member scopes in a group: | Member | Default | Privileges | | ----------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Admin | Group creator is assigned Admin scope | - Change scope of Group Members to admin, moderator or participant. - Can add members to a group. - Kick & Ban Participants/Moderators/Admins - Send & Receive Messages & Calls - Update group - Delete group | | Moderator | A participant can be made a moderator | - Change scope of moderator or participant. - Update group - Kick & Ban Participants - Send & Receive Messages & Calls | | Participant | Any other user is assigned Participant scope | - Send & Receive Messages & Calls | ## Messaging Every message in CometChat belongs to either one of the five categories: 1. Message 2. Custom 3. Action 4. Call 5. Interactive Each category can be further be classified into types. ### Message The category `message` can be used to send messages of the following types: 1. `text` - A plain text message 2. `image`- An image message 3. `video`- A video message 4. `audio`- An audio message 5. `file`- A file message ### Custom * In the case of messages that belong to the `custom` category, there are no predefined types. * Custom messages can be used by developers to send messages that do not fit in the default category and types provided by CometChat. * For messages with the category `custom`, the developers can set their own type to uniquely identify the custom message. * A very good example of a custom message would be the sharing of location co-ordinates. In this case, the developer can decide to use the custom message with type set to `location`. ### Action Action messages are system-generated messages. Messages belonging to the `action` category can further be classified into one of the below types: 1. `groupMember` - action performed on a group member. 2. `message` - action performed on a message. Action messages hold another property called `action` which actually determine the action that has been performed For the type `groupMember` the action can be either one of the below: 1. `joined` - when a group member joins a group 2. `left` - when a group member leaves a group 3. `kicked` - when a group member is kicked from the group 4. `banned` - when a group member is banned from the group 5. `unbanned` - when a group member is unbanned from the group 6. `added` - when a user is added to the group 7. `scopeChanged` - When the scope of a group member is changed. For the type `message`, the action can be either one of the below: 1. `edited` - when a message is edited. 2. `deleted` - when a message is deleted. ### Call Messages with the category `call` are Calling related messages. These can belong to either one of the 2 types 1. `audio` 2. `video` The call messages have a property called status that helps you figure out the status of the call. The status can be either one of the below values: 1. `initiated` - when a is initiated to a user/group 2. `ongoing` - when the receiver of the call has accepted the call 3. `canceled` - when the call has been canceled by the initiator of the call 4. `rejected` - when the call has been rejected by the receiver of the call 5. `unanswered` - when the call was not answered by the receiver. 6. `busy` - when the receiver of the call was busy on another call. 7. `ended` - when the call was successfully completed and ended by either the initiator or receiver. ### Interactive Messages with the category `interactive` are useful where users can perform some action without leaving the conversation. Interactive messages can be of the following types: 1. `form` 2. `card` 3. `scheduler` 4. `customInteractive` # Limits Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/limits To ensure a reliable and seamless chat experience while minimizing downtime and errors, certain limits are in place. The limits may vary based on your subscription plan. If you have any questions, feel free to [contact us](https://www.cometchat.com/contact). ### Groups 1. Groups with all features enabled can support up to 300 members. 2. Groups without delivery/read receipts and typing indicators can support up to 100,000 members. ### Users 1. A single user can join a maximum of 2,000 groups. 2. A user can have up to 1,000 friends. 3. Presence subscriptions are capped at 1,000 concurrently online users. Once this threshold is exceeded, presence events (online/offline) will no longer be emitted. ### Messages 1. Each message, including metadata, must not exceed 65,536 characters (\~65KB). ### Voice & Video Calling 1. For the best experience, a maximum of 50 participants can join a single video call. ### API 1. REST API calls are rate-limited as follows: * **Standard operations**: 20,000 API calls per minute. * **Core operations**: 10,000 API calls per minute (e.g., creating/deleting users, joining/leaving groups). All other operations fall under standard operations. # Link Preview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/link-preview The Link Preview extension will help you show a preview of the web page for every link in your message. While this extension gives you all the details required for generating a preview, our [Rich Media Preview](/fundamentals/rich-media-preview) gives you a decorated iframe with the styling. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Link Preview extension. ## How does it work? We provide you a few details about the URL that is in your message. The details are as follows: 1. Description 2. Favicon 3. Image 4. Title 5. URL. Say, for example, a user shares a Facebook link in their message, then our extension will query the link for the details that you need to build a preview. These details are provided as part of metadata as shown in the example below: ```json "@injected": { "extensions": { "link-preview": { "links": [ { "description": "Create an account or log into Facebook. Connect with friends, family and other people you know. Share photos and videos, send messages and get updates.", "favicon": "https://static.xx.fbcdn.net/rsrc.php/yz/r/KFyVIAWzntM.ico", "image": "https://www.facebook.com/images/fb/icon/325x325.png", "title": "Facebook - Log In or Sign Up", "url": "https://www.facebook.com" } ] } } } ``` If the link-preview key is missing, it means that the extension is either not enabled or has timed out. Also, it may happen that certain details are missing or the details are not available altogether. Consider switching to Rich Media Preview for better experience. ## Implementation Using the Link Preview extension, you can build a preview box similar to the one you've seen in Slack. You can fetch the details for the Link Preview using `getMetadata()` method. ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("link-preview") ) { var linkPreviewObject = extensionsObject["link-preview"]; var links = linkPreviewObject["links"]; var description = links[0]["description"]; var favicon = links[0]["favicon"]; var image = links[0]["image"]; var title = links[0]["title"]; var url = links[0]["url"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("link-preview")){ JSONObject linkObject = extensionsObject.getJSONObject("link-preview"); JSONArray linkArray= linkObject.getJSONArray("links"); JSONObject linkPreviewObject=linkArray.getJSONObject(0); if (linkPreviewObject.has("description")) String description = linkPreviewObject.getString("description"); if (linkPreviewObject.has("favicon")) String favicon = linkPreviewObject.getString("favicon"); if (linkPreviewObject.has("image")) String image = linkPreviewObject.getString("image"); if (linkPreviewObject.has("title")) String title = linkPreviewObject.getString("title"); if (linkPreviewObject.has("url")) String url = linkPreviewObject.getString("url"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject.has("link-preview")) { val linkObject = extensionsObject.getJSONObject("link-preview") val linksArray = linkObject.getJSONArray("links") val linkPreviewObject = linksArray.getJSONObject(0) if (linkPreviewObject.has("description")) val description = linkPreviewObject.getString("description") if (linkPreviewObject.has("favicon")) val favicon = linkPreviewObject.getString("favicon") if (linkPreviewObject.has("image")) val image= linkPreviewObject.getString("image") if (linkPreviewObject.has("title")) val title= linkPreviewObject.getString("title") if (linkPreviewObject.has("url")) val url= linkPreviewObject.getString("url") } } } } ``` ```swift let textMessage = message as? TextMessage if let metaData = textMessage.metaData , let injected = metaData["@injected"] as? [String : Any], let cometChatExtension = injected["extensions"] as? [String : Any], let linkPreviewDictionary = cometChatExtension["link-preview"] as? [String : Any], let linkArray = linkPreviewDictionary["links"] as? [[String: Any]] { guard let linkPreview = linkArray[safe: 0] else { return } if let linkTitle = linkPreview["title"] as? String { print(linkTitle) } if let description = linkPreview["description"] as? String { print(description) } if let thumbnail = linkPreview["image"] as? String { print(thumbnail) } if let linkURL = linkPreview["url"] as? String { print(linkURL) } if let favIcon = linkPreview["favicon"] as? String { print(favIcon) } } ``` Links that take more than a second to resolve will be automatically skipped to keep in-flight transit time to a minimum. # Live Data Migration Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/live-data-migration Upon integrating with our messaging solution, you may encounter a scenario where your application is transitioning from a homegrown chat feature to our comprehensive services. During this transition phase, a live migration process is necessary to ensure continuity of communication. Live migration accommodates the interaction between the legacy chat system and the new implementation. It ensures that users on different versions of your app—with some utilizing the original chat and others leveraging the latest version with CometChat integrated—can communicate seamlessly. Implementing live migration effectively bridges the gap between the two systems during the upgrade cycle, until all users have transitioned to the updated application featuring our robust messaging capabilities. To initiate live migration, please contact our [Sales team](https://www.cometchat.com/contact-sales). # Mentions (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/mentions **Legacy Notice**: This extension is already included as part of the core messaging experience and is scheduled for deprecation in the near future. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. Mentions are a great way to get someone's attention in a conversation. Mentions start with the @ symbol followed by a name. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Mentions extension. ## How does it work? ### Implement UI logic in your app Simply enabling the extension will not add the functionality to your apps. The Mentions extension heavily depends on the UI. It should have the following logic already implemented. 1. When `@` symbol is typed in the message composer, show a list of all the users of that group. 2. Insert the selected name from the list in the message composer as `@{Name|UID}`. 3. The message bubbles and the message composer render the `@{Name|UID}` as just `@Name`. For showing a list of users in a group, you can refer to our [Retrieve Group Members](/sdk/javascript/retrieve-group-members) documentation under the SDK of your choice. ***For example:*** To mention Andrew Joseph with UID `cometchat-uid-1`, the text message should be **Hello @\{Andrew Joseph|cometchat-uid-1}**. However, it should be rendered or formatted as **Hello @Andrew Joseph** in the message composer as well as the message bubbles in the chat. You have to use third party libraries that make the above mentioned implementation simpler and a rich text editor like [Quill](https://quilljs.com/) or [TinyMCE](https://www.tiny.cloud/tinymce/features/). ### Listing messages with mentions To get all the messages with mentions for a user, make use of the `callExtension` method provided by CometChat SDK as shown below: ```js const URL = "v1/fetch"; CometChat.callExtension('mentions', 'GET', URL, null).then(response => { // {messages: []} }) .catch(error => { // Error occured }); ``` ```java String URL = "/v1/fetch"; CometChat.callExtension("mentions", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // {messages: []} } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "mentions", type: .get, endPoint: "v1/fetch", body: nil, onSuccess: { (response) in // { messages: [] } }) { (error) in // Some error occured } } ``` # Message Shortcuts Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/message-shortcuts The Message Shortcuts extension enables your users to send each other predefined messages. For example, **!hb** can be automatically expanded to **Happy birthday!** ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Message shortcuts extension. 3. Open the settings for this extension. 4. You should a list of Global Message shortcuts. 5. Edit the existing shortcuts or add new ones. 6. Save your settings. ## How does it work? The shortcuts saved in the Extension's settings are Global message shortcuts that can be accessed by all the users of your app. The shortcuts saved by users are accessible only to them along with the Global message shortcuts. With the Message Shortcuts extension, you can: 1. Fetch all shortcuts on your user's device. 2. Allow users to edit, define or delete shortcuts. 3. Send predefined message by typing shortcuts. ## Implementation ### 1. Fetch all shortcuts Once the user has successfully logged in, you can request the shortcuts from the extension. Additionally, you can provide a button to refresh the shortcuts. Make use of the `callExtension` method exposed by the CometChat SDK to fetch the shortcuts. ```js CometChat.callExtension('message-shortcuts', 'GET', 'v1/fetch', null) .then(shortcuts => { // Save these shortcuts locally. }) .catch(error => { // Some error occured }); ``` ```java CometChat.callExtension("message-shortcuts", "GET", "/v1/fetch", null, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Shortcuts received here. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "message-shortcuts", type: .get, endPoint: "v1/fetch", body: nil, onSuccess: { (response) in print("Stickers",response) }) { (error) in print("Error",error?.errorCode, error?.errorDescription) } ``` The response will have the following JSON structure: ```json { "shortcuts": { "!hbd": "Happy Birthday! 🥳", "!cu": "See you later.", "!ty": "Hey! Thanks a lot! 😊", "!wc": "You're welcome!" } } ``` ### 2. Modify shortcuts Shortcuts can be added, edited or deleted by your users. You need to have a section in your front-end application that allows the users to do so. The extension accepts a final list of shortcuts after all the modifications have been done by the user. Make use of the `callExtension` method exposed by the CometChat SDK to submit the final customized list. ```js const finalList = { shortcuts: { "!hbd":"Happy birthday! Have fun!" } }; CometChat.callExtension('message-shortcuts', 'POST', 'v1/update', finalList) .then(response => { // Updated successfully. }) .catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject finalList = new JSONObject(); JSONObject shortcuts = new JSONObject(); shortcuts.put("!hbd", "Happy birthday! Have fun!"); shortcuts.put("!ttyl", "Talk to you later"); finalList.put("shortcuts", shortcuts); CometChat.callExtension("message-shortcuts", "POST", "/v1/update", finalList, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift let finalList = ["shortcuts": ["!hbd": "Happy Birthday!" , "!cu" : "See you later.", "!ty", "Hey! Thanks a lot! :blush:", "!wc", "You're welcome!"]] CometChat.callExtension(slug: "message-shortcuts", type: .post, endPoint: "v1/update", body: finalList, onSuccess: { (response) in // Updated successfully. }) { (error) in // Error occured } ``` ### 3. Use shortcuts The UI implementation can be as follows: 1. When `!` is typed in the message composer, a list pops up above the message composer with all the available shortcuts and their predefined values. 2. On typing the next letter after the`!` typed earlier, the list gets filtered with the shortcuts that start with that letter. 3. Clicking on any shortcut from the list, expands the corresponding predefined message in the message composer. # Message Translation Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/message-translation The Message Translation extension helps you translate messages into multiple languages. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Message Translation extension. ## How does it work? The messages translation extension allows the receivers of the message to translate it in the language of their choice. In a group of multi-lingual people, a message sent by one of the participants can be in English. However, it can be translated by other members of the group to their languages. We support translations in the following languages: | Language | Language code | | --------------------- | ------------- | | Afrikaans | af | | Albanian | sq | | Amharic | am | | Arabic | ar | | Armenian | hy | | Azerbaijani | az | | Bengali | bn | | Bosnian | bs | | Bulgarian | bg | | Catalan | ca | | Chinese (Simplified) | zh | | Chinese (Traditional) | zh-TW | | Croatian | hr | | Czech | cs | | Danish | da | | Dari | fa-AF | | Dutch | nl | | English | en | | Estonian | et | | Farsi (Persian) | fa | | Filipino, Tagalog | tl | | Finnish | fi | | French | fr | | French (Canada) | fr-CA | | Georgian | ka | | German | de | | Greek | el | | Gujarati | gu | | Haitian Creole | ht | | Hausa | ha | | Hebrew | he | | Hindi | hi | | Hungarian | hu | | Icelandic | is | | Indonesian | id | | Irish | ga | | Italian | it | | Japanese | ja | | Kannada | kn | | Kazakh | kk | | Korean | ko | | Latvian | lv | | Lithuanian | lt | | Macedonian | mk | | Malay | ms | | Malayalam | ml | | Maltese | mt | | Marathi | mr | | Mongolian | mn | | Norwegian (Bokmål) | no | | Pashto | ps | | Polish | pl | | Portuguese (Brazil) | pt | | Portuguese (Portugal) | pt-PT | | Punjabi | pa | | Romanian | ro | | Russian | ru | | Serbian | sr | | Sinhala | si | | Slovak | sk | | Slovenian | sl | | Somali | so | | Spanish | es | | Spanish (Mexico) | es-MX | | Swahili | sw | | Swedish | sv | | Tamil | ta | | Telugu | te | | Thai | th | | Turkish | tr | | Ukrainian | uk | | Urdu | ur | | Uzbek | uz | | Vietnamese | vi | | Welsh | cy | The language is identified using identifiers from [RFC 5646](https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes) — if there is a 2-letter ISO 639-1 identifier, with a regional subtag if necessary, it uses that. Otherwise, it uses the ISO 639-2 3-letter code. ## Implementation The extension uses the `callExtension()` method provided by CometChat SDKs. The messages will be translated according to the languages specified by the receiver. You can specify the languages for translation as an array. If you pass in an empty array, the language will default to English. ```js CometChat.callExtension('message-translation', 'POST', 'v2/translate', { "msgId": 12, "text": "Hey there! How are you?", "languages": [ "ru", "hi", "mr" ] }).then( result => { // Result of translations }) .catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray languages = new JSONArray(); languages.add("ru"); languages.add("hi"); body.put("msgId", 12); body.put("languages", languages); body.put("text", "Hey there! How are you?"); CometChat.callExtension("message-translation", "POST", "/v2/translate", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // Result of translations } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "message-translation", type: .post, endPoint: "v2/translate", body: ["msgId": 12 ,"languages": ["hi", "ru"], "text": "Hey there! How are you?"] as [String : Any], onSuccess: { (response) in // Result of translations }) { (error) in // Some error occured } ``` The result will be received in the success callback of the `callExtension()` method. It will have the following JSON structure: ```json { "msgId": 12, "translations": [ { "message_translated": "Эй там! Как ты?", "language_translated": "ru", "error": null, "error_description": null }, { "message_translated": "अरे वहाँ! आप कैसे हैं?", "language_translated": "hi", "error": null, "error_description": null }, { "message_translated": "", "language_translated": "mr", "error": "UnsupportedLanguagePairException", "error_description": "Unsupported language pair: en to mr. Target language 'mr' is not supported" } ], "language_original": "en" } ``` If the source language is not supported for translation, then you will get the following error: ```json { "code": "ERR_NOT_SUPPORTED", "message": "Autodetected source language '' is not supported" } ``` ### Translating at the sender's end If the languages of the end-users/receivers are known before hand, this method of implementation can be used. That is, before your trigger `CometChat.sendMessage` method, make a call to the message translation extension as mentioned above. Since the message has not been sent yet, the `msgId` won't be available and can be skipped in that call. Once you get the response, make an entry in your message's metadata as shown below: ```js const messageText = "Hey there! How are you?"; const metadata = { "message-translation": { "ru": "Эй там! Как ты?", "hi": "अरे वहाँ! आप कैसे हैं?" }, }; const textMessage = new CometChat.TextMessage(receiverID, messageText, receiverType); textMessage.setMetadata(metadata); CometChat.sendMessage(textMessage).then( message => { console.log("Message sent successfully:", message); }, error => { console.log("Message sending failed with error:", error); } ); ``` ```java private String messageText = "Hey there! How are you?"; JSONObject metadata = new JSONObject(); JSONObject translations = new JSONObject(); try { translations.put("ru", "Эй там! Как ты?"); translations.put("hi", "अरे वहाँ! आप कैसे हैं?"); metadata.put("message-translation", translations); } catch (JSONException je) { je.printStackTrace(); } TextMessage textMessage = new TextMessage(receiverID, messageText, receiverType); textMessage.setMetadata(metadata); CometChat.sendMessage(textMessage, new CometChat.CallbackListener () { @Override public void onSuccess(TextMessage textMessage) { Log.d(TAG, "Message sent successfully: " + textMessage.toString()); } @Override public void onError(CometChatException e) { Log.d(TAG, "Message sending failed with exception: " + e.getMessage()); } }); ``` ```kotlin val messageText:String="Hey there! How are you?" val metadataObject:JSONObject=JSONObject("{ "message-translation": { "ru": "Эй там! Как ты?", "hi": "अरे वहाँ! आप कैसे हैं?" }, }") val textMessage = TextMessage(receiverID, messageText, receiverType) textMessage.metadata=metadataObject CometChat.sendMessage(textMessage, object : CometChat.CallbackListener() { override fun onSuccess(p0: TextMessage?) { Log.d(TAG, "Message sent successfully: " + p0?.toString()) } override fun onError(p0: CometChatException?) { Log.d(TAG, "Message sending failed with exception: " + p0?.message) } }) ``` ```swift let text = "Hey there! How are you?"; let translations = ["ru": "Эй там! Как ты?", "hi": "अरे वहाँ! आप कैसे हैं?"]; let metadata = ["message-translation": translations] let textMessage = TextMessage(receiverUid: receiverID, text: text, receiverType: .user) textMessage.metaData = metadata; CometChat.sendTextMessage(message: textMessage, onSuccess: { (message) in print("TextMessage sent successfully. " + message.stringValue()) }) { (error) in print("TextMessage sending failed with error: " + error!.errorDescription); } ``` Then, at the receiver's end, based on the device/browser language, you can show the translated text message in their chats from the metadata. ### Translating at the receiver's end If the languages of the end-users/receivers are not known before hand, this method of implementation can be used. Simply show a translate button above every message bubble in the UI. Make a call to the extension as mentioned above. The translation can then be shown in the same message bubble. However, unlike the translations that are saved in the metadata when translating at the sender's end, these translations are ephemeral and will be lost once the page is reloaded, the user fetches older messages and scrolls back to the latest translated messages or the user switces conversations and comes back to the conversation with translated messages. # Moderation Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/moderation-extensions CometChat Moderation features come in two variants: 1. The mordern rule based [Moderation](/moderation/overview) platform. 2. The [Legacy Moderation Extensions](/moderation/slow-mode) based on CometChat Extensions. * [Slow Mode (Deprecated)](/moderation/slow-mode) * [Report User (Legacy)](/moderation/report-user) * [Report Message (Legacy)](/moderation/report-message) * [Data Masking Filter (Legacy)](/moderation/data-masking-filter) * [Profanity Filter (Legacy)](/moderation/profanity-filter) * [Image Moderation (Legacy)](/moderation/image-moderation) * [In-flight Message Moderation (Legacy)](/moderation/in-flight-message-moderation) * [Virus and Malware Scanner (Legacy)](/moderation/virus-malware-scanner) * [XSS Filter (Deprecated)](/moderation/xss-filter) For the best experience, we recommend to use the rule based [Moderation](/moderation/overview) platform. Please visit the above mentioned links for more details. # Best Practices Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/multi-tenancy-best-practices ## Configuration as code Rather than configure apps manually in the CometChat app dashboard, it is advantageous, especially with high volume app creation, to create and manage apps using the CometChat App Management API. By using a configuration template and/or a process based code pattern, apps can be created and managed in a consistent manner. ## Tenancy and apps Tenancy can be modeled in CometChat based on the inherent tenancy of the use case. In most multi-tenant use cases, the CometChat App is also associated to some type of entity related to the use case, such as a location, customer or partner. The CometChat App ID for each such app created should be stored as an associated data with that entity. The app configuration other than App ID and credentials is best stored only in CometChat after app creation and initial configuration. The configuration can be queried and modified using the API. Instead of storing the app configuration outside CometChat, simply use code patterns to get and set the app configuration within CometChat based on the logic related to the use case. ## Metrics and Usage Because all multi-tenant apps consume from the limits associated with the base app, it is recommended to use the stats and metrics APIs to review usage for each app to determine any usage irregularities on a per app basis. # Multi Tenancy Plans And Apps Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/multi-tenancy-overview ## What is an app? CometChat apps are a way to combine a set of users, groups, roles and other configuration that results in a particular experience for chat users. ## What is a multi-app setup? To provide different experiences to a different set of users, a developer can create many CometChat apps. Each of these apps have their own data within them, like it's users, messages, etc., and do not interact or share data with other apps. Similarly, each of these apps have their own billing plans and cycles which do not interact with each other. ## What is a multi-tenant setup? To provide a similar experience to a different set of users, a developer can create many similar CometChat apps that consume from the limits and quotas of the same CometChat billing plan. The data is still not shared between apps, but the billing plan is. This provides economies of scale as well as a streamlined experience in configuring, deploying and managing many CometChat apps. ## When should you use a multi-tenant plan? Multi-tenant plans are quite suitable for certain use cases such as for aggregators and vertical-specific software. Think of situations such as\ the following or ones adjacent to it. * You're building an app that allows schools and teachers to communicate with students and parents. You'd create a multi tenant account for yourself and each school, their students, teachers, announcements etc. would be an app of their own. * A business app that lets business owners or franchises of a particular chain, their employees, and customers talk to each other. Something like Slack. Each business would be a separate app in this case, and the account would work on multi tenancy mode. These, and many more similar use cases can be addressed using a multi-tenant model. As an example of something that is not a great use case for multi-tenant but rather multi-app is, is when you are running 2 or 3 apps within the same organization with different user bases, separate P & Ls, or are owned by different departments for different purposes. Multi-app setup with clearly separate billing and metrics are a better choice in such cases. ## Setting up a multi-tenant plan To begin using the multi-tenant functionality of CometChat, an account must be enabled for multi-tenancy. File a support ticket to learn more and enable multi-tenancy for your account. Upon approval, the account will be configured with a base app that is associated with a billing plan and all other apps created in the multi-tenant account will be associated with this base app. ## Multi-tenant usage, billing and features All usage from all apps created in the mulit-tenant account will consume from the quotas (MAU, PCC, Voice and Video Minutes) of the base app. This usage will be added as a pooled bill on the base app, including overages, and charged as a combined bill to the payment method of the base app. All apps created in a multi-tenant account will have access to all the features included in the plan and configurations associated with the base app. ## App Management APIs Once an account has been enabled for muti-tenant usage, an App Management key and secret will be provided to you. The key and secret allow for the use of the App Management APIs to programmatically create and configure CometChat apps. App Management APIs provide the capabilities to manage apps including enable, disabling and configuring extensions, managing app team members, configuring webhooks and managing widgets. # Notifications Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/notification-extensions CometChat Notifications come in two variants: 1. The mordern [Notifications](/notifications/overview) platform. * [Push Notifications](/notifications/push-overview) * [Email Notifications](/notifications/email-overview) * [SMS Notification](/notifications/sms-overview) 2. The Legacy Notification Extensions based on CometChat Extensions. * [Legacy Push Notifications Extension](/notifications/web-push-notifications) * [Legacy Email Notifications Extension](/notifications/email-notification-extension) * [Legacy SMS Notifications Extension](/notifications/sms-notification-extension) For the best experience, we recommend to use the mordern [Notifications](/notifications/overview) platform. Please visit the above mentioned links for more details. # What Is CometChat? Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/overview CometChat is a comprehensive communications platform that empowers businesses to seamlessly integrate real-time chat, voice and video calling functionalities. These integrations can be done picking up the implementation methods that align best with your goals. Our **Messaging & chat** features offer flexible, secure, feature-rich and easy-to-manage integrations for your web and mobile apps. With **Voice & video calling** features, you get enterprise-grade security, robust infrastructure and a familiar UI from the same vendor as your chat solution. ## Solutions for every industry CometChat's solutions cater to every industry with a global and scalable infrastructure, multi-region capabilities, multi-tenancy, and round-the-clock support. Our comprehensive documentation, competitive pricing, and flexible implementation options ensure that our platform is equipped for enterprise-grade requirements while remaining accessible for startups. This dual readiness positions CometChat as both **Enterprise-ready** and **Startup-friendly**. Our customer base spans a diverse range of industries, including: * Online marketplaces * Healthcare * Dating * Events & streaming * Online education * Community & Social * Sports & Gaming * Team Comms & Workflows * SaaS Businesses ## Integrate in minutes With a few lines of code, you can have CometChat integrated into any app written in React, iOS, Android, Flutter and 12+ other languages. **Future proof your chat roadmap** by implementing chat quickly and efficiently with minimal risk. Our UI kits, APIs empower you to focus on growing your business while we handle the technical aspects. **Partner with subject matter experts** and master the art of real-time engagement with CometChat. Our expertise in messaging, chat, and calling empowers you to offer the best in-app chat experience. **Complete customizability & extensions** empowers you to personalize user experience, leverage data from other systems, connect chat to your core business logic with webhooks, extensions & integrations. ## Build with tools of your choice ### No-code widget Simply copy and paste a few lines of code to add text, voice, and video to your web app in minutes. ### Low-code UI Kits Reduce your time to market and give your users the modern chat experience they expect with UI kits. ### SDKs & APIs Fully customizable and easy to use? Yes, it's possible, with our SDKs and APIs for in-app messaging and voice & video calling. ## Compliances Choosing CometChat is your assurance of a meticulously vetted and highly secure solution. We deeply appreciate and obsess over the significance of both security and compliance. CometChat is fully compliant with the following security standards: * **HIPAA + BAA**: CometChat is compliant with HIPAA rules and standards and can enter into a BAA. * **PIPEDA**: CometChat is compliant with PIPEDA and follows the Fair Information Principles. * **GDPR**: CometChat meets all requirements of GDPR and provides special APIs to enable customers to maintain compliance. * **ISO 27001**: CometChat is certified compliant with the ISO 27001 standards. * **SOC 2 Type 2**: CometChat is certified compliant with SOC 2’s five Trust Service Principles of security, availability, privacy, confidentiality, and processing integrity. ## Features ### Messaging & chat | Core messaging | Advanced messaging | Engagement | | ------------------------ | ---------------------- | ----------------------------- | | One-on-one private chat | Threaded conversations | Mentions | | Group text messaging | Message replies | Stickers & GIFs | | Share files & multimedia | Message translation | Collaborative whiteboard | | Typing indicators | Smart Replies | Collaborative document | | Users & friends list | Chat history | Polls | | Users & friends presence | Custom messages | Mentions count | | Read receipts | Pin message | User profile avatars | | Delivery receipts | Save message | Reminders | | Audio messages | Rich media preview | Reactions | | Unread message count | URL shorteners | Push notifications | | Users search | Thumbnail generation | Email notifications & replies | | Messages search | Message shortcuts | SMS notifications | | | Voice transcription | Email replies | | | Broadcast message | | | Moderation | Administration & Security | Integrations & webhooks | | ---------------------------- | --------------------------------- | ----------------------- | | In-flight message moderation | Analytics | Analytics & usage API | | Image moderation | Dashboard team management | Rest APIs | | Profanity filter | Custom metadata | Before message webhook | | Data masking | Cross-platform sync | After message webhook | | XSS Filter | User & group management | Intercom | | User-to-user blocking | Encryption | SendGrid | | Moderation dashboard | Multi-device support | Chatwoot | | Human moderators | Historical data import API | Virgil security | | Report user | Live data migration | App management API | | Kick/ban users | Data export | App creation API | | Report message | ISO 27001 | Presence webhook | | Virus & malware scanner | SOC 2 | Read receipt | | Sentiment analysis | GDPR API | Delivery receipt | | | HIPPA w/ BAA | | | | Encryption in transit (TLS/SSL) | | | | Encryption at rest (AES 256) | | | | Role-based access control | | | | Disappearing messages | | | | End-to-end encryption | | | | End-user API endpoint restriction | | ### Voice & video calling | Calling essentials | Advanced calling features | Administration | | ----------------------------- | ------------------------- | ------------------------- | | 1-to-1 calling | Video broadcasting | Analytics & usage API | | Group calling | Call recording | Rest APIs | | Multi-device support | Interactive whiteboard | Dashboard analytics | | Conference calls | Interactive document | Call logs | | Personal meeting rooms | Picture-in-picture | Customizable call screens | | Mobile calling | Screen sharing | SRTP encryption | | Push notifications | In-call messaging | Pushkit & callkit support | | Grid tile & spotlight layouts | | App management API | ### CometChat AI | Insights AI | Conversational AI | Moderation AI | | ------------------ | ------------------------------------ | ------------------- | | AI Funnel Insights | Conversation Starter & Smart Replies | Content Moderation | | AI User Insights | Conversation Summaries | AI Image Moderation | | AI Entity Insights | AI Bots | Mute Suggestions | ## Moving forward Next, have a look at the Implementation checklist to quickly integrate chat functionality into your app and prepare for a successful launch. # Pin Message Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/pin-message ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Pin message extension. ## How does it work? Pin message extension provides you the ability to: 1. Pin messages 2. Unpin messages 3. Fetch all the pinned messages for a conversation. Messages pinned in a conversation (be it one-on-one or group) are visible to the receiver(s) as well. ### 1. Pin a message To pin a message, use the `callExtension` method provided by the SDK to make an HTTP POST request with the parameters as shown below. You need to pass the `msgId` that has to be pinned. ```js CometChat.callExtension('pin-message', 'POST', 'v1/pin', { "msgId": 280 // The ID of the message to be pinned. Here 280. }).then(response => { // { success: true } }) .catch(error => { // Error occurred }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", 280); CometChat.callExtension("pin-message", "POST", "/v1/pin", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "pin-message", type: .post, endPoint: "v1/pin", body: ["msgId": 280] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### 2. Unpin a message To unpin a message, use the `callExtension` method provided by the SDK to make an HTTP DELETE request with the parameters as shown below. You need to pass the `msgId`, `receiverType` and the `receiver` (can be either UID or GUID based on `receiverType`). ```js CometChat.callExtension('pin-message', 'DELETE', 'v1/unpin', { "msgId": 111, "receiverType": "group", "receiver": "cometchat-guid-1" }).then(response => { // { success: true } }) .catch(error => { // Error occurred }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", 111); body.put("receiverType", "group"); body.put("receiver", "cometchat-guid-1"); CometChat.callExtension("pin-message", "DELETE", "/v1/unpin", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "pin-message", type: .delete, endPoint: "v1/unpin", body: ["msgId": 111, "receiverType": "group", "receiver": "cometchat-guid-1"] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### 3. Fetch pinned messages To fetch the pinned messages for a conversation, use the `callExtension` method provided by the SDK to make an HTTP GET request with the query parameters as shown below. You need to pass the `receiverType` and the `receiver` (can be either UID or GUID based on `receiverType`). ```js const URL = `v1/fetch?receiverType=${RECEIVER_TYPE}&receiver=${RECEIVER}`; CometChat.callExtension('pin-message', 'GET', URL, null).then(response => { // {pinnedMessages: []} }) .catch(error => { // Error occured }); ``` ```java String URL = "/v1/fetch?receiverType=" + RECEIVER_TYPE + "&receiver=" + RECEIVER; CometChat.callExtension("pin-message", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // {pinnedMessages: []} } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "pin-message", type: .get, endPoint: "v1/fetch?receiverType=\(RECEIVER_TYPE)&receiver=\(RECEIVER)", body: nil, onSuccess: { (response) in // {pinnedMessages: []} }) { (error) in // Some error occured } } ``` # Polls Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/polls Polls let you quickly record the opinions directly in the Conversations and also view the results. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Polls extension. ## How do polls work? Polls extension has the following 3 parts: 1. Creating a poll by submitting a question along with the possible options. 2. Voting in a poll. 3. Fetching the results for a particular poll. ## 1. Creating a Poll In order to create a poll, you need to submit the following details: 1. Question 2. Array of options 3. Receiver (UID/GUID) 4. Receiver type (user/group) The options in the array are assigned an index appropriately (starting from 1). You can create a poll by using `callExtension` method provided by our SDKs: ```js CometChat.callExtension('polls', 'POST', 'v2/create', { "question": "Which OS do you use?", "options": ["Windows", "Ubuntu", "MacOS", "Other"], "receiver": "cometchat-uid-1", "receiverType": "user" }).then(response => { // Details about the created poll }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray options = new JSONArray(); options.add("Milk"); options.add("Cereal"); body.put("question", "Milk goes first or the cereal?"); body.put("options", options); body.put("receiver", "cometchat-guid-1"); body.put("receiverType", "group"); CometChat.callExtension("polls", "POST", "/v2/create", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "polls", type: .post, endPoint: "v2/create", body: ["question": "Which OS do you use?" ,"options":["Windows", "Ubuntu", "MacOS", "Other"],"receiver":"cometchat-uid-1","receiverType":"user"] as [String : Any], onSuccess: { (response) in // Details about the created poll }) { (error) in // Error occured } ``` ## 2. Receiving a poll Polls are custom messages. So, you have to implement our `onCustomMessageReceived` listener in order to receive the Poll-related message. Please refer to our [Receive Messages](/sdk/javascript/receive-message) documentation under the SDK of your choice. The `metadata` stores all the information about the poll. You will find the following details in `metadata` -> `@injected` -> `extensions` -> `polls`. | Key | Value | | -------- | ------------------------------------------------------------------------------------ | | id | A String representing a unique ID for the poll. | | options | An Object with the option number as the key and the option description as the value. | | question | A string representing the question asked in the poll. | | results | An object that stores voting results. | Apart from the above Poll-related details, the `metadata` will also contain `incrementUnreadCount` with value as `true`. This will be useful for incrementing the unread count every time a poll is received. ## 3. Voting in a poll Voting in a poll simply requires you to provide the `id` of the poll and the option you intend to vote for. The `vote` parameter is basically the option number. You can allow users to vote for a poll by using the `callExtension` method provided by our SDKs: ```js CometChat.callExtension('polls', 'POST', 'v2/vote', { vote: "3", id: "d5441d53-c191-4696-9e92-e4d79da7463", }).then(response => { // Successfully voted }) .catch(error => { // Error Occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("vote", OPTION_NUMBER); body.put("id", POLL_ID); CometChat.callExtension("polls", "POST", "/v2/vote", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // Voted successfully } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "polls", type: .post, endPoint: "v2/vote", body: ["vote": "3","id": "d5441d53-c191-4696-9e92-e4d79da7463"], onSuccess: { (response) in // Successfully voted }) { (error) in // Error Occured } ``` ## 4. Getting Results There are 2 ways to fetch the results of the poll: 1. Real-time updates from the `metadata` 2. Fetch the results by using the `callExtension` method. ### Real-time updates As mentioned earlier, a Poll is a message of the category: `custom`. When the votes are cast by the users, the metadata for the message will be updated accordingly. To get real-time voting information, you need to implement the `onMessageEdited` listener. Please check our [Edit message](/sdk/javascript/edit-message) documentation under the SDK of your choice. The updated details will be available in the metadata of the message. Here is a sample response: ```json "@injected": { "extensions": { "polls": { "id": "d5441d53-c191-4696-9e92-e4d79da7463", "options": { "1": "Chicken", "2": "The Egg" }, "results": { "total": 2, "options": { "1": { "text": "Chicken", "count": 1, "voters": { "cometchat-uid-1": { "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" } } }, "2": { "text": "The Egg", "count": 1, "voters": { "cometchat-uid-2": { "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp" } } } } }, "question": "Which came first? The chicken or the egg?" } } } ``` ### Using callExtension() method For fetching results, the only parameter required is the id of the poll. You can use this method only when you are the creator of the poll. Others cannot call this method to get the poll results. Result for a poll can be fetched using a `callExtension` method provided by our SDKs: ```js CometChat.callExtension('polls', 'GET', 'v2/results?id='+POLL_ID, null) .then(results => { // Poll results }) .catch(error => { // Some error occured }); ``` ```java String URL = "/v2/results?id=" + POLL_ID; CometChat.callExtension("polls", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // Poll results } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "polls", type: .get, endPoint: "v2/results?id=\(POLL_ID)", body: nil, onSuccess: { (response) in // Poll results }) { (error) in // Some error occured } } ``` A sample response for the results is as follows: ```json "polls": { "id": "d5441d53-c191-4696-9e92-e4d79da7463", "options": { "1": "Chicken", "2": "The Egg" }, "results": { "total": 2, "options": { "1": { "text": "Chicken", "count": 1, "voters": { "cometchat-uid-1": { "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" } } }, "2": { "text": "The Egg", "count": 1, "voters": { "cometchat-uid-2": { "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp" } } } } }, "question": "Which came first? The chicken or the egg?" } ``` # Reactions (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/reactions **Legacy Notice**: This extension is already included as part of the core messaging experience and is scheduled for deprecation in the near future. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. Reactions are the ability to react to an individual message with a specific emotion, quickly showing acknowledgment or expressing how you feel in a lightweight way. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Reactions extension. ## How do reactions work? A user can react to a message using multiple emojis. To allow a user to react to a message, show a popup with all the available emojis. Once the user clicks on a particular emoji, add that emoji as a reaction to the target message. If a user has reacted to a message using a certain emoji and clicks on the same emoji, remove it from the target message. Sending Reactions To add a reaction using selected emoji, use the `callExtension` method provided by our SDKs as follows: ```js CometChat.callExtension('reactions', 'POST', 'v1/react', { msgId: MESSAGE_ID, emoji: "😊" }).then(response => { // Reaction added successfully }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", ID_OF_THE_MESSAGE); body.put("emoji", "😊"); CometChat.callExtension("reactions", "POST", "/v1/react", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Reaction added successfully. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "reactions", type: .post, endPoint: "v1/react", body: ["msgId":MESSAGE_ID, "emoji":"😊"], onSuccess: { (response) in // Reaction added successfully }) { (error) in // Some error occured } ``` ## Receiving Reactions The messages will be updated later with Reactions as and when users react to them. Hence, you need to implement the `onMessageEdited` listener. Please check our [Edit message](/sdk/javascript/edit-message) documentation under the SDK of your choice. The updated details will be available in the metadata of the message. Here is a sample response: ```json "@injected": { "extensions": { "reactions": { "😊": { "cometchat-uid-2": { "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp" }, "cometchat-uid-1": { "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, }, "👍": { "cometchat-uid-3": { "name": "George Alan", } } } } } ``` ## Implementation At the recipients' end, from the message object, you can fetch the metadata by calling the getMetadata() method. Using this metadata, you can fetch the reaction details for that message. ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("reactions") ) { var reactionsObject = extensionsObject["reactions"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("reactions")) { JSONObject reactionsObject = extensionsObject.getJSONObject("reactions"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject != null && extensionsObject.has("reactions")) { val reactionsObject = extensionsObject.getJSONObject("reactions") } } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil) { var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["reactions"] != nil { var reactionsObject = extensionsObject?["reactions"] as! [String : Any] } } } ``` # Reminders Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/reminders Create reminders for messages or anything else. ## Extension Settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Reminders extension. 3. Go to the Users section and create a new user with `cc_reminder_bot` as the UID. The name and Avatar can be of your choice. The `cc_reminder_bot` user should be available for your app in order to use the Reminders extension. There shouldn't be an existing user using the same `UID`. ## How do reminders work? Users can choose to be reminded about a message from a conversation or set some sort of custom personalized reminder. When the reminder is due, `cc_reminder_bot` will send a message to the user. Users can then list, edit or delete reminders. ### Set reminders The following parameters are required for setting a reminder | Parameter | Value | Description | | ---------- | -------------- | ----------------------------------------------------------------------------------------- | | `about` | Integer/String | `Integer` => For setting a message reminder. `String` => For setting a personal reminder. | | `isCustom` | Boolean | `false` => For setting a message reminder. `true` => For setting a personal reminder. | | `timeInMS` | Integer | Unix timestamp: (e.g.: `1638351344989`) | #### Message reminders To set Message reminders, the `about` should be an integer corresponding to the message id. The `isCustom` value should be set to`false`. In order to set the reminders, use the `CometChat.callExtension` method as shown below: ```js CometChat.callExtension('reminders', 'POST', 'v1/reminder', { about: 1, isCustom: false, timeInMS: 1638351344989 }).then(response => { // Reminder created successfully // Reminder details with reminderId. }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("about", ID_OF_THE_MESSAGE); body.put("isCustom", false); body.put("timeInMS", 1638351344989); CometChat.callExtension("reminders", "POST", "/v1/reminder", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Reminder created successfully. // Reminder details with reminderId. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "reminders", type: .post, endPoint: "v1/reminder", body: ["about":MESSAGE_ID, "isCustom":false, "timeInMS": 1638351344989], onSuccess: { (response) in // Reminder created successfully. // Reminder details with reminderId. }) { (error) in // Some error occured } ``` #### Personal reminders To set Personal reminders, the about can contain the description. The `isCustom` value should be set to`true`. In order to set the reminders, use the `CometChat.callExtension` method as shown below: ```js CometChat.callExtension('reminders', 'POST', 'v1/reminder', { about: "Drinking water", isCustom: true, timeInMS: 1638351344989 }).then(response => { // Reminder created successfully // Reminder details with reminderId. }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("about", "Drinking water"); body.put("isCustom", true); body.put("timeInMS", 1638351344989); CometChat.callExtension("reminders", "POST", "/v1/reminder", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Reminder created successfully. // Reminder details with reminderId. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "reminders", type: .post, endPoint: "v1/reminder", body: ["about":"Drinking water", "isCustom":true, "timeInMS": 1638351344989], onSuccess: { (response) in // Reminder created successfully. // Reminder details with reminderId. }) { (error) in // Some error occured } ``` If the reminder has been created successfully, you will receive the reminder object with `reminderId` in the success response. ### List reminders List the reminders set by a user using the `CometChat.callExtension` method as shown below: ```js CometChat.callExtension('reminders', 'GET', 'v1/fetch', null).then(response => { // reminders array }).catch(error => { // Some error occured }); ``` ```java CometChat.callExtension("reminders", "GET", "/v1/fetch", null, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // reminders array } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "reminders", type: .get, endPoint: "v1/fetch", body: nil, onSuccess: { (response) in // reminders array }) { (error) in // Some error occured } ``` ### Delete reminders Reminders can be deleted using the `reminderId` as shown below: ```js CometChat.callExtension('reminders', 'DELETE', 'v1/reminder', { reminderId: "e9cda52a-3839-4fd5-a010-b70db136f0f1" }).then(response => { // Reminder deleted successfully }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body = new JSONObject(); body.put("reminderId", "e9cda52a-3839-4fd5-a010-b70db136f0f1"); CometChat.callExtension("reminders", "DELETE", "/v1/reminder", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Reminder deleted successfully } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "reminders", type: .delete, endPoint: "v1/reminder", body: ["reminderId": "e9cda52a-3839-4fd5-a010-b70db136f0f1"], onSuccess: { (response) in // Reminder deleted successfully }) { (error) in // Some error occured } ``` ### Edit reminders In case a reminder needs to be preponed or postponed, it can be done using the Edit reminders functionality. The following updates the reminder with `reminderId: "e9cda52a-3839-4fd5-a010-b70db136f0f1"` For editing, use the `CometChat.callExtension` method as shown below: ```js CometChat.callExtension('reminders', 'PUT', 'v1/reminder', { reminderId: "e9cda52a-3839-4fd5-a010-b70db136f0f1", about: 1, isCustom: false, timeInMS: 1638351344999 }).then(response => { // Reminder updated successfully. }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("about", ID_OF_THE_MESSAGE); body.put("isCustom", false); body.put("timeInMS", 1638351344989); CometChat.callExtension("reminders", "PUT", "/v1/reminder", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Reminder updated successfully. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "reminders", type: .put, endPoint: "v1/reminder", body: ["about":MESSAGE_ID, "isCustom":false, "timeInMS": 1638351344989], onSuccess: { (response) in // Reminder updated successfully. }) { (error) in // Some error occured } ``` For Message reminders, `timeInMS` can be updated.\ For Personal reminders, `timeInMS` & `about` can be updated. ### Receive reminders The user will receive reminders from a special user - `cc_reminder_bot` - that was configured before. These reminders are sent as messages with `category: custom` and `type: extension_reminders`. The `customData` object will have an `about` field that the user had mentioned while setting the reminder. Learn more about [Custom messages listener](/sdk/javascript/receive-message#real-time-messages) for receiving reminders. # Rich Media Preview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/rich-media-preview The Rich Media Preview Extension allows the developer to generate rich preview panels for all the popular sites. This extension fetches the first URL from the message for the generation of a preview. ## Before you begin 1. Sign up with [Iframely](https://iframely.com/embed). 2. Get their API key to configure the extension. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Rich Media Preview extension. 3. Open the Settings for this extension. 4. Enter the iFramely API Key. 5. Save your settings. ## How does it work? If the text message contains a URL, the extension will create a Preview using your iFramely credentials. These details can then be used to show a nice preview card for that URL. The information about the Preview will be updated later for the message and hence you need to implement the `onMessageEdited` listener. Please check our [Edit message](/sdk/javascript/edit-message) documentation under the SDK of your choice. Here is a sample response (for [https://stackoverflow.com](https://stackoverflow.com)): ```json "@injected": { "extensions": { "rich-media": { "url": "https://stackoverflow.com", "meta": { "description": "Stack Overflow | The World’s Largest Online Community for Developers", "title": "Stack Overflow - Where Developers Learn, Share, & Build Careers", "canonical": "https://stackoverflow.com/", "site": "Stack Overflow" }, "links": { "thumbnail": [ { "href": "https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon@2.png?v=73d79a89bded", "type": "image/png", "rel": [ "thumbnail", "og", "ssl" ], "content_length": 6562, "media": { "width": 316, "height": 316 } }, { "href": "https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a", "rel": [ "thumbnail", "ssl", "apple-touch-icon", "icon" ], "type": "image/png" } ], "icon": [ { "href": "https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a", "rel": [ "thumbnail", "ssl", "apple-touch-icon", "icon" ], "type": "image/png" }, { "href": "https://cdn.sstatic.net/Sites/stackoverflow/Img/favicon.ico?v=ec617d715196", "rel": [ "shortcut", "icon", "ssl" ], "type": "image/icon" } ] }, "rel": [ "summary", "ssl", "html5", "inline" ], "html": "
" } } } ```
## Implementation At the recipients' end, from the message object, you can fetch the metadata by calling the getMetadata() method. Using this metadata, you can fetch the Rich Media Embed. ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if (extensionsObject != null && extensionsObject.hasOwnProperty("rich-media")) { var richMediaObject = extensionsObject["rich-media"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("rich-media")) { JSONObject richMediaObject = extensionsObject.getJSONObject("rich-media"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject != null && extensionsObject.has("rich-media")) { val richMediaObject = extensionsObject.getJSONObject("rich-media") } } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["rich-media"] != nil { var richMediaObject = extensionsObject?["rich-media"] as! [String : Any] } } } ``` # Save Message Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/save-message ## Extension settings 1. Login to the [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Save message extension. ## How does it work? Save message extension provides you the ability to: 1. Save messages 2. Unsave messages 3. Fetch all the saved messages by the user. Saved messages are private and are visible to the user who has saved them. ### 1. Save a message To save a message, use the `callExtension` method provided by the SDK to make an HTTP POST request with the parameters as shown below. You need to pass the `msgId` of the message that has to be saved. ```js CometChat.callExtension('save-message', 'POST', 'v1/save', { "msgId": 111 }).then(response => { // { success: true } }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", 111); CometChat.callExtension("save-message", "POST", "/v1/save", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "save-message", type: .post, endPoint: "v1/save", body: ["msgId": 111] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### 2. Unsave a message To unsave a message, use the `callExtension` method provided by the SDK to make an HTTP DELETE request with the parameters as shown below. You need to pass the `msgId` of the message that needs to be unsaved. ```js CometChat.callExtension('save-message', 'DELETE', 'v1/unsave', { "msgId": 111 }).then(response => { // { success: true } }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", 111); CometChat.callExtension("save-message", "DELETE", "/v1/unsave", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "save-message", type: .delete, endPoint: "v1/unsave", body: ["msgId": 111] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### 3. Fetch saved messages To fetch the saved messages for a user, use the `callExtension` method provided by the SDK to make an HTTP GET request with the query parameters as shown below. ```js const URL = `v1/fetch`; CometChat.callExtension('save-message', 'GET', URL, null).then(response => { // {savedMessages: []} }) .catch(error => { // Error occured }); ``` ```java String URL = "/v1/fetch"; CometChat.callExtension("save-message", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // {savedMessages: []} } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "save-message", type: .get, endPoint: "v1/fetch", body: nil, onSuccess: { (response) in // {savedMessages: []} }) { (error) in // Some error occured } } ``` # Smart Replies (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/smart-replies **Legacy Notice**: This extension is already included as part of the core messaging experience (AI) and is scheduled for deprecation in the near future. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. The Smart Reply extension allows you to show quick reply options to a user so that they can easily respond to a message. We will always suggest 3 options; one positive, one neutral and one negative. We also add a category, in case you want to skip some suggestions. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Smart Reply extension. ## How does it work? When a user sends a message, our Smart Reply extension will add metadata while the message is in-flight. The recipient will receive the message with metadata suggesting the responses. At the recipients' end, from the message object, you can fetch the metadata by calling the getMetadata() method. Using this metadata, you can fetch suggested responses for the message. ```json "@injected": { "extensions": { "smart-reply": { "reply_positive": "", "reply_neutral": "", "reply_negative": "", "category": "" } } } ``` If the data is missing, it means that the extension has timed out. ## Implementation Using the Smart Reply extension, you can build a UI like this: ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("smart-reply") ) { var smartReplyObject = extensionsObject["smart-reply"]; var reply_positive = smartReplyObject["reply_positive"]; var reply_neutral = smartReplyObject["reply_neutral"]; var reply_negative = smartReplyObject["reply_negative"]; var category = smartReplyObject["category"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("smart-reply")) { JSONObject smartReply = extensionsObject.getJSONObject("smart-reply"); String reply_positive = smartReply.getString("reply_positive"); String reply_neutral = smartReply.getString("reply_neutral"); String reply_negative = smartReply.getString("reply_negative"); String category = smartReply.getString("category"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject.has("smart-reply")) { val smartReplyObject = extensionsObject.getJSONObject("smart-reply") if (smartReplyObject.has("reply_positive")) val reply_positive = smartReplyObject.getString("reply_positive") if (smartReplyObject.has("reply_neutral")) val reply_neutral = smartReplyObject.getString("reply_neutral") if (smartReplyObject.has("reply_negative")) val reply_negative = smartReplyObject.getString("reply_negative") if (smartReplyObject.has("category")) val category = smartReplyObject.getString("category") } } } } ``` ```swift var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["smart-reply"] != nil { var smartReply = extensionsObject?["smart-reply"] as! [String : Any] let reply_positive = smartReply["reply_positive"] let reply_neutral = smartReply["reply_neutral"] let reply_negative = smartReply["reply_negative"] let category = smartReply["category"] } } } ``` # Stickers Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/stickers The Stickers Extension is more like an image manager which allows you to quickly add/remove stickers directly from the dashboard. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Stickers extension. 3. Open the Settings for this extension. 4. Click on Save to start using Stickers with in your app. CometChat provides 14 Default Sets of stickers for your use. Apart from these 14 sets, you can also create your own sets. Moreover, you can also choose stickers from each set as per your liking and use only those in your app. ## How does it work? ### Loading stickers Before you start Sending or Receiving stickers in your app, you first have to load the Sticker Sets. In your app, you can add a section/drawer that shows the enabled stickers. A user can click on any of these stickers to send it in a chat. In order to load stickers, you can use the `callExtension` method provided by our SDKs. ```js CometChat.callExtension('stickers', 'GET', 'v1/fetch', null) .then(stickers => { // Stickers received }) .catch(error => { // Some error occured }); ``` ```java CometChat.callExtension("stickers", "GET", "/v1/fetch", null, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Stickers received here. } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "stickers", type: .get, endPoint: "v1/fetch", body: nil, onSuccess: { (response) in print("Success",response) }) { (error) in print("Error",error?.errorCode, error?.errorDescription) } ``` In response, you will get the following JSON which contains `defaultStickers` and `customStickers` arrays. Stickers with the same stickerSetId can be grouped together while displaying them in your application. ```json { "defaultStickers": [ { "stickerOrder": "4", "stickerSetId": "9bc4bf29-6913-4a95-84c5-53a385c8fa0f", "stickerUrl": "https://site.bear1.png", "stickerSetName": "Bear", "id": "530fe94e-e7b9-424b-8f6f-fa8454ae8d97", "stickerSetOrder": "1", "stickerName": "bear_1.png" }, { ... }, ... ], "customStickers":[ { "modifiedAt": "2020-06-03T14:28:17.339Z", "stickerOrder": "1", "stickerSetId": "70bcd62c-103a-4d8a-acc8-a9af3debd423", "stickerUrl": "https://images.com/812/hurray.png", "createdAt": "2020-04-25T10:41:42.697Z", "stickerSetName": "rejoice", "id": "dd8ab83a-b036-4220-9351-ad968152fd36", "stickerSetOrder": "1", "stickerName": "hurray" }, { ... }, ... ] } ``` ### Sending Stickers Stickers can be sent as a media message. You can check [Send message](/sdk/javascript/send-message) section (linked for JavaScript) of our SDKs for more details. Also, you can send stickers as [Custom message](/sdk/javascript/send-message#custom-message) and include the `incrementUnreadCount: true` in the metadata of that custom message. This will help you increment unread counts for Custom messages (in this case stickers). ### Receiving Stickers Stickers are images that can be received and displayed as any regular media message. In your application, you can use the `onMediaMessageReceived` listener in order to receive stickers. Refer to our [Receive Messages](/sdk/javascript/receive-message) documentation under the SDK of your choice. # Stipop Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/stickers-stipop *Learn how to integrate stickers by Stipop in your app.* Stipop is the world's trendiest sticker platform and creator community. ## Before you begin: 1. Sign up at [Stipop](https://stipop.io/). 2. On successful signup, provide the following details: 1. Application name 2. Website 3. Category 4. Sub-category 5. Region 6. App MAU 3. Click on Get Started once done. 4. You will be able to see the API Key on their Dashboard. Keep this handy. 5. In the left navigation pane, go to Settings and select the Application tab. 6. Copy the Application ID and keep this handy. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the extensions section and enable the Stipop extension. 3. Click on the settings button and enter your Stipop Application ID and API Key. 4. Save the settings once done. ## How does it work? The extension provides the following functionalities: 1. Get the current Trending stickers. 2. Search for stickers using a certain phrase or keyword This extension uses the `callExtension` method provided by the CometChat SDK. ### Get trending stickers The API call requires the following Query Parameters: | | | | | ----------- | ------ | ------------------------------------------------------------------------------------------------------------------------------- | | lang | string | Specify default language for regional stickers. Use a 2-letter ISO 639-1 language code. **Default Value: en** | | limit | int | The maximum number of stickers per page. Use pageNumber accordingly for optimized sticker view. **Default Value: 20 (max: 50)** | | pageNumber | int | Specify pageNumber to show limit number of stickers per page. | | countryCode | string | Specify default country for local stickers. Use a 2-letter ISO 3166-1 country code. **Default Value: US** | ```js const qs = `?lang=${lang}&limit=${limit}&pageNumber=${pageNumber}&countryCode=${contryCode}`; CometChat.callExtension('stickers-stipop', 'GET', 'v1/trending' + qs, null) .then(response => { // Stickers in response }) .catch(error => { // Error occured }); ``` ```java String URL = "/v1/trending?lang="+language+"&limit="+limit+"&pageNumber="+pageNumber+"&countryCode="+countryCode; CometChat.callExtension("stickers-stipop", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // Stickers } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "stickers-stipop", type: .get, endPoint: "v1/trending?lang="+language+"&limit="+limit+"&pageNumber="+pageNumber+"&countryCode="+countryCode, nil, onSuccess: { (response) in // Stickers }) { (error) in // Some error occured } } ``` ### Search for stickers The API call requires the following Query Parameters: | | | | | ---------- | ------ | ------------------------------------------------------------------------------------------------------------------------------- | | lang | string | Specify default language for regional stickers. Use a 2-letter ISO 639-1 language code. **Default Value: en** | | limit | int | The maximum number of stickers per page. Use pageNumber accordingly for optimized sticker view. **Default Value: 20 (max: 50)** | | pageNumber | int | Specify pageNumber to show limit number of stickers per page. | | query | string | The search term for finding stickers. | ```js const qs = `?lang=${lang}&limit=${limit}&pageNumber=${pageNumber}&query=${query}`; CometChat.callExtension('stickers-stipop', 'GET', 'v1/search' + qs, null) .then(response => { // Stickers in response }) .catch(error => { // Error occured }); ``` ```java String URL = "/v1/search?lang="+language+"&limit="+limit+"&pageNumber="+pageNumber+"&query="+query; CometChat.callExtension("stickers-stipop", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // Stickers } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "stickers-stipop", type: .get, endPoint: "/v1/search?lang="+language+"&limit="+limit+"&pageNumber="+pageNumber+"&query="+query, nil, onSuccess: { (response) in // Stickers }) { (error) in // Some error occured } } ``` # Tenor Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/tenor GIFs are a great way to change the tone or convey emotions in your conversations. Here's a guide which helps to implement Tenor in an easy and quick way. Let's get started! ## Before you begin 1. Sign up at [Tenor](https://tenor.com/developer/dashboard) and create a new app. 2. Enter your App name, description and click create. 3. Make note of the API key that has been created. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Tenor extension. 3. Click on the Settings button, enter your Tenor API key, and hit save. ## How does it work? This extension uses the `callExtension` method provided by the CometChat SDK. You can perform the following actions using this method: 1. Get trending GIFs 2. Search for GIFs ### Get Trending GIFs To list and show the most trending GIFs on Tenor, all you have to do is include the following parameters in your request. | key | Value | Description | | ------ | ------ | -------------------------------------------------------------------------------------------------------------- | | offset | number | Since you can get paginated results for trending GIFs, you can provide an offset and fetch results accordingly | | limit | number | The number of Trending GIFs that you want to fetch | Once you have set the above parameters, you can make a call to the extension as follows: ```js const URL = "v1/trending?offset=1&limit=15"; CometChat.callExtension("gifs-tenor", "GET", URL, null) .then((response) => { // GIFs data from Tenor }) .catch((error) => { // Error occured }); ``` ```java String URL = "/v1/trending?offset=1&limit=15"; CometChat.callExtension("gifs-tenor", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // GIFs data from Tenor } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "gifs-tenor", type: .get, endPoint: "v1/trending?offset=10&limit=15", body: nil, onSuccess: { (response) in // GIFs data from Tenor }) { (error) in // Some error occured } } ``` ### Search for GIFs Apart from listing the trending ones, the extension also allows searching for a particular GIF using the following parameters: | key | value | Description | | ------ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | offset | number | Since you can get paginated results for searches, you can provide an offset and fetch results accordingly. | | limit | number | The number of GIFs that you want to fetch as part of the search. | | lang | 2-letter ISO 639-1 language identifier | (Optional) Defaults to en. (Example values: es, fr, it.) | | query | string | Search term | Once you have all the above parameters, you can make a call to the extension as follows: ```js const URL = "v1/search?offset=1&limit=15&query=awesome"; CometChat.callExtension("gifs-tenor", "GET", URL, null) .then((response) => { // GIFs data from tenor }) .catch((error) => { // Error occured }); ``` ```java String URL = "/v1/search?offset=1&limit=15&query=awesome"; CometChat.callExtension("gifs-tenor", "GET", URL, null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // GIFs data from tenor } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "gifs-tenor", type: .get, endPoint: "v1/search?offset=10&limit=15&query=awesome", body: nil, onSuccess: { (response) in // GIFs data from tenor }) { (error) in // Some error occured } } ``` # Thumbnail Generation Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/thumbnail-generation The Thumbnail Generation extension will help you generate a thumbnail preview of an image or a video message. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to Extensions section and enable the Thumbnail Generation extension. ## How does it work? A small, medium and large thumbnail is generated for every attachment of a Media message of type video or image. For eg, if a Media message of type video is sent with 2 attachments, the links to these thumbnails are then provided in the metadata of the message as shown below: ```json "@injected": { "extensions": { "thumbnail-generation": { "url_small": "https://data.cometchat.io/a1/small.png", "url_medium": "https://data.cometchat.io/a1/medium.png", "url_large": "https://data.cometchat.io/a1/large.png", "attachments": [ { "data": { "name": "a1.mp4", "extension": "mp4", "mimeType": "video/mp4", "url": "http://commondatastorage.com/sample/a1.mp4", "thumbnails": { "url_small": "https://data.cometchat.io/a1/small.png", "url_medium": "https://data.cometchat.io/a1/medium.png", "url_large": "https://data.cometchat.io/a1/large.png", }, }, "error": null, }, { "data": { "name": "a2.mp4", "extension": "mp4", "mimeType": "video/mp4", "url": "http://data.cometchat.io/media/asdfasdf.mp4", "thumbnails": { "url_small": "https://data.cometchat.io/a2/small.png", "url_medium": "https://data.cometchat.io/a2/medium.png", "url_large": "https://data.cometchat.io/a2/large.png", }, }, "error": null, }, { "data": { "name": "a3.mp3", "extension": "mp3", "mimeType": "audio/mp3", "url": "http://data.cometchat.io/media/asdfasdf.mp3", "thumbnails": null, }, "error": { "code": "ERR_FILETYPE_NOT_SUPPORTED", "message": "Support only for jpg, jpeg, png, gif, mov, mpg, mpeg, mp4, wmv, avi", "devMessage": "Support only for jpg, jpeg, png, gif, mov, mpg, mpeg, mp4, wmv, avi", "httpStatusCode": 400, } } ] } } } ``` If the thumbnail-generation key is missing, it means that the extension is either not enabled or has timed out. The `url_small`, `url_medium` & `url_large` keys to the outside of `attachments` are the thumbnail URLs for the first attachment from the `attachments` array. These have been retained for backward compatibility only.\ You can iterate over `attachments` array for better implementation. ## Implementation You can make use of the `getMetadata()` method to extract the thumbnail details for a message. The `url` field is the link to the actual image or video. You can make use of `url_small`, `url_medium` & `url_large` keys for showing thumbnails based on the device of your end users. ```js const metadata = message.getMetadata(); if (metadata != null) { const injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { const extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("thumbnail-generation") ) { const { attachments } = extensionsObject["thumbnail-generation"]; for (const attachment of attachments) { if (!attachment.error) { const { url_small, url_medium, url_large } = attachment.data.thumbnails; // Use the urls accordingly. } } } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("thumbnail-generation")) { JSONObject tg = extensionsObject.getJSONObject("thumbnail-generation"); JSONArray attachments = tg.getJSONArray("attachments"); for (int i = 0; i < attachments.length(); i++) { JSONObject attachment = attachments.getJSONObject(i); JSONObject error = attachment.getJSONObject("error"); if (error == null) { JSONObject data = attachment.getJSONObject("data"); JSONObject thumbnails = data.getJSONObject("thumbnails"); String url_small = thumbnails.getString("url_small"); String url_medium = thumbnails.getString("url_medium"); String url_large = thumbnails.getString("url_large"); // Use the urls are per requirement } } } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injected = metadata.getJSONObject("@injected") if (injected != null && injected.has("extensions")) { val extensions = injectedJSONObject.getJSONObject("extensions") if (extensions != null && extensions.has("thumbnail-generation")) { val tg = extensions.getJSONObject("thumbnail-generation") val attachments = tg.getJSONArray("attachments") for (i in 0 until attachments.length()) { val attachment = attachments.getJSONObject(i) val error = attachment.getJSONObject("error") if (error == null) { val data = attachment.getJSONObject("data") val thumbnails = data.getJSONObject("thumbnails") val url_small = thumbnails.getString("url_small") val url_medium = thumbnails.getString("url_medium") val url_large = thumbnails.getString("url_large") } } } } } } ``` ```swift if let metaData = message?.metaData , let injected = metaData["@injected"] as? [String : Any], let extensions =injected["extensions"] as? [String : Any], let attachments = extensions["thumbnail-generation"] as? [[String : Any]] { for attachment in attachments { if let data = attachment["data"] as? [String:Any] , let thumbnails = data["thumbnails"] as? [String:any] { if let urlSmall = URL(string: thumbnails["url_small"] as? String) { // Use the url accordingly. } if let urlMedium = URL(string: thumbnails["url_medium"] as? String) { // Use the url accordingly. } if let urlLarge = URL(string: thumbnails["url_large"] as? String) { // Use the url accordingly. } // check for attachment.error if "thumbnails" is null } } } ``` Unlike image thumbnails, which are normally generated in milliseconds, video thumbnails may take a little longer. Before viewing the preview, we recommend verifying to see if the file exists. If the difference between message sentAt and the current time is less than 5 seconds, you can set a simple timer to monitor every second. # TinyURL Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/tinyurl *Learn how to minify the long website links in your text messages using TinyURL.* ## Before you begin 1. Sign up with [TinyURL](https://tinyurl.com/app/login) 2. Once you have logged in, click on Account in the top right corner. 3. In the left navigation pane, select API. 4. Create an API Token by giving it a name and permission to Create TinyURL. 5. Make note of the API Token as it will be required in Extension's settings. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the TinyURL extension. 3. Open the settings and enter the TinyURL API Token. 4. If you have chosen a paid plan, you can also save your BYO domain or subdomain. Default is set to `tinyurl.com` 5. Save your settings. BYO Domain If you don't plan on using a custom domain, please save `tinyurl.com` as the default value here. ## How does it work? This extension uses the `callExtension` method provided by CometChat SDK. You can call the extension as follows: ```js CometChat.callExtension("url-shortener-tinyurl", "POST", "v1/shorten", { text: "Your message with URL https://yourdomain.com/very/very/long/url", }) .then((response) => { // minifiedText in response }) .catch((error) => { // Error occured }); ``` ```java String URL = "/v1/shorten"; JSONObject body=new JSONObject(); body.put("text", "Your message with URL https://yourdomain.com/very/very/long/url"); CometChat.callExtension("url-shortener-tinyurl", "POST", URL, body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { // minifiedText from the extension } @Override public void onError(CometChatException e) { // Some error occured } }); ``` ```swift CometChat.callExtension(slug: "url-shortener-tinyurl", type: .post, endPoint: "v1/shorten", body: ["text": "Your message with URL https://yourdomain.com/very/very/long/url"], onSuccess: { (response) in // minifiedText from the extension }) { (error) in // Some error occured } } ``` # User Roles And Permissions In CometChat Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/user-roles-and-permissions CometChat provides a comprehensive roles and permissions system to ensure that team members have the appropriate level of access to platform features and settings. Properly assigning these roles helps maintain security, streamline workflows, and delegate responsibilities effectively. ## User Roles Overview * **Owner** – Unrestricted access to every feature, including Plans & Billing. * **Admin** – Full access to all sections except Plans & Billing. * **Moderator** – Manages content and user interactions; limited to moderation-related features. * **Developer** – Configures integrations and technical settings; does not have access to moderation controls. ## Permissions Matrix | **Section** | **Permission** | **Owner** | **Admin** | **Moderator** | **Developer** | | ------------------- | -------------------- | --------- | --------- | ------------- | ------------- | | **Overview** | Overview | Yes | Yes | No | No | | **Integrate** | Integrate | Yes | Yes | No | Yes | | **Manage** | User | Yes | Yes | Yes | Yes | | | Group | Yes | Yes | Yes | Yes | | | User Roles | Yes | Yes | Yes | Yes | | **Chats** | Logs | Yes | Yes | Yes | Yes | | | Widget | Yes | Yes | No | Yes | | | Features | Yes | Yes | No | Yes | | | Moderation | Yes | Yes | Yes | No | | **Insights** | Insights | Yes | Yes | Yes | Yes | | **Settings** | Settings | Yes | Yes | No | No | | **Calls** | Logs | Yes | Yes | Yes | Yes | | | Insights | Yes | Yes | Yes | Yes | | | Moderation | Yes | Yes | Yes | No | | **AI Chatbot** | Bots | Yes | Yes | No | Yes | | | Instructions | Yes | Yes | No | Yes | | **Non-AI Bots** | Bots | Yes | Yes | No | Yes | | | Instructions | Yes | Yes | No | Yes | | **Notifications** | Notifications | Yes | Yes | Yes | Yes | | | Legacy Notifications | Yes | Yes | Yes | Yes | | | Insights | Yes | Yes | Yes | Yes | | **Application** | Credentials | Yes | Yes | No | Yes | | | Webhooks | Yes | Yes | No | Yes | | | Legacy Webhooks | Yes | Yes | Yes | Yes | | | Team Members | Yes | Yes | Yes | Yes | | **Plans & Billing** | Settings | No | No | No | No | # Live Streaming By API Video (Deprecated) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/video-broadcasting Deprecated: This extension is no longer maintained and will not receive further updates. The Live streaming by api.video extension enables you to set up a live stream to broadcast to a large number of users. ## Before you begin 1. Sign up with [api.video](https://api.video/) 2. Get your **API Key**. Make sure you set up a payment method with them in order to get the **Production API key**. The Sandbox API Key will not work. 3. Broadcaster needs to download and install [OBS](https://obsproject.com/), a free and open-source software. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Live Streaming (Video Broadcasting) extension. 3. Open the Settings for this extension. 4. Enter the api.video Production API Key. 5. You can also select whether you want to record the live stream. ## How does it work? This extension delivers 2 different configurations: 1. The broadcaster gets the `server` address and `streamKey`. 2. The viewers get the `embed link` along with a few more details. ### Broadcaster #### 1. Get broadcast details The CometChat SDKs provide a `callExtension` method that can be called to trigger this extension. The broadcaster has to provide the following: 1. Receiver type - `user` or `group` 2. The `receiver` of the broadcast link (can be a `uid` for a user or `guid` in case of a group) ```js CometChat.callExtension('broadcast', 'POST', 'v1/broadcast', { receiverType: 'user/group', receiver: 'uid/guid' }).then(response => { // Success response }).catch(error => { // Some error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("receiverType", "user/group"); body.put("receiver", "uid/guid"); CometChat.callExtension("broadcast", "POST", "/v1/broadcast", body, new CometChat.CallbackListener() { @Override public void onSuccess(JSONObject responseObject) { // Broadcaster details } @Override public void onError(CometChatException e) { // Some error occured. } }); ``` ```swift CometChat.callExtension(slug: "broadcast", type: .post, endPoint: "v1/broadcast", body: ["receiverType":"user/group", "receiver":"uid/guid"], onSuccess: { (response) in // Success response }) { (error) in // Some error occured } ``` If the call is successful, the method will return the following JSON response: ```json { "broadcaster": { "server": "rtmp://broadcast.api.video_s", "streamKey": "04cb0167-5za4-4ba6-831x-efa28e1917o3" } } ``` #### 2. Start Streaming In order to start streaming/broadcasting, launch OBS studio and go to: **Settings > Stream > Select `Custom`** from drop-down and enter the `server` and `streamKey`**.** Once the details have been entered, click OK and close the Settings Panel. Next, you can click on the "Start Streaming" button. ### Viewers The viewers can either be a Group or a User. The recipient(s) will receive a text message with `embed link` and `metadata` as follows: ```json Hello! I’m currently broadcasting. Use this link to join the broadcast: https://embed.api.video/live/li3WPpN3Ixj7dTDwdtL0dKt1 ``` ```json "@injected": { "extensions": { "broadcast": { "hls": "https://live.api.video/li6xl2dCcboxPGTFq1D4Fhmb.m3u8", "iframe": "", "player": "https://embed.api.video/live/li6xl2dCcboxPdGTFq1D4Fhmb", "thumbnail": "https://cdn.api.video/live/li6xl2dCcboxPGTFq1D4Fhmb/thumbnail.jpg" } } } ``` ## Implementation At the viewers' end, from the message object, you can fetch the metadata by calling the getMetadata() method. Using this metadata, you can fetch the broadcast details. ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("broadcast") ) { var broadcastObject = extensionsObject["broadcast"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("broadcast")) { JSONObject broadcastObject = extensionsObject.getJSONObject("broadcast"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject != null && extensionsObject.has("broadcast")) { val broadcastObject = extensionsObject.getJSONObject("broadcast") } } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["broadcast"] != nil { var broadcastObject = extensionsObject?["broadcast"] as! [String : Any] } } } ``` # Voice Transcription Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/voice-transcription Voice transcription extension allows you to convert an audio message into text. ## Before you begin 1. Sign up with [Rev.ai](https://rev.ai/) 2. Get your `Access Token` for configuring this extension. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Voice Transcription extension. 3. Open the Settings for this extension. 4. Enter the Rev.ai Access Token, and click on save. ## How does it work? Once the Extension is enabled for your App and the settings are done, the recipients will receive metadata with the transcription details. The transcription information will be updated later for the message and hence you need to implement the `onMessageEdited` listener. Please check our [Edit ,message](/sdk/javascript/edit-message) documentation under the SDK of your choice. Here is a sample response: ```json "@injected": { "extensions": { "voice-transcription": { "transcribed_message": "This is a test" } } ``` If the voice-transcription key is missing, it means that either the extension is not enabled or has timed out. ## Implementation At the recipients' end, from the message object, you can fetch the metadata by calling the getMetadata() method. Using this metadata, you can fetch the Rich Media Embed. ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("voice-transcription") ) { var voiceTranscriptionObject = extensionsObject["voice-transcription"]; var transcribed_message = voiceTranscriptionObject["transcribed_message"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("voice-transcription")) { JSONObject transcriptionObject = extensionsObject.getJSONObject("voice-transcription"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject != null && extensionsObject.has("voice-transcription")) { val transcriptionObject = extensionsObject.getJSONObject("voice-transcription") } } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["voice-transcription"] != nil { var transcriptionObject = extensionsObject?["voice-transcription"] as! [String : Any] } } } ``` ```dart Map? metadata = message.metadata; try { if (metadata != null) { Map? injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.containsKey("extensions")) { Map extensionsObject = injectedObject["extensions"]; if (extensionsObject.containsKey("voice-transcription")) { Map voiceTranscriptionObject = extensionsObject["voice-transcription"]; List attachments = voiceTranscriptionObject['attachments']; for (var attachment in attachments) { if (attachment['error'] == null) { final attachmentData = attachment['data']; final transcribedMessage = attachmentData['transcribed_message']; } } } } } } catch (e, stack) { debugPrint("$stack"); } ``` # Events Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/webhooks-events ### Why is Idempotency Important? Idempotency ensures that your system processes webhook events reliably, even in cases duplicate events due to retries. Webhooks are inherently asynchronous, and network issues or endpoint failures can lead to retries. Without idempotency, the same event could be processed multiple times, causing unintended side effects such as duplicate records, inconsistent states, or incorrect business logic execution. By implementing idempotency, you can: Prevent Duplicate Processing: Ensure that the same event is not processed more than once, even if it is retried. Maintain Data Integrity: Avoid creating duplicate records or inconsistent states in your database. Improve System Reliability: Handle retries gracefully and ensure your system behaves predictably under all circumstances. Enhance Debugging and Monitoring: Easily identify and resolve issues related to duplicate or failed events. ## Messaging events ### message\_sent The hook triggers after the message is sent. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.message.id` * **Purpose**: Ensures the message is processed only once. ```json { "trigger": "message_sent", "data": { "message": { "id": "1", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "message", "type": "text", "data": { "text": "hi", "entities": { "sender": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696934440 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } } }, "sentAt": 1696934912, "updatedAt": 1696934912 } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_edited The hook triggers after the message is edited. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.message.id` & `data.message.editedAt` * **Purpose**: Tracks edits to ensure the same edit is not processed multiple times. ```json { "trigger": "message_edited", "data": { "message": { "id": "2", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "action", "type": "message", "data": { "action": "edited", "entities": { "by": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696934440 }, "entityType": "user" }, "for": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" }, "on": { "entity": { "id": "1", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "message", "type": "text", "data": { "text": "hello", "entities": { "sender": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "lastActiveAt": 1696934440 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } } }, "sentAt": 1696934912, "editedAt": 1696934985, "editedBy": "cometchat-uid-1", "deliveredAt": 1696934912, "readAt": 1696934950, "updatedAt": 1696934985 }, "entityType": "message" } }, }, "sentAt": 1696934985, "updatedAt": 1696934985 } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_deleted The hook triggers after the message is deleted. **Idempotency Details** * **Key**: `webhook`,`trigger` & `data.message.id` * **Purpose**: Tracks deletions to prevent duplicate processing. ```json { "trigger": "message_deleted", "data": { "message": { "id": "3", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "action", "type": "message", "data": { "action": "deleted", "entities": { "by": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696934440 }, "entityType": "user" }, "for": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" }, "on": { "entity": { "id": "2", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "message", "type": "text", "data": { "entities": { "sender": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "lastActiveAt": 1696934440 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } } }, "sentAt": 1696934912, "deliveredAt": 1696934912, "readAt": 1696934950, "deletedAt": 1696935005, "updatedAt": 1696935005, "deletedBy": "cometchat-uid-1" }, "entityType": "message" } }, }, "sentAt": 1696935005, "updatedAt": 1696935005 } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_delivery\_receipt The hook triggers when the client chat application confirms with Cometchat servers that a message was delivered. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.body.messageId`,`data.body.timestamp` & `data.sender` * **Purpose**: Tracks delivery receipts to ensure they are processed only once. ```json { "trigger": "message_delivery_receipt", "data": { "receiver": "cometchat-uid-1", "receiverType": "user", "type": "receipts", "sender": "cometchat-uid-2", "messageSender": "cometchat-uid-1", "body": { "action": "delivered", "messageId": "57", "user": { "hasBlockedMe": false, "blockedByMe": false, "deactivatedAt": 0, "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "lastActiveAt": 1696934489, "role": "default", "status": "online" }, "timestamp": 1696934912 } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_read\_receipt The hook triggers when the client chat application confirms with Cometchat servers that a message was read. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.body.messageId`,`data.body.timestamp` & `data.sender` * **Purpose**: Tracks read receipts to ensure they are processed only once. ```json { "trigger": "message_read_receipt", "data": { "receiver": "cometchat-uid-1", "receiverType": "user", "type": "receipts", "sender": "cometchat-uid-2", "messageSender": "cometchat-uid-1", "body": { "action": "read", "messageId": "57", "user": { "hasBlockedMe": false, "blockedByMe": false, "deactivatedAt": 0, "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "lastActiveAt": 1696934489, "role": "default", "status": "online" }, "timestamp": 1696934950 } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_reaction\_added The hook triggers after a user reacts to a message. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.reaction.id` & `data.reaction.uid` * **Purpose**: Tracks reactions to ensure they are processed only once. ```json { "trigger": "message_reaction_added", "data": { "reaction": { "id": "", "messageId": "", "reaction": "🏒", "uid": "cometchat-uid-1", "reactedAt": 1700655536, "reactedBy": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "offline", "role": "default", "lastActiveAt": 1700652818 } } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_reaction\_removed The hook triggers after a user un-reacts to a message. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.reaction.id` & `data.reaction.uid` * **Purpose**: Tracks reaction removals to ensure they are processed only once. ```json { "trigger": "message_reaction_removed", "data": { "reaction": { "id": "", "messageId": "", "reaction": "🏒", "uid": "cometchat-uid-1", "reactedAt": 1700231289, "reactedBy": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "offline", "role": "default", "lastActiveAt": 1700652818 } } }, "appId": "", "region": "", "webhook": "" } ``` ### user\_mentioned The hook triggers after a user is mentioned in the message. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.message.id` & `data.message.mentions.uid` * **Purpose**: Tracks mentions to ensure they are processed only once. ```json { "trigger": "user_mentioned", "data": { "message": { "id": "4", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "message", "type": "text", "data": { "text": "Hi <@uid:cometchat-uid-2>", "entities": { "sender": { "entity": { "uid": "cometchat-uid-1", "name": "George Alan", "status": "offline", "role": "default", "createdAt": 1702025699 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-2", "name": "cometchat-uid-1", "status": "available", "role": "default", "lastActiveAt": 1702028122, "createdAt": 1701931840, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } }, "mentions": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "cometchat-uid-1", "status": "available", "role": "default", "lastActiveAt": 1702028122, "createdAt": 1701931840, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } } }, "sentAt": 1702028666, "updatedAt": 1702028666 } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_delivered\_to\_all The hook triggers when the client chat application confirms with Cometchat servers that a message was delivered to all the participants of the group. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.body.messageId` & `data.body.timestamp` * **Purpose**: Tracks group delivery to ensure it is processed only once. ```json { "trigger": "message_delivered_to_all", "data": { "receiver": "group__1720436412627", "receiverType": "group", "type": "receipts", "sender": "app_system", "messageSender": "superhero2", "body": { "messageId": "385", "timestamp": 1722245922, "action": "deliveredToAll", "user": { "uid": "app_system", "name": "System", "avatar": "", "role": "default", "status": "offline" } } }, "appId": "", "region": "", "webhook": "" } ``` ### message\_read\_by\_all The hook triggers when the client chat application confirms with Cometchat servers that a message was read by all the participants of a group. **Idempotency Details** * **Key**: `webhook`,`trigger`,`data.body.messageId` & `data.body.timestamp` * **Purpose**: Tracks group read receipts to ensure they are processed only once. ```json { "trigger": "message_read_by_all", "data": { "receiver": "group__1720436412627", "receiverType": "group", "type": "receipts", "sender": "app_system", "messageSender": "superhero2", "body": { "messageId": "385", "timestamp": 1722245922, "action": "readByAll", "user": { "uid": "app_system", "name": "System", "avatar": "", "role": "default", "status": "offline" } } }, "appId": "", "region": "", "webhook": "" } ``` The following events will be available only if the **Enhanced Messaging Status** feature is enabled for your app. * `message_delivered_to_all`, * `message_read_by_all` ## User-related events ### user\_blocked The hook triggers when a user blocks another user. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.users.uid` * **Purpose**: Tracks user block events to ensure they are processed only once. ```json { "trigger": "user_blocked", "data": { "users": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696935105 } }, "appId": "", "region": "", "webhook": "" } ``` ### user\_unblocked The hook triggers when a user unblocks another user. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.users.uid` * **Purpose**: Tracks user unblock events to ensure they are processed only once. ```json { "trigger": "user_unblocked", "data": { "users": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696934491, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696935105 } }, "appId": "", "region": "", "webhook": "" } ``` ### user\_connection\_status\_changed The hook triggers after a user connects/disconnects from the websocket server. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.user.uid`+`data.user.status`+`data.timestamp` * **Purpose**: Tracks user connection status changes to ensure they are processed only once. ```json { "trigger": "user_connection_status_changed", "data": { "timestamp": 1696935103114, "user": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "offline", "role": "default", "lastActiveAt": 1693916686 }, "status": "offline", "currentConnection": { "action": "disconnected", "appInfo": { "version": "3.0.12", "apiVersion": "v3.0", "origin": "http://localhost:5173", "uts": 1696934440846, "clientIp": "3.128.113.92" }, "platform": "javascript", "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", "connectedAt": 1696934440982 }, "userPresenceChanged": true }, "appId": "", "region": "", "webhook": "" } ``` ## Group events ### group\_member\_banned This hooks triggers after members are banned from a group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member bans to ensure they are processed only once. ```json { "trigger": "group_member_banned", "data": { "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 1, "conversationId": "group_group__1696932914913", "createdAt": 1696932915, "owner": "cometchat-uid-1", "updatedAt": 1696933533, "onlineMembersCount": 1 }, "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "offline", "role": "default", "lastActiveAt": 1695751453, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696932834 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_member\_unbanned The hook triggers after members are unbanned from a group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member unbans to ensure they are processed only once. ```json { "trigger": "group_member_unbanned", "data": { "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "offline", "role": "default", "lastActiveAt": 1695751453, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } }, "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 1, "conversationId": "group_cometchat-guid-1", "createdAt": 1696932915, "owner": "cometchat-uid-1", "updatedAt": 1696933533, "onlineMembersCount": 1 }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696932834 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_member\_scope\_changed The hook triggers if the scope of a member changes in a group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member scope changes to ensure they are processed only once. ```json { "trigger": "group_member_scope_changed", "data": { "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696933928, "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "scope": "admin", "oldScope": "participant" } }, "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 2, "conversationId": "group_cometchat-guid-1", "createdAt": 1695722891, "owner": "cometchat-uid-1", "updatedAt": 1696933925, "onlineMembersCount": 2 }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696933934 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_created The hook triggers after the group is created. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.group.createdAt` * **Purpose**: Tracks group creation to ensure it is processed only once. ```json { "trigger":"group_created", "data":{ "group":{ "guid":"cometchat-guid-1", "name":"Hiking Group", "type":"public", "scope":"admin", "membersCount":1, "joinedAt":1696932915, "conversationId":"group_cometchat-guid-1", "hasJoined":true, "createdAt":1696932915, "owner":"cometchat-uid-1" }, "members":{ "cometchat-uid-1":{ "uid":"cometchat-uid-1", "name":"Andrew Joseph", "status":"available", "role":"default", "lastActiveAt":1696932834 } } }, "appId":"", "region":"", "webhook":"" } ``` ### group\_updated The hook triggers after the group is updated. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.group.updatedAt` * **Purpose**: Tracks group updates to ensure they are processed only once. ```json { "trigger": "group_updated", "data": { "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 2, "conversationId": "group_cometchat-guid-1", "createdAt": 1695728507, "owner": "cometchat-uid-2", "updatedAt": 1696934048, "updatedBy": "cometchat-uid-1", "onlineMembersCount": 2 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_deleted The hook triggers after the group is deleted. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.group.createdAt` * **Purpose**: Tracks group deletions to ensure they are processed only once. ```json { "trigger": "group_deleted", "data": { "group": { "guid": "cometchat-guid-1", "name": "1234", "type": "public", "membersCount": 1, "conversationId": "group_cometchat-guid-1", "createdAt": 1695722912, "owner": "cometchat-uid-1", "updatedAt": 1695817083, "updatedBy": "cometchat-uid-1", "onlineMembersCount": 1 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_member\_joined The hook triggers after a user joins a group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member joins to ensure they are processed only once. ```json { "trigger": "group_member_joined", "data": { "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696933689 } }, "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 2, "conversationId": "group_cometchat-guid-1", "createdAt": 1695728507, "owner": "cometchat-uid-1", "updatedAt": 1696933691, "onlineMembersCount": 1 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_member\_left The hook triggers after a user leaves the group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member departures to ensure they are processed only once. ```json { "trigger": "group_member_left", "data": { "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696933689 } }, "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 1, "conversationId": "group_cometchat-guid-1", "createdAt": 1695722891, "owner": "cometchat-uid-1", "updatedAt": 1696933827, "onlineMembersCount": 1 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_member\_added The hook triggers after members are added to a group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member additions to ensure they are processed only once. ```json { "trigger": "group_member_added", "data": { "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 2, "conversationId": "group_cometchat-guid-1", "createdAt": 1696932915, "owner": "cometchat-uid-1", "onlineMembersCount": 1 }, "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "offline", "role": "default", "lastActiveAt": 1695751453, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696932834 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_member\_kicked This hook triggers after members are kicked from a group. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.members.uid`+`data.group.updatedAt` * **Purpose**: Tracks group member removals to ensure they are processed only once. ```json { "trigger": "group_member_kicked", "data": { "members": { "cometchat-uid-2": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1696933689, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" } }, "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 1, "conversationId": "group_cometchat-guid-1", "createdAt": 1695722891, "owner": "cometchat-uid-1", "updatedAt": 1696933889, "onlineMembersCount": 8 }, "by": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696933881 } }, "appId": "", "region": "", "webhook": "" } ``` ### group\_owner\_transferred The hook triggers if the owner of the group is changed. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.group.guid`+`data.group.updatedAt` * **Purpose**: Tracks group ownership transfers to ensure they are processed only once. ```json { "trigger": "group_owner_transferred", "data": { "group": { "guid": "cometchat-guid-1", "name": "Hiking Group", "type": "public", "membersCount": 2, "conversationId": "group_cometchat-guid-1", "createdAt": 1695728507, "owner": "cometchat-uid-2", "updatedAt": 1696933737, "updatedBy": "cometchat-uid-1", "onlineMembersCount": 2, "oldOwner": "cometchat-uid-1" } }, "appId": "", "region": "", "webhook": "" } ``` ## Call & Meeting events ### call\_initiated The hook triggers when the call is initiated. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.call.id`+`data.call.sentAt` * **Purpose**: Tracks call initiation to ensure it is processed only once. ```json { "trigger": "call_initiated", "data": { "call": { "id": "52", "conversationId": "cometchat-uid-1_user_cometchat-uid-5", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-5", "category": "call", "type": "audio", "data": { "action": "initiated", "entities": { "by": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696933934 }, "entityType": "user" }, "for": { "entity": { "uid": "cometchat-uid-5", "name": "John Paul", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp", "status": "offline", "role": "default", "conversationId": "cometchat-uid-1_user_cometchat-uid-5" }, "entityType": "user" }, "on": { "entity": { "sessionid": "", "conversationId": "cometchat-uid-1_user_cometchat-uid-5", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-5", "status": "initiated", "type": "audio", "data": { "entities": { "sender": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1696933934 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-5", "name": "John Paul", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp",, "status": "offline", "role": "default", "conversationId": "cometchat-uid-1_user_cometchat-uid-5" }, "entityType": "user" } } }, "initiatedAt": 1696934199, "joinedAt": 1696934199 }, "entityType": "call" } }, "resource": "WEB-3_0_12-acfa8397-42f0-4f19-bc28-bc7db316ecaf-1696933879599" }, "sentAt": 1696934199, "updatedAt": 1696934199 } }, "appId": "", "region": "", "webhook": "" } ``` ### call\_started The hook triggers when the call is started. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.created_at` * **Purpose**: Tracks call start events to ensure they are processed only once. ```json { "trigger": "call_started", "data": { "created_at": 1696934572, "sessionId": "" }, "type": "call", "appId": "", "region": "", "webhook": "" } ``` ### call\_participant\_joined The hook triggers when a participant joins the call. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.occupant.joined_at` * **Purpose**: Tracks participant joins to ensure they are processed only once. ```json { "trigger": "call_participant_joined", "data": { "occupant": { "joined_at": 1696934573, "audio_call": "true", "name": "Andrew Joseph" }, "initial_config": { "is_video_muted": "false", "start_recording_on_call_start": "false", "call_version": "2.3.0", "is_audio_muted": "false", "sdk": "react", "mode": "DEFAULT", "platform": "web", "is_audio_only": "true" }, "sessionId": "" }, "type": "call", "appId": "", "region": "", "webhook": "" } ``` ### call\_participant\_left The hook triggers when a participant leaves the call. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.occupant.left_at` * **Purpose**: Tracks participant departures to ensure they are processed only once. ```json { "trigger": "call_participant_left", "data": { "occupant": { "joined_at": 1696934501, "audio_call": "true", "left_at": 1696934553, "name": "George Alan" }, "sessionId": "" }, "type": "call", "appId": "", "region": "", "webhook": "" } ``` ### call\_ended The hook triggers when the call is ended. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.destroyed_at` * **Purpose**: Tracks call end events to ensure they are processed only once. ```json { "trigger": "call_ended", "data": { "all_occupants": [ { "joined_at": 1696934501, "audio_call": "true", "left_at": 1696934553, "name": "George Alan" }, { "joined_at": 1696934501, "audio_call": "true", "left_at": 1696934551, "name": "Andrew Joseph" } ], "destroyed_at": 1696934553, "created_at": 1696934501, "sessionId": "" }, "type": "call", "appId": "", "region": "", "webhook": "" } ``` ### call\_busy This hook is triggered when a 1-on-1 call cannot be connected because the recipient is already on another call (i.e., their line is busy). Note: This event is exclusive to 1-on-1 calls. In group calls, all participants can join at any time, so a "busy" state does not apply. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.call.id`+`data.call.sentAt` * **Purpose**: Tracks call busy events to ensure they are processed only once. ```json { "trigger": "call_busy", "data": { "call": { "id": "43414", "conversationId": "superhero1_user_superhero3", "sender": "superhero3", "receiverType": "user", "receiver": "superhero1", "category": "call", "type": "audio", "data": { "action": "busy", "entities": { "by": { "entity": { "uid": "superhero3", "name": "Spiderman", "status": "available", "role": "default", "lastActiveAt": 1744959907 }, "entityType": "user" }, "for": { "entity": { "uid": "superhero1", "name": "Iron Man New 2", "metadata": { "metadata": "updated_653" }, "status": "available", "lastActiveAt": 1744960245, "conversationId": "superhero1_user_superhero3" }, "entityType": "user" }, "on": { "entity": { "sessionid": "v1.us.258520c054f20343.1744960250fba0641a3d6f635262e35c07dca5acfb6fa94127", "conversationId": "superhero1_user_superhero3", "sender": "superhero1", "receiverType": "user", "receiver": "superhero3", "status": "busy", "type": "audio", "data": { "entities": { "receiver": { "entity": { "conversationId": "superhero1_user_superhero3", "lastActiveAt": 1744959907, "name": "Spiderman", "role": "default", "status": "available", "uid": "superhero3" }, "entityType": "user" }, "sender": { "entity": { "lastActiveAt": 1744960245, "metadata": { "metadata": "updated_653" }, "name": "Iron Man New 2", "status": "available", "uid": "superhero1" }, "entityType": "user" } } }, "initiatedAt": 1744960250 }, "entityType": "call" } }, "resource": "WEB-4_0_10-942b534c-b606-4d44-90c3-878c60eb3a63-1744959889623" }, "sentAt": 1744960250, "updatedAt": 1744960250 } }, "appId": "", "region": "", "webhook": "" } ``` ### call\_cancelled The hook triggers when the call is cancelled. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.call.id`+`data.call.sentAt` * **Purpose**: Tracks call cancelled events to ensure they are processed only once. ```json { "trigger": "call_cancelled", "data": { "call": { "id": "43408", "conversationId": "superhero3_user_superhero4", "sender": "superhero4", "receiverType": "user", "receiver": "superhero3", "category": "call", "type": "audio", "data": { "action": "cancelled", "entities": { "by": { "entity": { "uid": "superhero4", "name": "Wolverine", "status": "available", "role": "default", "lastActiveAt": 1744959814 }, "entityType": "user" }, "for": { "entity": { "uid": "superhero3", "name": "Spiderman", "status": "available", "role": "default", "lastActiveAt": 1744959907, "conversationId": "superhero3_user_superhero4" }, "entityType": "user" }, "on": { "entity": { "sessionid": "v1.us.258520c054f20343.1744960108582f85230d0552516bdac185a6bd862eeac55f78", "conversationId": "superhero3_user_superhero4", "sender": "superhero4", "receiverType": "user", "receiver": "superhero3", "status": "cancelled", "type": "audio", "data": { "entities": { "receiver": { "entity": { "conversationId": "superhero3_user_superhero4", "lastActiveAt": 1744959907, "name": "Spiderman", "role": "default", "status": "available", "uid": "superhero3" }, "entityType": "user" }, "sender": { "entity": { "lastActiveAt": 1744959814, "name": "Wolverine", "role": "default", "status": "available", "uid": "superhero4" }, "entityType": "user" } } }, "initiatedAt": 1744960108 }, "entityType": "call" } }, "resource": "WEB-4_0_10-837115e3-f277-4105-8f1f-4e19a1a7f2be-1744959734040" }, "sentAt": 1744960111, "updatedAt": 1744960111 } }, "appId": "", "region": "", "webhook": "" } ``` ### call\_rejected This hook is triggered when a 1-on-1 call is explicitly rejected by the recipient. In group calls, this event is not triggered—since the call remains active as long as at least one member joins, even if others reject it. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.call.id`+`data.call.sentAt` * **Purpose**: Tracks call rejected events to ensure they are processed only once. ```json { "trigger": "call_rejected", "data": { "call": { "id": "43406", "conversationId": "superhero3_user_superhero4", "sender": "superhero3", "receiverType": "user", "receiver": "superhero4", "category": "call", "type": "audio", "data": { "action": "rejected", "entities": { "by": { "entity": { "uid": "superhero3", "name": "Spiderman", "status": "available", "role": "default", "lastActiveAt": 1744959907 }, "entityType": "user" }, "for": { "entity": { "uid": "superhero4", "name": "Wolverine", "status": "available", "role": "default", "lastActiveAt": 1744959814, "conversationId": "superhero3_user_superhero4" }, "entityType": "user" }, "on": { "entity": { "sessionid": "v1.us.258520c054f20343.1744960087681ed39d02b69199ee4e0cf9d9173dc6c643461e", "conversationId": "superhero3_user_superhero4", "sender": "superhero4", "receiverType": "user", "receiver": "superhero3", "status": "rejected", "type": "audio", "data": { "entities": { "receiver": { "entity": { "conversationId": "superhero3_user_superhero4", "lastActiveAt": 1744959907, "name": "Spiderman", "role": "default", "status": "available", "uid": "superhero3" }, "entityType": "user" }, "sender": { "entity": { "lastActiveAt": 1744959814, "name": "Wolverine", "role": "default", "status": "available", "uid": "superhero4" }, "entityType": "user" } } }, "initiatedAt": 1744960087 }, "entityType": "call" } }, "resource": "WEB-4_0_10-942b534c-b606-4d44-90c3-878c60eb3a63-1744959889623" }, "sentAt": 1744960092, "updatedAt": 1744960092 } }, "appId": "", "region": "", "webhook": "" } ``` ### call\_unanswered This hook is triggered when a call goes unanswered. For group calls, the call is considered unanswered only if none of the members join. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.call.id`+`data.call.sentAt` * **Purpose**: Tracks call unanswered events to ensure they are processed only once. ```json { "trigger": "call_unanswered", "data": { "call": { "id": "43410", "conversationId": "superhero3_user_superhero4", "sender": "superhero4", "receiverType": "user", "receiver": "superhero3", "category": "call", "type": "audio", "data": { "action": "unanswered", "entities": { "by": { "entity": { "uid": "superhero4", "name": "Wolverine", "status": "available", "role": "default", "lastActiveAt": 1744959814 }, "entityType": "user" }, "for": { "entity": { "uid": "superhero3", "name": "Spiderman", "status": "available", "role": "default", "lastActiveAt": 1744959907, "conversationId": "superhero3_user_superhero4" }, "entityType": "user" }, "on": { "entity": { "sessionid": "v1.us.258520c054f20343.17449601247f75e0a5c7b9601b32e9fb26645c34975bc6c93d", "conversationId": "superhero3_user_superhero4", "sender": "superhero4", "receiverType": "user", "receiver": "superhero3", "status": "unanswered", "type": "audio", "data": { "entities": { "receiver": { "entity": { "conversationId": "superhero3_user_superhero4", "lastActiveAt": 1744959907, "name": "Spiderman", "role": "default", "status": "available", "uid": "superhero3" }, "entityType": "user" }, "sender": { "entity": { "lastActiveAt": 1744959814, "name": "Wolverine", "role": "default", "status": "available", "uid": "superhero4" }, "entityType": "user" } } }, "initiatedAt": 1744960124 }, "entityType": "call" } }, "resource": "WEB-4_0_10-837115e3-f277-4105-8f1f-4e19a1a7f2be-1744959734040" }, "sentAt": 1744960170, "updatedAt": 1744960170 } }, "appId": "", "region": "", "webhook": "" } ``` ### meeting\_started The hook triggers when a meeting is started. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.created_at` * **Purpose**: Tracks meeting start events to ensure they are processed only once. ```json { "trigger": "meeting_started", "data": { "created_at": 1696934692, "sessionId": "" }, "type": "meet", "appId": "", "region": "", "webhook": "" } ``` ### recording\_generated The hook triggers when the recording is generated. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.startTime` * **Purpose**: Tracks recording generation to ensure it is processed only once. ```json { "trigger": "recording_generated", "data": { "recordingDate": "2023-10-10", "duration": "21.433000", "startTime": "1696937627", "sessionId": "", "recording_url": "" }, "appId": "", "region": "", "webhook": "" } ``` ### meeting\_participant\_joined The hook triggers when a participant joins the meeting. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.occupant.joined_at` * **Purpose**: Tracks participant joins in meetings to ensure they are processed only once. ```json { "trigger": "meeting_participant_joined", "data": { "occupant": { "joined_at": 1696934692, "audio_call": "false", "name": "Andrew Joseph" }, "initial_config": { "is_video_muted": "false", "start_recording_on_call_start": "false", "call_version": "2.3.0", "is_audio_muted": "false", "sdk": "react", "mode": "DEFAULT", "platform": "web", "is_audio_only": "false" }, "sessionId": "" }, "type": "meet", "appId": "", "region": "", "webhook": "" } ``` ### meeting\_participant\_left The hook triggers when a participant leaves the meeting. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.occupant.left_at` * **Purpose**: Tracks participant departures in meetings to ensure they are processed only once. ```json { "trigger": "meeting_participant_left", "data": { "occupant": { "joined_at": 1696934692, "audio_call": "false", "left_at": 1696934730, "name": "Andrew Joseph" }, "sessionId": "" }, "type": "meet", "appId": "", "region": "", "webhook": "" } ``` ### meeting\_ended The hook triggers when the meeting is ended. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.sessionId`+`data.destroyed_at` * **Purpose**: Tracks meeting end events to ensure they are processed only once. ```json { "trigger": "meeting_ended", "data": { "all_occupants": [ { "joined_at": 1696934692, "audio_call": "false", "left_at": 1696934730, "name": "Andrew Joseph" } ], "destroyed_at": 1696934730, "created_at": 1696934692, "sessionId": "" }, "type": "meet", "appId": "", "region": "", "webhook": "" } ``` ## Moderation Events ### moderation\_engine\_approved The hook triggers when a message is marked as approved by the moderation engine. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.message.id`+`data.message.sentAt` * **Purpose**: Tracks moderation approvals to ensure they are processed only once. ```json { "trigger": "moderation_engine_approved", "data": { "message": { "id": "38437", "muid": "_4b6na3agb", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-2", "receiverType": "user", "receiver": "cometchat-uid-1", "category": "message", "type": "text", "data": { "text": "hello", "resource": "WEB-4_0_10-a10f2a72-8d27-4fbc-aceb-05a2258e98f4-1738586366602", "entities": { "sender": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1738589887 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1738589887, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } } }, "sentAt": 1738591120, "updatedAt": 1738591120 } }, "appId": "", "region": "", "webhook": "" } ``` ### moderation\_engine\_blocked The hook triggers when a message is marked as disapproved by the moderation engine. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.message.id`+`data.message.updatedAt` * **Purpose**: Tracks moderation blocks to ensure they are processed only once. ```json { "trigger": "moderation_engine_blocked", "data": { "message": { "id": "38439", "muid": "_zhovsxqdo", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-2", "receiverType": "user", "receiver": "cometchat-uid-1", "category": "message", "type": "text", "data": { "text": "andrew@gmail.com", "resource": "WEB-4_0_10-a10f2a72-8d27-4fbc-aceb-05a2258e98f4-1738586366602", "moderation": { "status": "disapproved", "rule": { "id": "email_filter", "name": "Email Filter" } }, "entities": { "sender": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1738589887 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1738589887, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } } }, "sentAt": 1738591286, "updatedAt": 1738591286 }, "moderation": [ { "condition": { "entity": "message", "operand": "text", "category": "pattern", "operator": "contains", "value": [ "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" ], "message": "Text message contains a pattern matching an email address" }, "rule": { "id": "email_filter", "name": "Email filter", "revisionId": "2531882e5e289115_contact_email_filter_7", "action": [ "blockMessage" ], "blockedAt": 1738591286 } } ] }, "appId": "", "region": "", "webhook": "" } ``` ### moderation\_manual\_approved The hook triggers when a blocked message is manually marked as approved. **Idempotency Details** * **Key**: `webhook`+`trigger`+`data.message.id`+`data.message.updatedAt` * **Purpose**: Tracks manual moderation approvals to ensure they are processed only once. ```json { "trigger": "moderation_manual_approved", "data": { "message": { "id": "38439", "muid": "_zhovsxqdo", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-2", "receiverType": "user", "receiver": "cometchat-uid-1", "category": "message", "type": "text", "data": { "text": "andrew@gmail.com", "resource": "WEB-4_0_10-a10f2a72-8d27-4fbc-aceb-05a2258e98f4-1738586366602", "moderation": { "status": "approved" }, "entities": { "sender": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "role": "default", "lastActiveAt": 1738589887 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "available", "role": "default", "lastActiveAt": 1738589887, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } } }, "sentAt": 1738591286, "updatedAt": 1738591286 }, "moderation": [ { "rule": { "id": "email_filter", "name": "Email filter", "revisionId": "2531882e5e289115_contact_email_filter_7", "action": [ "blockMessage" ], "blockedAt": 1738591286, "condition": { "entity": "message", "operand": "text", "category": "pattern", "operator": "contains", "value": [ "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" ], "message": "Text message contains a pattern matching an email address" } } } ] }, "appId": "", "region": "", "webhook": "" } ``` # Events Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/webhooks-legacy-events ## Message events ### before\_message The endpoint will be triggered when a message is in-flight. ```json { "trigger": "before_message", "data": { "conversationId": "cometchat-uid-4_user_cometchat-uid-5", "sender": "cometchat-uid-5", "receiverType": "user", "receiver": "cometchat-uid-4", "category": "message", "type": "text", "data": { "text": "Hi Webhook Test", "entities": { "sender": { "entity": { "uid": "cometchat-uid-5", "name": "John Paul", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp", "status": "offline", "role": "default" }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline", "role": "default" }, "entityType": "user" } } }, "sentAt": 1586435925, "updatedAt": 1586435925, }, "appId": "167*****1529", "webhook": "send-message" } ``` ### after\_message The endpoint will be triggered after a message is sent. ```json { "trigger": "after_message", "data": { "id": "1", "conversationId": "cometchat-uid-4_user_cometchat-uid-5", "sender": "cometchat-uid-5", "receiverType": "user", "receiver": "cometchat-uid-4", "category": "message", "type": "text", "data": { "text": "Hi Webhook Test", "entities": { "sender": { "entity": { "uid": "cometchat-uid-5", "name": "John Paul", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp", "status": "offline", "role": "default" }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline", "role": "default" }, "entityType": "user" } } }, "sentAt": 1586435925, "updatedAt": 1586435925, }, "appId": "167*****1529", "webhook": "send-message" } ``` ### message\_delivery\_receipt The endpoint will be triggered when a message is marked delivered. ```json { "trigger": "message_delivery_receipt", "appId": "167*****1529", "origin": { "platform": "WEBSOCKET" }, "chatAPIVersion?": "3.0", "region?": "us|eu|other", "webhook": "webhook_name", "data": { "messageId": "MESSAGE_ID", "receiptType": "delivered", "deliveredAt": 1673017183, "messageSender":"messageSenderUID", "receiptSender":"receiptSenderUID", "receiptReceiver":"uid|guid", "receiverType": "user|group" } } ``` ### message\_read\_receipt The endpoint will be triggered when a message is marked read. ```json { "trigger": "message_read_receipt", "appId": "167*****1529", "origin": { "platform": "WEBSOCKET" }, "chatAPIVersion?": "3.0", "region?": "us|eu|other", "webhook": "webhook_name", "data": { "messageId": "MESSAGE_ID", "receiptType": "read", "readAt": 1673017183, "messageSender":"messageSenderUID", "receiptSender":"receiptSenderUID", "receiptReceiver":"uid|guid", "receiverType": "user|group" } } ``` ## User-related events ### user\_connection\_status\_change The endpoint will be triggered when a users logs in or logs out of CometChat. ```json { "trigger": "after_connection_status_changed", "appId": "167*****1529", "origin": { "platform": "API|MGNT-API|WEBSOCKET|WEBRTC" }, "chatAPIVersion?": "3.0", "region?": "us|eu|other", "webhook": "webhook_name", "data": { "user": { "uid": "uid of the user", "status": "online|offline", "status_updated": true, "status_updated_at": "unixtimestamp in millisec" }, "event": { "type": "connected|disconnected", "at": "unixtimestamp in millisec", "event_for": { "connected_at": "unixtimestamp in millisec", "cometchat_device_id": "unique device id used by cometchat to identify the device(random string)", "session_id": "unique id to indetify the unique session of users", "platform": "android|ios|web" } }, "connections": [ { "connected_at": "unixtimestamp in millisec", "cometchat_device_id": "unique device id used by cometchat to identify the device(random string)", "session_id": "unique id to indetify the unique session of users", "platform": "android|ios|web" }, { "connected_at": "unixtimestamp in millisec", "cometchat_device_id": "unique device id used by cometchat to identify the device(random string)", "session_id": "unique id to indetify the unique session of users", "platform": "android|ios|web" } ] } } ``` # Managing Legacy Webhook Triggers Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/webhooks-legacy-management You can manage and configure legacy webhooks in CometChat either from the **dashboard UI** or programmatically via **Management APIs**. *** ## Option 1: Manage from the Dashboard To manage webhooks using the CometChat dashboard: ### Steps: 1. Log in to your [CometChat Dashboard](https://app.cometchat.com/login) and select your app. 2. Go to **Settings** > **Legacy Webhooks** from the left menu. 3. Click on **Add New Webhook**. 4. Fill in the configuration: * **Webhook ID**: A unique identifier for your webhook. * **URL**: Endpoint where event payloads will be delivered. * **Triggers**: Select the events you want to receive. * **Security**: (Recommended) Enable authentication. 5. Enable the webhook. 6. Save the configuration. *** ## Option 2: Manage via Management APIs CometChat also provides Management APIs to automate webhook and trigger management. ### Webhook Management Endpoints | Operation | API Reference | | -------------------------- | ----------------------------------------------------------------------------- | | Create a new webhook | [Create Webhook](https://api-explorer.cometchat.com/reference/create-webhook) | | Update an existing webhook | [Update Webhook](https://api-explorer.cometchat.com/reference/update-webhook) | | List all webhooks | [List Webhooks](https://api-explorer.cometchat.com/reference/list-webhooks) | | Get a webhook by ID | [Get Webhook](https://api-explorer.cometchat.com/reference/get-webhook) | | Delete a webhook | [Delete Webhook](https://api-explorer.cometchat.com/reference/delete-webhook) | ### Trigger Management Endpoints | Operation | API Reference | | ------------------------------ | ------------------------------------------------------------------------------- | | Add triggers to a webhook | [Add Triggers](https://api-explorer.cometchat.com/reference/add-triggers) | | List all triggers of a webhook | [List Triggers](https://api-explorer.cometchat.com/reference/list-triggers) | | Remove triggers from a webhook | [Remove Triggers](https://api-explorer.cometchat.com/reference/remove-triggers) | *** Choose the method that best suits your workflow—dashboard for manual setup or APIs for automated, scalable integration. # Legacy Webhooks Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/webhooks-legacy-overview CometChat legacy webhooks enable real-time event-driven communication with your system. They allow you to receive HTTP POST requests whenever specific events occur—such as sending a message or a user coming online. These webhooks are ideal for integrating external services like SMS, email, analytics, or auditing systems. *** ## Webhook Endpoint Requirements To ensure reliable delivery and security, your webhook endpoint must meet the following requirements: 1. **HTTPS Required**: Your endpoint must use `HTTPS` to ensure secure data transmission. 2. **Public Accessibility**: It must be accessible from the public internet. 3. **Support for POST Requests**: The endpoint must accept `HTTP POST` requests with a `Content-Type` of `application/json`. 4. **Immediate Acknowledgment**: Your server must respond with an `HTTP 200 OK` status quickly to acknowledge receipt. *** ## Security It is strongly recommended to use **Basic Authentication** to protect your webhook endpoints. ### Header Format When enabled, every webhook request from CometChat will include the following HTTP header: ```html Authorization: Basic ``` > Set your username and password while configuring the webhook on the CometChat dashboard. *** ## Webhook Triggers Below are the legacy webhook events supported by CometChat: ### Message Events These events are triggered during the lifecycle of a message. | Event | Description | | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | [before\_message](./webhooks-legacy-events#before_message) | Triggered when a message is in-flight—just before it is processed by CometChat. | | [after\_message](./webhooks-legacy-events#after_message) | Triggered after a message has been successfully sent. | | [message\_delivery\_receipt](./webhooks-legacy-events#message_delivery_receipt) | Triggered when a message is marked as delivered to a user. | | [message\_read\_receipt](./webhooks-legacy-events#message_read_receipt) | Triggered when a message is marked as read by the recipient. | ### User Events These events relate to changes in user presence status. | Event | Description | | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | | [user\_connection\_status\_change](./webhooks-legacy-events#user_connection_status_change) | Triggered when a user connects or disconnects from the CometChat platform. | *** Next Steps: * [Manage Webhooks](/fundamentals/webhooks-legacy-management) * [View Full Event Payloads](/fundamentals/webhooks-legacy-events) # Managing Webhook Triggers Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/webhooks-management CometChat allows you to configure and manage webhook triggers either through the **CometChat Dashboard** or by using the **Management APIs**. This guide walks you through both methods. *** ## Option 1: Managing Webhooks via Dashboard You can easily configure webhook triggers through the CometChat dashboard. ### Steps to Configure: 1. Log in to the [CometChat Dashboard](https://app.cometchat.com/login) and select your app. 2. Navigate to **Settings** > **Webhooks** in the left-hand menu. 3. Click **Add Webhook** to create a new webhook. 4. Provide the following details: * **Webhook ID** – A unique identifier. * **URL** – Your server endpoint where event payloads will be sent. * **Triggers** – Enable events you wish to listen to. * **Security** – Enable authentication for enhanced security. 5. Enable the webhook. 6. Click **Save** to apply your configuration. *** ## Option 2: Managing Webhooks via Management APIs If you prefer automation or need to manage webhooks programmatically, you can use our REST APIs. ### Webhook Operations | Operation | API Reference | | -------------------------- | --------------------------------------------------------------------------------- | | Create a new webhook | [Create Webhook](https://api-explorer.cometchat.com/reference/create-webhook-api) | | Update an existing webhook | [Update Webhook](https://api-explorer.cometchat.com/reference/update-webhook-api) | | List all webhooks | [List Webhooks](https://api-explorer.cometchat.com/reference/list-webhooks-api) | | Get webhook by ID | [Get Webhook](https://api-explorer.cometchat.com/reference/get-webhook-api) | | Delete a webhook | [Delete Webhook](https://api-explorer.cometchat.com/reference/delete-webhook-api) | ### Trigger Operations | Operation | API Reference | | ------------------------------ | ----------------------------------------------------------------------------------- | | Add triggers to a webhook | [Add Triggers](https://api-explorer.cometchat.com/reference/add-triggers-api) | | List triggers for a webhook | [List Triggers](https://api-explorer.cometchat.com/reference/list-triggers-api) | | Remove triggers from a webhook | [Remove Triggers](https://api-explorer.cometchat.com/reference/remove-triggers-api) | *** Choose the method that best fits your use case—Dashboard for quick setup, or APIs for advanced and automated configurations. # Webhooks Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/fundamentals/webhooks-overview CometChat Webhooks enable real-time, event-driven communication with your server by sending HTTP POST requests for specific events such as messages, user actions, group updates, calls, and moderation results. You can use webhooks to build custom workflows such as sending SMS or email notifications, logging activity, syncing with external systems, or triggering automation. *** ## Setting Up Your Webhook Endpoint To successfully receive and process events from CometChat, your webhook endpoint must meet the following criteria: 1. **Use HTTPS** – All webhook URLs must be secured with SSL. 2. **Be publicly accessible** – Your server should be reachable from the internet. 3. **Support POST method** – Events will be delivered as `HTTP POST` requests with `application/json` content. 4. **Return a 200 OK** – Your endpoint must acknowledge receipt by responding with `HTTP 200`. *** ## Securing Your Webhook ### Basic Authentication (Recommended) To ensure only authorized systems can access your endpoint, use Basic Authentication: ```html Authorization: Basic ``` You can configure this with a username and password known only to your system. ### Token-based files access Token-based file access provides improved control over media files through pre-signed URLs. When this feature is enabled, media URLs in webhook payloads may return a 401 Unauthorized response. You can enable this feature in the **Settings** section under **Chats** in the CometChat dashboard. Once enabled, it cannot be disabled. To access media files, use the media URL from the webhook payload to obtain a URL secured with a file access token (FAT). This URL redirects to a pre-signed URL that remains valid for 5 minutes. **Sample request:** ```html curl --location 'https://files-.cometchat.io//media/audio3.mp3' \ --header 'appId: ' \ --header 'apiKey: ' ``` **Sample response:** ```json { "data": { "url": "https://files-.cometchat.io//media/audio3.mp3?fat=" } } ``` *** ## Webhook Best Practices To maximize reliability and avoid common issues, follow these recommendations: ### 1. Handle Retries Gracefully * Use the `retryOnFailure` flag when setting up webhooks. * If enabled, CometChat retries failed deliveries: * First retry: after 10 seconds. * Second retry: after 30 seconds. * Use unique event IDs from payloads to **deduplicate** retries. ### 2. Respond Quickly * Respond within **2 seconds** to prevent timeouts. * For long processing tasks, enqueue events to systems like **Kafka, RabbitMQ, or AWS SQS**, and process them asynchronously. ### 3. Log and Monitor * Maintain detailed logs of all incoming webhook requests and your server responses. * Track failures, latency, and retry attempts. ### 4. Implement Robust Error Handling * Return appropriate HTTP status codes: * `200 OK` for success. * `4xx` for client-side errors (e.g., bad request). * `5xx` for server-side issues. ### 5. Thoroughly Test Before Production * Simulate various conditions: successful delivery, retries, and failures. * Ensure your implementation handles all cases gracefully. *** ## Webhook Event Triggers CometChat supports webhook triggers for different categories of events. Click each event name to see its payload and details. *** ### Message Events | Event | Description | | ------------------------------------------------------------------------------------ | ---------------------------------------------------- | | [message\_sent](/fundamentals/webhooks-events#message_sent) | Triggered after a message is sent. | | [message\_edited](/fundamentals/webhooks-events#message_edited) | Triggered after a message is edited. | | [message\_deleted](/fundamentals/webhooks-events#message_deleted) | Triggered after a message is deleted. | | [message\_delivery\_receipt](/fundamentals/webhooks-events#message_delivery_receipt) | Triggered when a message is delivered to the client. | | [message\_read\_receipt](/fundamentals/webhooks-events#message_read_receipt) | Triggered when a message is marked as read. | | [message\_reaction\_added](/fundamentals/webhooks-events#message_reaction_added) | Triggered when a user reacts to a message. | | [message\_reaction\_removed](/fundamentals/webhooks-events#message_reaction_removed) | Triggered when a reaction is removed. | | [user\_mentioned](/fundamentals/webhooks-events#user_mentioned) | Triggered when a user is mentioned in a message. | *** ### User Events | Event | Description | | ------------------------------------------------------------------------------------------------- | -------------------------------------------- | | [user\_blocked](/fundamentals/webhooks-events#user_blocked) | Triggered when a user blocks another user. | | [user\_unblocked](/fundamentals/webhooks-events#user_unblocked) | Triggered when a user unblocks another user. | | [user\_connection\_status\_changed](/fundamentals/webhooks-events#user_connection_status_changed) | Triggered when a user connects/disconnects. | *** ### Group Events | Event | Description | | ----------------------------------------------------------------------------------------- | ---------------------------------------------- | | [group\_created](/fundamentals/webhooks-events#group_created) | Triggered after a group is created. | | [group\_updated](/fundamentals/webhooks-events#group_updated) | Triggered after a group is updated. | | [group\_deleted](/fundamentals/webhooks-events#group_deleted) | Triggered after a group is deleted. | | [group\_member\_added](/fundamentals/webhooks-events#group_member_added) | Triggered when a member is added. | | [group\_member\_removed](/fundamentals/webhooks-events#group_member_removed) | Triggered when a member is removed. | | [group\_member\_banned](/fundamentals/webhooks-events#group_member_banned) | Triggered when a member is banned. | | [group\_member\_unbanned](/fundamentals/webhooks-events#group_member_unbanned) | Triggered when a member is unbanned. | | [group\_member\_joined](/fundamentals/webhooks-events#group_member_joined) | Triggered when a user joins a group. | | [group\_member\_left](/fundamentals/webhooks-events#group_member_left) | Triggered when a user leaves a group. | | [group\_member\_kicked](/fundamentals/webhooks-events#group_member_kicked) | Triggered when a member is kicked. | | [group\_member\_scope\_changed](/fundamentals/webhooks-events#group_member_scope_changed) | Triggered when a member's scope changes. | | [group\_owner\_transferred](/fundamentals/webhooks-events#group_owner_transferred) | Triggered when group ownership is transferred. | *** ### Call and Meeting Events | Event | Description | | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | [call\_initiated](/fundamentals/webhooks-events#call_initiated) | Triggered when a call is initiated. | | [call\_started](/fundamentals/webhooks-events#call_started) | Triggered when a call starts. | | [call\_ended](/fundamentals/webhooks-events#call_ended) | Triggered when a call ends. | | [call\_participant\_joined](/fundamentals/webhooks-events#call_participant_joined) | Triggered when a participant joins a call. | | [call\_participant\_left](/fundamentals/webhooks-events#call_participant_left) | Triggered when a participant leaves a call. | | [call\_busy](/fundamentals/webhooks-events#call_busy) | This hook is triggered when a 1-on-1 call cannot be connected because the recipient is already on another call (i.e., their line is busy). | | [call\_cancelled](/fundamentals/webhooks-events#call_cancelled) | The hook triggers when the call is cancelled. | | [call\_rejected](/fundamentals/webhooks-events#call_rejected) | This hook is triggered when a 1-on-1 call is explicitly rejected by the recipient. | | [call\_unanswered](/fundamentals/webhooks-events#call_unanswered) | This hook is triggered when a call goes unanswered. | | [meeting\_started](/fundamentals/webhooks-events#meeting_started) | Triggered when a meeting starts. | | [meeting\_ended](/fundamentals/webhooks-events#meeting_ended) | Triggered when a meeting ends. | | [meeting\_participant\_joined](/fundamentals/webhooks-events#meeting_participant_joined) | Triggered when a participant joins a meeting. | | [meeting\_participant\_left](/fundamentals/webhooks-events#meeting_participant_left) | Triggered when a participant leaves a meeting. | | [recording\_generated](/fundamentals/webhooks-events#recording_generated) | Triggered when a recording is generated. | *** ### Moderation Events | Event | Description | | ---------------------------------------------------------------------------------------- | ------------------------------------------------------ | | [moderation\_engine\_approved](/fundamentals/webhooks-events#moderation_engine_approved) | Triggered when a message is auto-approved. | | [moderation\_engine\_blocked](/fundamentals/webhooks-events#moderation_engine_blocked) | Triggered when a message is auto-blocked. | | [moderation\_manual\_approved](/fundamentals/webhooks-events#moderation_manual_approved) | Triggered when a blocked message is manually approved. | *** By following this guide, you can seamlessly integrate CometChat webhooks into your system and build event-driven experiences at scale. # Home Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/index Technical documentation & Implementation guides to add In-app Messaging & Voice & Video Calling to your apps and websites in minutes. export function openSearch() { document.getElementById('search-bar-entry').click(); }
Get Started

Seamlessly integrate real-time chat, voice, and video functionalities.

Using Cursor, VS Code, Claude, Lovable, or any MCP-enabled tool? Add our CometChat Docs MCP so your AI always pulls the latest CometChat documentation.

[Add CometChat Docs MCP](/mcp-server)
{/** Products Section */}

Products

{/* } iconType="solid" href="/chat" > Lightning-fast conversations with enterprise scalability } iconType="solid" href="/calls" > Crystal-clear calls and streams with zero lag */} } iconType="solid" href="/chat-call"> Lightning-fast conversations & calling with enterprise scalability } iconType="solid" href="/ai-agents"> Automate conversations using AI-powered chatbot technology. } iconType="solid" href="/moderation/overview"> Ensure safety with advanced content filtering tools. } iconType="solid" href="/notifications/overview"> Boost engagement by sending instant user notifications. } iconType="solid" href="/insights"> Generate AI-powered insights for meaningful conversations.

Resources

Quick links to deeper integration guides, API references, and community support.

Search our comprehensive knowledge base for all your CometChat questions. Experience CometChat in action with our live demo. Stay ahead of the curve with the latest features. Stay informed of any service interruptions.
Brainstorm with our solution engineers to refine your integration.
# API Explorer Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/api-explorer # Blocked Messages Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/blocked-messages ## Overview The Blocked Messages endpoint in the Moderation Service API provides app owners and collaborators with the capability to retrieve details about messages that have been blocked due to violations of message moderation rules. This endpoint plays a crucial role in enabling platform app owners and collaborators to review and manage content that has been deemed inappropriate, harmful, or non-compliant with platform guidelines. ### List Blocked Messages Retrieves the list of blocked messages, with the option to search messages within a specified date range. You can also set this up from your end using the [List Moderation Blocked Message List REST API](https://api-explorer.cometchat.com/reference/list-moderation-blocked-messages). ### Approve Blocked Message Allows the approval of messages previously blocked due to moderation violations. You can also set this up from your end using the [Approve Blocked Message REST API](https://api-explorer.cometchat.com/reference/approve-moderation-blocked-messages). # Constraints And Limits Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/constraints-and-limits ## Constraints ### Rule Management Here are the constraints for managing rules within the system: | Parameter | Constraint | | ------------------- | ------------------------------------------------------------------------- | | **Rule ID** | No spaces or special characters allowed, Maximum length of 100 characters | | **Name** | Maximum length of 100 characters | | **Description** | Maximum length of 255 characters | | **Rule Filters** | Each rule can have a maximum of 10 filters | | **Rule Conditions** | Each rule can have a maximum of 10 conditions | | **Rules per app** | An app can have up to 25 rules (exluding default rules) | ### Lists Management Here are the constraints for managing lists within the system: | Parameter | Constraint | | ----------------- | ------------------------------------------------------------------------- | | **ID** | No spaces or special characters allowed, Maximum length of 100 characters | | **Name** | Maximum length of 100 characters | | **Description** | Maximum length of 255 characters | | **CSV File** | Accepted file size: up to 1 MB | | **Lists per app** | An app can have up to 25 lists (excluding the default lists) | ## Limitations * Make sure the SDK version you are using is 3.0 or higher. * AI Image moderation currently supports & moderates JPEG and PNG image formats. * AI video moderation currently supports & moderates MP4, MOV, and AVI formats. * If a message is marked as delivered/read and previous messages include pending/disapproved ones, those will also be automatically marked as delivered/read, even though they haven't actually been delivered to the receiver. # Custom API Moderation Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/custom/custom-api CometChat allows you to integrate your own moderation logic using a **Custom API**. With this feature, you can define a webhook URL in the **List Configuration**, where CometChat will send messages for moderation along with relevant context from the conversation (if provided in settings). ## **How It Works** 1. When a user sends a message, CometChat retrieves the webhook URL from the configured **List**. 2. The message, along with previous conversation messages (if a context window is set in settings), is sent to the webhook. 3. The webhook (your external API) processes the data using your custom moderation logic. 4. The webhook responds with a structured decision containing details about the moderation outcome. 5. CometChat processes the response and applies the moderation decision in real-time. This approach gives you complete control over moderation, allowing you to implement **custom filtering, AI-based analysis, or any other logic** on your own servers. ## Integration ### Step 1: Configure Custom API Settings 1. **Login to the CometChat Dashboard** * Navigate to [CometChat Dashboard](https://app.cometchat.com) and select your app. 2. **Navigate to Moderation Settings** * Go to **Moderation → Settings** in the left-hand menu. 3. **Open Custom API Settings Tab** * Click on the **Custom API** tab within the Moderation Settings. 4. **Fill in the Custom API Configuration** * **Set Action on API Error** * Define how the system should respond if the Custom API is unavailable (e.g., "Allow message" or "Block message"). * **Set Context Window** * Specify the number of previous messages in a conversation that will be used for context. 5. **Click Save Settings** ### Step 2: Enable Custom API Moderation 1. Navigate to **Moderation → Rules**. 2. Click **"Create New Rule"**. 3. Select **Custom API** as the moderation type. 4. The rule you create should be of type **"Text Contains"** or **"Image Contains"**. 5. Save the rule. ## Payload Sent to Webhook When a message is sent, CometChat invokes your webhook with a payload that includes: * he latest message (the one just sent) — provided in full detail (entire message object) * The previous messages — provided as plain text only, for context (based on the context window setting) This structure allows you to apply moderation logic to the current message while considering its surrounding context. ```json { "contextMessages": [ { "cometchat-uid-1": "Hello there!" }, { "cometchat-uid-2": "Hey, how are you?" }, { "cometchat-uid-1": "Let's team up." }, { "cometchat-uid-2": { "id": "30431", "muid": "_r49ocm6oj", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "sender": "cometchat-uid-1", "receiverType": "user", "receiver": "cometchat-uid-2", "category": "message", "type": "text", "data": { "text": "ok", "resource": "WEB-4_0_10-04aecbad-8354-4fc8-98df-d0119e1a9539-1747717193939", "entities": { "sender": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://data-us.cometchat-staging.com/assets/images/avatars/andrewjoseph.png", "status": "available", "role": "default", "lastActiveAt": 1747717203 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "avatar": "https://data-us.cometchat-staging.com/assets/images/avatars/georgealan.png", "status": "offline", "role": "default", "lastActiveAt": 1721138868, "conversationId": "cometchat-uid-1_user_cometchat-uid-2" }, "entityType": "user" } }, "moderation": { "status": "pending" } }, "sentAt": 1747717214, "updatedAt": 1747717214, } } ] } ``` ## Webhook Response Format The webhook should return a response in the following format: ```javascript { isMatchingCondition: true, // True if the message violates the rule confidence: 0.95, // Confidence score of the decision reason: "Contains hate speech" // Reason for flagging } ``` # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/custom/custom-api-overview CometChat offers AI-powered message moderation to help maintain a safe and respectful chat environment. You can choose between two moderation options: ### **Custom API Moderation** If you prefer to use a third-party moderation service or your own AI model, CometChat enables integration via a **Custom Moderation API**. With this option, you can: * **Set Up a Webhook** – Configure an endpoint where messages will be sent for moderation. * **Customize Authentication** – Add security layers like basic authentication. * **Contextual Moderation** – Define how many previous messages from the conversation should be included in the webhook request for better analysis. * **Process Moderation Decisions** – CometChat processes the webhook response and applies moderation actions accordingly. This moderation provide flexibility to enhance user safety and compliance within your chat platform. # Getting Started Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/getting-started # Moderation Integration To maintain a safe, respectful, and engaging environment for your users, our platform offers a powerful **Moderation Integration** system. This system allows you to automatically review, filter, and take action on user-generated messages, images, and videos before they are delivered. With Moderation Integration, you can define flexible rules, receive real-time updates, and ensure your app meets community guidelines, legal standards, and brand values without manual intervention. If you’re using the CometChat UI Kit or SDK, you can skip steps 2 and 3. *** ## Integrate Moderation Note: If you're using CometChat UI Kits or SDKs, you can skip steps 2 & 3.

Define content moderation rules for your app's messaging system.

Set up a webhook to receive real-time moderation events.

Use APIs to send and review flagged messages programmatically.

*** ## Key Components of Moderation Integration **Step 1:** [Set up moderation rules](#setting-up-moderation-rules) **Step 2:** [Configure a moderation webhook](#configuring-a-moderation-webhook) **Step 3:** [Integrate and test the Moderation API](#integrating-and-testing-the-moderation-api) *** ## Setting Up Moderation Rules Moderation rules act as filters to ensure that the messages exchanged within your app meet your safety and content guidelines. ### How It Works * When a message, image, or video is submitted, it is automatically checked against the moderation rules you’ve configured. * These rules can detect offensive language, sensitive content, spam, scams, and more. * Based on your settings, content can be: * **Approved:** Delivered to the recipient. * **Disapproved:** Blocked and not delivered. ### Benefits * **Safety first:** Protect your users and brand from harmful or unwanted content. * **Customizable:** Fine-tune moderation rules to suit your app’s unique needs. * **Seamless experience:** Moderation happens in real time, keeping communication flowing smoothly. ### Creating Moderation Rules CometChat provides a set of **default moderation rules** designed to cover common use cases such as offensive language, spam, and inappropriate content. You can enable these rules to start moderating messages immediately, without any additional setup. {/* ![Default moderation rules](/images/existing-rules.png) */} If you have specific requirements, you can create **custom moderation rules** tailored to your app’s needs. Rules can be created in two ways: 1. **Using the CometChat Dashboard** — A simple, no-code interface for visually creating and managing moderation rules. {/* ![Create rule screen](/images/create-rule.png) */} 2. **Using the CometChat API** — Programmatically create and manage moderation rules for advanced or automated workflows. See the [Create Rule API documentation](\{apiEndpoints.createRule.url}). *** ## Configuring a Moderation Webhook To automate your moderation flow and receive updates in real time, configure a **moderation webhook**. This allows your system to react instantly when a message or media is moderated. ### How It Works * Every time content is moderated, a webhook event is triggered and sent to the URL you specify. * Your application can then take action based on the moderation result. ### Prerequisites * Your webhook URL must be accessible over **HTTPS** to ensure secure data transmission. * The URL should be publicly accessible from the internet. * Ensure your endpoint supports the `HTTP POST` method. Event payloads will be delivered via `POST` requests in JSON format. * Configure your endpoint to respond immediately to the CometChat server with a `200 OK` response. * For security, set up **Basic Authentication** (username and password) for server-to-server communication. When your webhook URL is triggered, the HTTP header includes: ```http Authorization: Basic ``` ### Handle Moderation Events Ensure your webhook endpoint is ready to process moderation events. Refer to the [Moderation Events](/docs-beta/fundamentals/webhooks-overview#moderation-events) section for the full list. The key events to handle include: * `moderation_engine_approved` — Triggered when the engine automatically approves content. * `moderation_engine_blocked` — Triggered when the engine automatically blocks content. * `moderation_manual_approved` — Triggered when a moderator manually approves previously blocked content. To receive these events, enable the relevant webhooks in the CometChat Dashboard: > **Application → Webhooks → Create Webhook → Triggers → Moderation** Select all three moderation triggers to ensure your app receives the necessary notifications. {/* ![Enable webhooks](/images/webhook-events.png) */} *** ## Integrating and Testing the Moderation API Once your moderation rules and webhook are configured, integrate the **Moderation API** into your application to programmatically submit content and receive moderation results. ### Steps to Integrate and Test 1. **Submit content:** Use the API to send messages, images, or videos for moderation. 2. **Check responses:** Verify moderation status in real time. 3. **Handle outcomes:** Apply business logic based on approved, flagged, or disapproved responses. 4. **End-to-end testing:** Test both the API response and webhook delivery to ensure complete coverage. When you’re ready, you can render all moderation endpoints dynamically: ### Send message This endpoint is used to submit a message for moderation before it is delivered to the recipient. The message is scanned against the moderation rules configured for the app. **URL:** ``` https://api-explorer.cometchat.com/reference/chat-api-send-message-moderation ``` **Request Body:** ```json { "category": "message", "type": "text", "data": { "text": "Hi new user" }, "sender": "cometchat-uid-2", "receiver": "cometchat-uid-1", "receiverType": "user", "sentAt": 1750335220 } ``` ### List messages Retrieves a list of messages submitted for moderation, along with the current moderation status of each message as determined by your configured rules. **URL:** ``` https://api-explorer.cometchat.com/reference/chat-api-list-message-moderation/ ``` ### Get message Retrieves the details of a specific message submitted for moderation, including its current moderation status as determined by your configured rules. **URL:** ``` https://api-explorer.cometchat.com/reference/chat-api-get-message-moderation/ ``` ### Update message Edits an existing message. The moderation status is re-evaluated based on your configured rules. **URL:** ``` https://api-explorer.cometchat.com/reference/chat-api-update-message-moderation/ ``` ### Delete message Deletes a previously submitted message along with its associated moderation data, in accordance with your configured rules. **URL:** ``` https://api-explorer.cometchat.com/reference/chat-api-delete-message-moderation/ ``` ### Approve message Approves a previously blocked message, allowing it to be delivered to the recipient. **URL:** ``` https://api-explorer.cometchat.com/reference/chat-api-approve-moderation-blocked-messages/ ``` *** | Endpoint | Purpose | | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | **Send message for moderation**
`POST /moderation/messages` | Submits a new message for moderation. Triggers the engine, emits a webhook, and makes the message available via the get-message endpoint. | | **Edit message for moderation**
`PUT /moderation/messages/:id` | Re-evaluates an edited message. If approved, the updates are accepted; if blocked, the message is withheld. | | **Get message moderation status**
`GET /moderation/messages/:id` | Retrieves the moderation status, rule metadata, and action history of a message. | | **List messages for moderation**
`GET /moderation/messages` | Lists all moderated messages with optional filters such as category, type, status, and receiver UID/GUID. | | **Delete message from moderation**
`DELETE /moderation/messages/:id` | Deletes a moderated message. | *** ## Summary By combining well-defined moderation rules, automated webhooks, and robust API integration, you can build a safe, scalable, and user-friendly content moderation system tailored to your app’s values and audience expectations. # Data Masking Filter (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/legacy/data-masking-filter **Legacy Notice**: This extension is considered legacy and is scheduled for deprecation in the near future. It is no longer recommended for new integrations. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. The Data Masking Extension allows you to hide phone numbers, email address and other sensitive information in messages. You as a developer, can add regular expressions for matching & masking. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Data Masking Filter extension. 3. Open the Settings for this extension and configure the following: 1. Drop Message: If enabled, any message with sensitive information will be dropped. 2. Default Masks: Masks for Emails, Social Security Numbers (SSN), US phone numbers are built in. 3. Custom Masks: Add more regex that will act as masks for some form of sensitive information. 4. Save the extension settings. Refer [this](https://www.w3schools.com/jsref/jsref_obj_regexp.asp) for more details on Regular Expressions. ## How does it work? Once the Extension is enabled for your App and the Extension Settings are done, the recipients will receive metadata with the masked message. Here is a sample response: ```json "@injected": { "extensions": { "data-masking": { "data": { "sensitive_data": "yes", "message_masked": "My number is ***** & my email id is ****" } } } } ``` If the data-masking key is missing, it means that the extension is either not enabled or has timed out. ## Implementation At the recipients' end, from the message object, you can fetch the metadata by calling the getMetadata() method. Using this metadata, you can fetch the masked message. ```js var metadata = message.getMetadata(); if (metadata != null) { var injectedObject = metadata["@injected"]; if (injectedObject != null && injectedObject.hasOwnProperty("extensions")) { var extensionsObject = injectedObject["extensions"]; if ( extensionsObject != null && extensionsObject.hasOwnProperty("data-masking") ) { var dataMaskingFilterObject = extensionsObject["data-masking"]["data"]; var sensitive_data = dataMaskingFilterObject["sensitive_data"]; var message_masked = dataMaskingFilterObject["message_masked"]; } } } ``` ```java JSONObject metadata = message.getMetadata(); if (metadata != null) { JSONObject injectedObject = metadata.getJSONObject("@injected"); if (injectedObject != null && injectedObject.has("extensions")) { JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); if (extensionsObject != null && extensionsObject.has("data-masking")) { JSONObject dataMaskingObject = extensionsObject.getJSONObject("data-masking"); JSONObject data = dataMaskingObject.getJSONObject("data"); String sensitive_data = data.getString("sensitive_data"); String message_masked = data.getString("message_masked"); } } } ``` ```kotlin if (metadata != null) { if (metadata.has("@injected")) { val injectedJSONObject = metadata.getJSONObject("@injected") if (injectedJSONObject != null && injectedJSONObject.has("extensions")) { val extensionsObject = injectedJSONObject.getJSONObject("extensions") if (extensionsObject != null && extensionsObject.has("data-masking")) { val dataMaskingDetails = extensionsObject.getJSONObject("data") val dataMaskingObject = dataMaskingDetails.getJSONObject("data") val sensitive_data = dataMaskingObject.getString("sensitive_data") val message_masked = dataMaskingObject.getString("message_masked")) } } } } ``` ```swift let textMessage = message as? TextMessage var metadata : [String : Any]? = textMessage.metaData if metadata != nil { var injectedObject : [String : Any]? = (metadata?["@injected"] as? [String : Any])! if injectedObject != nil && (injectedObject!["extensions"] != nil){ var extensionsObject : [String : Any]? = injectedObject?["extensions"] as? [String : Any] if extensionsObject != nil && extensionsObject?["data-masking"] != nil { var dataMasking = extensionsObject?["data-masking"] as! [String : Any] var dataMaskingDetails = dataMasking?["data"] as! [String : Any] let sensitive_data = dataMaskingDetails["sensitive_data"] as! String let message_masked = dataMaskingDetails["message_masked"] as! String } } } ``` # Report Message (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/legacy/report-message **Legacy Notice**: This extension is considered legacy and is scheduled for deprecation in the near future. It is no longer recommended for new integrations. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. Enable your users to report messages in a group. **Extension settings** 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Report messages extension. 3. Open the settings for this extension. 4. The settings page has the following: * **Moderation criteria:** The max number of reports after which you want to be notified. * **Moderation actions:** Get the list of reports on the configured Webhook URL. ## How does it work? The extension has the following functionalities: 1. Allowing end-users to report messages. 2. Allowing admins to login to the dashboard to take action on the reports. ### 1. Reporting a message Messages can be reported in either group conversations or one-on-one conversations. In the context menu of a message, you can have a "Report" button. Clicking it should open up a modal asking for the reason. Here's the description of the parameters that need to be passed to the extension: | Parameters | Value | Description | | ---------- | ------- | --------------------------------------------- | | msgId | Integer | The ID of the message that has to be reported | | reason | String | The reason for reporting the message. | Once you have the message to be reported along with the reason, make use of the `callExtension` method provided by the SDK to submit the report: ```js CometChat.callExtension('report-message', 'POST', 'v1/report', { "msgId": 123, "reason": "Contains profanity" }).then(response => { // { success: true } }) .catch(error => { // Error occurred }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("msgId", 123); body.put("reason", "Contains profanity"); CometChat.callExtension("report-message", "POST", "/v1/report", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "report-message", type: .post, endPoint: "v1/report", body: [ "msgId": 123, "reason":"Contains profanity" ] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### 2. View reports and take action In order to list and take action on the reported users: 1. Open up the Extension's settings page 2. Click "View Reports" link. This will load all the reports. 3. The following actions can be taken for users reported in Group: 1. Delete => Reported message will be deleted. 2. Ignore => The report is ignored. 4. To load new reports, click on the Refresh button. # Report User (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/legacy/report-user **Legacy Notice**: This extension is considered legacy and is scheduled for deprecation in the near future. It is no longer recommended for new integrations. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. Enables your users to report users who use offensive or suspicious messages in the chat. ## Extension settings 1. Login to CometChat and select your app. 2. Go to the Extensions section and enable the Report user extension. 3. Open the settings for this extension. 4. The settings page has the following: * **Moderation criteria:** The max number of reports after which you want to be notified. * **Moderation actions**: Get the list of reports on the configured Webhook URL. ## How does it work? The extension has the following functionalities: 1. Allowing end-users to report other users. 2. Allowing admins to login to the Dashboard to take action on the reports. ### 1. Reporting a user Users can be reported in either group conversations or one-on-one conversations. By clicking on the user's avatar, you can show an item in the context menu called "Report". Clicking on the "Report" button should open up a modal asking for the reason. Here's the description of the parameters that need to be passed to the extension: | Parameters | Value | Description | | ---------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | uid | String | The UID of the user that needs to be reported | | reason | String | Reason for reporting. This should be max 150 characters. | | guid | String | The GUID of the group in which the user is being reported.If the user is being reported in a one-on-one conversation, this can be skipped. | Once you have the user to be reported along with the reason, make use of the callExtension method provided by the SDK to submit the report: ```js CometChat.callExtension('report-user', 'POST', 'v1/report', { "uid": "cometchat-uid-3", "reason": "Misbehaving", // "guid": "cometchat-guid-1" // Used only when reporting the user in a group }).then(response => { // { success: true } }) .catch(error => { // Error occurred }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("uid", "cometchat-uid-3"); body.put("reason", "Misbehaving"); // body.put("guid", "cometchat-guid-1"); // Used only when reporting the user in a group CometChat.callExtension("report-user", "POST", "/v1/report", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "report-user", type: .post, endPoint: "v1/report", body: [ "uid": "cometchat-uid-3", "reason":"Misbehaving", "guid":"cometchat-guid-1" // Used only when reporting the user in a group ] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### 2. View reports and take action on a reported user In order to list and take an action on the reported users: 1. Open up the Extension's settings page 2. Click "View Reports" link. This will load all the reports. 3. Select the criteria from the dropdown: 1. One-on-one conversations => Lists the users who have been reported in One-on-one conversations. 2. Group conversations => List the users who have been reported in a Group. 3. All reports => Lists all the reports. 4. The following actions can be taken for users reported in Group: 1. Kick => Reported user is kicked out of the group. 2. Ban => Reported user is banned from the group. 3. Ignore => The report is ignored. 5. The following actions can be take for users reported in one-on-one conversations: 1. Block => The reported user is blocked on behalf of the reporter. 2. Ignore => The report is ignored. 6. To load new reports, click on the Refresh button. # Slow Mode (Deprecated) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/legacy/slow-mode Deprecated: This extension is no longer maintained and will not receive further updates. Slow down messages to make them legible! ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Slow mode extension. ## How does Slow mode work? Slow mode extension works great in groups with a large number of participants. Especially, during a live event with a potential for a flood of messages being sent every second. When the extension is enabled and enforced in a group, it allows the participants to send messages only after a certain intervals. This helps to keep chats readable for everyone during large events. The extension has the following 4 parts: 1. Enabling the slow mode for a group 2. Disabling the slow mode for a group 3. Enforcing slow mode for participants 4. Fetching the slow mode details ### Enabling slow mode Slow mode can be enabled only by the group admins or moderators. Participants cannot enable the slow mode. Once slow mode is enabled in a group, the information is shared with its members in real-time as a custom message. With this, it can be enforced immediately. You need to implement the `onCustomMessageReceived` listener in order to receive the Slow mode related messages. The message sent has the category of `custom` and type `extension_slow-mode`. Following are the inputs required to enable slow mode in a particular group: | Parameter | Type | Description | | ------------------ | ------ | ------------------------------------------------------------------------------------------------------------------- | | `guid` | string | The group's ID in which the slow mode needs to be enabled. | | `slowDownTimeInMS` | int | The time in milliseconds for which the participants have to wait before being able to send the consecutive message. | You can make use of the `callExtension` method exposed by CometChat SDKs to enable slow mode as an admin/moderator. ```js CometChat.callExtension('slow-mode', 'POST', 'v1/configure', { "guid": "cometchat-guid-1", "slowDownTimeInMS": 660000, }).then(response => { // Success true }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("guid", "cometchat-guid-1"); body.put("slowDownTimeInMS", 660000); CometChat.callExtension("slow-mode", "POST", "/v1/configure", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "slow-mode", type: .post, endPoint: "v1/configure", body: ["guid": "cometchat-guid-1" ,"slowDownTimeInMS": 660000] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### Disabling slow mode Slow mode can be disabled only by the group admins or moderators. Participants cannot disable the slow mode. Once slow mode is disabled in a group, the information is shared with its members in real-time as a custom message. With this, it can be turned off for that group immediately. Following are the inputs required to enable slow mode in a particular group: | Parameter | Type | Description | | --------- | ------ | ----------------------------------------------------------- | | `guid` | string | The group's ID in which the slow mode needs to be disabled. | You have to implement the `onCustomMessageReceived` listener in order to receive the Slow mode related messages. The message sent has the category of `custom` and type `extension_slow-mode`. You can make use of the `callExtension` method exposed by CometChat SDKs to disable slow mode as an admin/moderator. ```js CometChat.callExtension('slow-mode', 'DELETE', 'v1/configure', { "guid": "cometchat-guid-1" }).then(response => { // Success true }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("guid", "cometchat-guid-1"); CometChat.callExtension("slow-mode", "DELETE", "/v1/configure", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "slow-mode", type: .delete, endPoint: "v1/configure", body: nil, onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### Enforcing slow mode This is handled by the extension for groups that have slow mode enabled as mentioned below: #### 1. For participants of a group If the moderator or admin of a group has enabled slow mode with the time of 1 min, then the participants will have to wait for 1 minute after sending a message. Once the participant has waited for 1 min, he/she then becomes eligible to send out the next message. If there's an attempt by the participants to send a message before the interval has expired for them, the message gets blocked by the extension. #### 2. For admins and moderators The extension does not restrict moderators and admins of a group. Slow mode is enforced only for the participants. Groups without admins/moderators Groups that are created from the dashboard do not have an admin or moderator. Hence, care needs to be taken to add a member to such groups and change their scope to either moderator or admin. #### 3. Change in member scope If a participant is made an admin or moderator of a group, the slow mode is no longer applicable for him/her. Similarly, if an admin or moderator of a group is demoted to a participant, the slow mode will be applicable immediately to him/her as mentioned above. ### Fetching slow mode details As mentioned above, the details about the enabling or disabling the slow mode are shared in real-time with the members as a custom message. But, it might happen that a few members are offline or are added later on to the group. Hence, it is important to make the same details available to them for a consistent experience. You can make use of the `callExtension` method exposed by the CometChat SDKs to fetch the details about slow mode as a member of a group. ```js const guid = "cometchat-guid-1"; CometChat.callExtension('slow-mode', 'GET', `v1/fetch-configuration?guid=${guid}`, null).then(response => { // Configuration for the mentioned group }) .catch(error => { // Error occured }); ``` ```java CometChat.callExtension("slow-mode", "GET", "/v1/fetch-configuration?guid=cometchat-guid-1", null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "slow-mode", type: .get, endPoint: "v1/fetch-configuration?guid=cometchat-guid-1", body: nil, onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` The response has the following format: | Parameters | Type | Description | | ---------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `isSlowed` | boolean | Whether the slow mode is enabled in the mentioned group.If false, the following fields are not present in the response. | | `slowDownTimeInMS` | int | The time interval for which a participant has to wait for sending messages. | | `lastMessageSentAtTimestamp` | timestamp | The timestamp at which the last message was sent by the logged in user in the mentioned group.If the scope of the logged in user is Admin or Moderator in the mentioned group, this field is not included in the response. | ## Implementation #### 1. For admins and moderators When a group chat is opened, and the scope of the logged-in user is either an admin or a moderator of that group, he/she should be able to toggle slow mode for that group. When a group has multiple admins/moderators, and one of the admins enables (or disables) the slow mode for a group, the UI for other admins/moderators should update and show the control to disable (or enable) the slow mode. This can be achieved in real-time due to the custom message that is sent. Whenever, an admin or a moderator in a group switches conversations to a different group, use the fetch-configuration call to check for the above mentioned details. It may happen, that the logged in user is admin/moderator for one group but a participant in another. #### 2. For participants of a group When a group chat is opened, and the scope of the logged-in user is participant, he/she should be able to send messages only after the the configured intervals. You can enforce the blocking behaviour by disabling the message composer or the send button on the UI. It will get enabled only once the participant has waited for the defined amount of slow-down time. While the participant is waiting, a timer can be displayed to indicate the amount of time left after which they can send the next message. # Lists Management Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/lists-management ## Overview The Lists Management endpoints in the Moderation Service API provide essential tools for creating and managing lists of keywords or regex patterns that are crucial for effective message moderation. These endpoints enable app owners and collaborators to define specific terms, phrases, or patterns that, when detected in user-generated content, trigger moderation actions. The next section provides a detailed elaboration of the capabilities offered. To begin managing lists: * Login to your [CometChat dashboard](https://app.cometchat.com/login) and choose your app. * Navigate to **Moderation** > **Settings** in the left-hand menu. * Select the **Lists** tab. ## Default Lists Default lists are predefined lists of words, patterns and sentences that are readily available for use on your platform. Here are the standard default lists available: ### Profane Words Our default list is a comprehensive compilation of predefined profane words and phrases. This list is designed to enhance message moderation efforts by automatically identifying and flagging inappropriate language. ### Platform Circumvention The Platform Cicurvention list contains a curated set of sentences and words designed to identify attempts to circumvent platform rules and policies. These phrases are used by the AI Platform Circumvention Rule to detect and prevent efforts aimed at bypassing restrictions, ensuring compliance and maintaining platform integrity. ### Spam Detection The Default Spam Detection List identifies repetitive or irrelevant messages promoting products, services, or schemes without user consent. It helps filter out unwanted content, including bulk messages, phishing attempts, and fraudulent offers, ensuring a cleaner and more secure communication experience. ### Scam Detection The Default Scam Detection List includes messages crafted to deceive users by creating a sense of urgency, promising false rewards, or impersonating trusted entities. These messages often aim to manipulate users into sharing personal information, making payments, or clicking on malicious links. The list helps identify and block scams, protecting users from fraud, phishing attempts, and other deceptive practices. ### Fraud or Scam Indicators Prompt The Fraud or Scam Indicators list is designed to detect manipulated images used for fraudulent or deceptive activities. It helps flag fake documents, counterfeit products, and misleading visuals that could be used to scam users or spread misinformation. ### Terrorism or Extremist Promotion Prompt The Terrorism or Extremist Promotion list identifies imagery that endorses terrorism, violent extremism, or radical ideologies. It helps prevent the spread of extremist propaganda, recruitment materials, and content that incites violence. ### Minor Safety and Exploitation Prompt The Minor Safety and Exploitation list is used to detect sexualized or exploitative imagery of minors. It helps prevent child abuse, grooming, and the sharing of harmful content, ensuring compliance with child protection policies. ### Privacy or Personal Data Prompt The Privacy or Personal Data list flags images that expose sensitive or private information, such as identification documents, financial details, or personal records. This helps prevent identity theft, unauthorized data leaks, and privacy violations. ### Graphic Violence or Gore Prompt The Graphic Violence or Gore list identifies violent or gory imagery, including depictions of severe injuries, crime scenes, or graphic deaths. It helps limit exposure to disturbing content and ensures a safer viewing experience. ### Explicit or Sexual Content Prompt The Explicit or Sexual Content list is designed to detect nudity, sexually explicit imagery, or highly suggestive content. It helps enforce platform guidelines by filtering out inappropriate material. ### Hate or Harassment Prompt The Hate or Harassment list flags imagery containing hateful symbols, offensive gestures, or harassment. It helps identify and prevent content that promotes discrimination, hate speech, or targeted abuse. ### Hate and Harassment Prompt The Hate and Harassment list detects messages that contain hate speech, threats, slurs, or harassment directed at individuals or groups. It helps create a respectful and safe online environment by preventing abusive behavior. ### Explicit or Inappropriate Content Prompt The Explicit or Inappropriate Content list identifies text that includes explicit sexual descriptions, extreme violence, or other unsuitable material. It helps ensure compliance with content policies and maintains platform integrity. ### Impersonation or Fraud Prompt The Impersonation or Fraud list detects deceptive attempts to impersonate individuals, businesses, or organizations. It helps prevent identity theft, scam attempts, and fraudulent activities. ### Non-Consensual Sexual Content or Exploitation Prompt The Non-Consensual Sexual Content or Exploitation list flags messages that depict or encourage non-consensual sexual acts, grooming, or coercion. It helps protect users from exploitation and ensures adherence to safety policies. ### Privacy and Sensitive Info Prompt The Privacy and Sensitive Info list identifies messages that share personal or sensitive information without consent. It helps protect user privacy by preventing unauthorized data exposure. ### Self-Harm or Suicidal Content Prompt The Self-Harm or Suicidal Content list detects messages indicating self-harm, suicidal thoughts, or encouragement of self-injury. It helps enable early intervention and support mental health safety. ### Spam and Scam Prompt The Spam and Scam list identifies spam messages, phishing attempts, and fraudulent schemes. It helps filter out unwanted content, including bulk messages and misleading offers, ensuring a cleaner and more secure communication environment. ### Violent or Terroristic Threats Prompt The Violent or Terroristic Threats list detects content that promotes violence, terrorism, or extremist actions. It helps prevent harmful speech, glorification of violence, and threats against individuals or groups. ## Managing Lists ### Create List Allows you to define new moderation lists specifying the words or patterns under which text or custom messages should be blocked. Creating a new list from the dashboard: 1. Click the Add button within the Lists tab. 2. Create the list by saving the following details: * Name: Descriptive name for the moderation list. * ID: The unique identifier of the list. * Category: Choose the type for list, either 'word', 'pattern' or 'sentence similarity'. * Description: Detailed explanation of the list. * Your Source type for lists could be either words, patterns or sentences, separated by a comma or a CSV file. 3. Save You can also set this up from your end using the [Create Moderation List REST API](https://api-explorer.cometchat.com/reference/create-rule-keyword). ### Fetch All Lists Fetches the details of existing list lists. You can also set this up from your end using the [List Moderation Lists REST API](https://api-explorer.cometchat.com/reference/list-rule-keywords). ### Get List Fetches the details of an existing list. You can set this up from your end using the [Get Moderation List REST API](https://api-explorer.cometchat.com/reference/get-rule-keyword). ### Update List Allows you to update existing lists, which includes modifying the list name, category, and individual words or patterns within the list. Updating a list from the dashboard: 1. Click on "Edit" in the action menu of the List you want to update. 2. Update the list by saving the following details: * Name: Descriptive name for the moderation list. * Category: Choose the type for List, either 'word', 'pattern' or 'sentence similarity'. * Description: Detailed explanation of the list. * Your Source type for list could be either words, patterns or sentences separated by a comma or a CSV file. 3. Save You can also set this up from your end using the [Update Moderation List REST API](https://api-explorer.cometchat.com/reference/update-rule-keyword). ### Delete List Allows for the removal of lists from the system that are no longer needed. Deleting a list from the dashboard: * Click "Delete" in the action menu of the list you want to remove, then confirm. You can also set this up from your end using the [Delete Moderation List REST API](https://api-explorer.cometchat.com/reference/delete-rule-keyword). # OpenAI Moderation Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/open-ai/openai-custom CometChat allows you to integrate OpenAI for real-time message moderation, enabling automated detection of harmful, offensive, or inappropriate content. ## Integration ### **Step 1: Configure OpenAI Settings** 1. **Login to the CometChat Dashboard** * Navigate to [CometChat Dashboard](https://app.cometchat.com) and select your app. 2. **Navigate to Moderation Settings** * Go to **Moderation → Settings** in the left-hand menu. 3. **Open OpenAI Settings Tab** * Click on the **OpenAI Settings** tab within the Moderation Settings. 4. **Fill in the OpenAI Configuration** * **Select OpenAI Model** * Choose the OpenAI model you want to use (e.g., `gpt-4-turbo`). * **Provide OpenAI API Key** * Enter your OpenAI API key to authenticate requests. * **Set Action on OpenAI Error** * Define how the system should respond if OpenAI is unavailable (e.g., "Allow message" or "Block message"). * **Set Context Window** * Specify the number of previous messages in a conversation that will be used for OpenAI context. 5. **Click Save Settings** ### **Step 2: Enable OpenAI Moderation** 1. Navigate to **Moderation → List**. 2. Click **"Create New Rule"**. 3. Select **OpenAI** as the moderation type. 4. Select a predefined **prompt** from the List Section or create your own. 5. **Ensure that the rule type is either** `Text Contains` **or** `Image Contains`. 6. Save the rule and Enable it. > **Note:** The rule you create should be of type **Text Contains** or **Image Contains** to work with OpenAI moderation. *** # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/open-ai/openai-overview # Overview CometChat offers AI-powered message moderation to help maintain a safe and respectful chat environment. You can choose between two moderation options: ### **OpenAI Moderation** Leverage OpenAI’s AI models to automatically detect and filter offensive, harmful, or inappropriate messages in real time. This option allows you to: * **Define Custom Prompts** – Set specific prompts to classify and moderate messages based on your needs. * **Choose an AI Model** – Select the OpenAI model that best suits your moderation requirements. * **Contextual Moderation** – Configure how many previous messages from the conversation should be considered for better contextual understanding. * **Flexible Moderation Actions** – Block, allow, or take fallback actions if the API request fails. * **Secure API Management** – Provide and manage OpenAI credentials directly in the CometChat dashboard. This moderation provide flexibility to enhance user safety and compliance within your chat platform. # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/overview The Moderation feature provides a comprehensive suite of capabilities designed to manage and enforce message moderation rules across various types of messages, ensuring your platform remains safe and compliant for all users. These capabilities include rule management for creating, updating, and deleting moderation rules, as well as keyword lists for detecting inappropriate content. Additionally, automated actions promptly address potential violations, and detailed reports on blocked messages help to continuously improve safety and compliance measures. By leveraging these robust functionalities, you can effectively maintain a secure and welcoming environment on your platform. Here’s an in-depth look at the key functionalities provided by the Moderation Service: ## Rules Management This feature enables you to define and manage a set of moderation rules tailored to address inappropriate messages under various conditions. You can establish specific criteria that determine what constitutes unacceptable behavior or content, such as the use of offensive language, unsafe content, or sharing sensitive information. By customizing these rules, you ensure that the moderation system effectively identifies and manages messages that violate your platform's standards, thereby maintaining a safe and respectful environment for all users. The ability to manage these rules includes adding new rules, updating existing ones, and removing obsolete rules, providing a flexible and dynamic approach to message moderation. For more detailed management, refer to the [rules management](/moderation/rules-management) section. ## Lists Management This feature allows you to create and manage comprehensive lists of keywords or regex patterns that are used for message moderation. These lists serve as a vital component in identifying and handling inappropriate content. You can customize these lists to include specific terms and patterns that are relevant to your platform's moderation needs. Once created, these keyword lists can be linked to various moderation rules when creating or updating rules, ensuring that the moderation system effectively detects and manages content that violates your standards. The ability to manage these lists includes adding new keywords or patterns or sentences, updating existing ones, and removing those that are no longer relevant, providing a flexible and responsive approach to message moderation. For more detailed management, refer to the [lists management](/moderation/lists-management) section. ## Blocked Messages This feature allows you to retrieve all the violated messages. You can retrieve a comprehensive list of messages that have been blocked due to violations of moderation rules. Additionally, you can perform searches within this list to find specific messages or filter results based on date ranges and find details for the violation. This functionality helps you effectively monitor and manage inappropriate content, ensuring a safe and compliant environment on your platform. For more details, refer to the [Blocked Messages](/moderation/blocked-messages) section. *** ## Overview of Moderation Rules Our platform offers a wide range of moderation rules to help you detect and manage various types of risky, sensitive, or inappropriate content. Below is an overview of the available rules categorized by content type: ### 🚩 Message Moderation Rules | Name | Description | | -------------------------------------------- | --------------------------------------------------------------------------------- | | **Word Pattern Match** | Identifies profane or offensive words using word matching. | | **Contact Details Removal** | Detects and removes phone numbers from text. | | **Email Detection** | Detects and removes email addresses from messages. | | **Spam Detection (English)** | Detects spam messages in English. | | **Scam Detection (English)** | Detects scam or fraudulent text in English. | | **Platform Circumvention (English)** | Identifies attempts to bypass platform rules. | | **Toxicity Detection (English)** | Detects toxic or harmful language in text. | | **Explicit or Inappropriate Content Prompt** | Detects explicit sexual descriptions, graphic violence, or other unsuitable text. | | **Privacy and Sensitive Info Prompt** | Identifies sensitive personal information shared without consent. | | **Hate and Harassment Prompt** | Detects hateful or harassing language toward individuals or groups. | | **Self-Harm or Suicidal Content Prompt** | Detects content suggesting self-harm or suicidal thoughts. | | **Impersonation or Fraud Prompt** | Detects deceptive attempts to impersonate individuals or organizations. | | **Violent or Terroristic Threats Prompt** | Detects content promoting violence or extremism. | | **Non-Consensual Sexual Content Prompt** | Detects sexual exploitation, grooming, or non-consensual content. | | **Spam and Scam Prompt** | Identifies spam, phishing attempts, and fraudulent schemes. | ### 🖼️ Image Moderation Rules | Name | Description | | ------------------------------------------- | ---------------------------------------------------------------------------------------- | | **Unsafe & Prohibited Content** | Detects unsafe or prohibited content in images. | | **Terrorism or Extremist Promotion Prompt** | Detects extremist propaganda, terrorist symbols, or images promoting violent ideologies. | | **Minor Safety and Exploitation Prompt** | Detects child sexual content or exploitative imagery of minors. | | **Self-Harm or Suicidal Content Prompt** | Detects imagery suggesting self-harm or suicidal ideation. | | **Privacy or Personal Data Prompt** | Identifies images containing personal or sensitive data. | | **Graphic Violence or Gore Prompt** | Detects images of extreme violence or gore. | | **Explicit or Sexual Content Prompt** | Identifies nudity, explicit sexual content, or suggestive imagery. | | **Hate or Harassment Prompt** | Detects hate symbols, harassment, or extremist imagery. | | **Fraud or Scam Indicators Prompt** | Flags manipulated or fraudulent images, such as fake IDs. | ### 🎥 Video Moderation Rules | Name | Description | | ------------------------------- | ---------------------------------------------------- | | **Unsafe & Prohibited Content** | Detects unsafe or prohibited content in video files. | # Rules Management Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/rules-management ## Overview The Rules Management endpoints in the Moderation Service API provide the functionality to define and manage moderation rules that help in identifying and handling inappropriate content based on a variety of conditions. These endpoints empower app owners and collaborators to create a customized message moderation strategy tailored to the specific needs of their platform. The next section provides a detailed elaboration of the capabilities offered. To begin managing rules: * Login to your [CometChat dashboard](https://app.cometchat.com/login) and choose your app. * Navigate to **Moderation** > **Settings** in the left-hand menu. * Select the **Rules** tab. ## Default Rules Default rules are predefined sets of message moderation conditions that are readily available for use on your platform, and automatically applied to moderate messages when enabled. These default rules form the foundation of an effective message moderation strategy, combining automation with customizable options to ensure a safe, respectful, and compliant environment for platform users. Here are the standard default rules available: ### Profanity Filter This feature automatically detects and manages text and custom messages containing offensive language, profanity, or derogatory remarks using a predefined list of offensive keywords to block inappropriate content. Ensuring user interactions maintain a respectful tone and comply with community standards, enhances overall platform decency. **Example** Before enabling the profanity filter, messages containing profane words are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. ### Contact Details Filter This feature detects and manages messages containing phone numbers by applying rules to prevent the sharing of private information that could compromise user privacy or security. It protects users from potential misuse of personal data and ensures compliance with data protection regulations. **Example** Before enabling the contact details filter, messages containing phone numbers are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. ### Email Filter This feature detects and manages messages containing email addresses by applying rules to prevent the sharing of private information that could compromise user privacy or security. It protects users from potential misuse of personal data and ensures compliance with data protection regulations. **Example** Before enabling the email filter, a message containing an email address is delivered to the receiver and can be seen on the receiver's chat screen. After enabling the filter, such messages are not delivered to the receiver, like in the example where the personal email isn't delivered to the receiver. The blocked messages are then visible on the dashboard for monitoring purposes. ### AI-based Image Moderation This feature identifies and manages image-type messages containing sensitive, explicit, or prohibited content using advanced artificial intelligence algorithms for image recognition. Once detected, the system automatically blocks the images that violate platform guidelines, ensuring that such content is not displayed to users. This proactive approach safeguards users from exposure to harmful visual material, maintaining a safe and compliant environment on the platform. \**Example* Non-violating images are being delivered as seen in the example. Enabling this filter blocks violating images that are not delivered to the receiver, like in the example where the second image is indicated by a single tick in the message status on the sender's screen and isn't delivered to the receiver. The blocked messages are then visible on the dashboard for monitoring purposes. ### AI-based Video Moderation This feature identifies and manages video-type messages containing sensitive, explicit, or prohibited content using advanced artificial intelligence algorithms for image recognition. Once detected, the system automatically blocks the images that violate platform guidelines, ensuring that such content is not displayed to users. This proactive approach safeguards users from exposure to harmful visual material, maintaining a safe and compliant environment on the platform. **Example** Before enabling the AI-based Video Moderation filter, a message containing violating videos is delivered to the receiver, like in the example where the first video can be seen on the receiver's chat screen. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status on the sender's chat screen. The blocked messages are then visible on the dashboard for monitoring purposes. ### AI Message Toxicity The AI Message Toxicity Detection rule is a powerful, AI-driven tool designed to identify and flag toxic, harmful, or inappropriate language within user-generated messages. This feature analyzes text in real-time, detecting patterns of abusive speech, such as threats, harassment, hate speech, and other forms of offensive communication. By automatically blocking these messages based on predefined moderation rules, the tool helps prevent the spread of toxic content, fostering a safer and more respectful communication environment. This system empowers platform administrators to maintain community standards, allowing them to intervene or moderate flagged messages promptly. It also supports various languages and contexts, ensuring that the platform remains compliant with safety guidelines and user conduct policies. **Example** Before enabling the AI message toxicity rule, a message containing a sentence which violates AI message toxicity is delivered to the receiver and can be seen on the receiver's chat screen. After enabling the filter, such messages are not delivered to the receiver. The blocked messages are then visible on the dashboard for monitoring purposes. ### AI Platform Circumvention The AI Platform Circumvention Rule employs a list of categories related to sentence similarity to identify and manage attempts by users to circumvent platform rules. This filter analyzes user-generated content for patterns and phrases that may indicate efforts to bypass established guidelines. By leveraging AI technology, it compares new submissions against a predefined set of sentence structures and categories to detect similarities that suggest rule violations. **Example** Before enabling the platform circumvention filter, a message containing a sentence which violates platform circumvention is delivered to the receiver and can be seen on the receiver's chat screen. After enabling the filter, such messages are not delivered to the receiver. The blocked messages are then visible on the dashboard for monitoring purposes. ### AI Scam Detection The AI Scam Detection rule leverages advanced AI-powered text moderation techniques to identify and prevent scam-related messages in real-time. By analyzing message patterns and identifying specific language markers and behaviors commonly associated with scams, this rule ensures that fraudulent schemes are swiftly intercepted before reaching users. This proactive detection system scans for misleading content, phishing attempts, fake offers, and other tactics typically employed by scammers, thereby safeguarding users and maintaining the trust and security of the platform. It also continuously adapts to evolving scam strategies through machine learning, making it more effective over time. **Example** Before enabling the AI Scam Detection rule, a message containing a sentence which violates AI Scam Detection rule is delivered to the receiver and can be seen on the receiver's chat screen. After enabling the filter, such messages are not delivered to the receiver. The blocked messages are then visible on the dashboard for monitoring purposes. ### AI Spam Detection AI Spam Detection uses sophisticated AI algorithms to automatically detect and filter out spam messages in real-time. By analyzing message content and patterns, it effectively identifies unwanted or irrelevant communications, reducing the risk of spam flooding your platform. This feature helps ensure a cleaner, more efficient messaging experience, allowing users to focus on genuine, meaningful interactions. **Example** Before enabling the AI Spam Detection rule, a message containing a sentence which violates AI Spam Detection rule is delivered to the receiver and can be seen on the receiver's chat screen. After enabling the filter, such messages are not delivered to the receiver. The blocked messages are then visible on the dashboard for monitoring purposes. ### OpenAI (Message): Hate and Harassment Prompt (All Languages) This feature uses a predefined OpenAI moderation prompt to detect hateful or harassing language toward individuals or groups. By automatically identifying and blocking such content, it ensures a respectful and inclusive environment, fostering positive interactions among users. **Example** Before enabling the hate and harassment detection, messages containing hateful or harassing language are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Privacy and Sensitive Info Prompt (All Languages) This feature leverages OpenAI to detect messages that share personal or sensitive information without consent. It helps prevent unauthorized disclosure of private data, safeguarding user privacy and maintaining compliance with data protection standards. **Example** Before enabling the privacy and sensitive information detection, messages containing personal or sensitive information are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Explicit or Inappropriate Content Prompt (All Languages) This feature identifies and manages messages containing explicit sexual descriptions, graphic violence, or other unsuitable text using OpenAI moderation. It ensures that such content is automatically blocked, maintaining a safe and appropriate environment for all users. **Example** Before enabling the explicit or inappropriate content detection, messages containing explicit or inappropriate content are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Spam and Scam Prompt (All Languages) This feature uses OpenAI to detect and block spam messages, phishing attempts, and fraudulent schemes. By filtering out malicious or unwanted content, it enhances user trust and protects them from potential scams or harmful activities. **Example** Before enabling the spam and scam detection, messages containing spam or scam content are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Violent or Terroristic Threats Prompt (All Languages) This feature identifies content that encourages, promotes, or glorifies violence or extremism using OpenAI moderation. It ensures that such messages are automatically blocked, contributing to a safer and more secure platform for all users. **Example** Before enabling the violent or terroristic threats detection, messages containing violent or terroristic content are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Non-Consensual Sexual Content or Exploitation Prompt (All Languages) This feature detects messages related to sexual exploitation, grooming, or non-consensual content using OpenAI moderation. It proactively blocks such content, protecting users from harmful interactions and maintaining a safe environment. **Example** Before enabling the non-consensual sexual content or exploitation detection, messages containing such content are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Impersonation or Fraud Prompt (All Languages) This feature identifies deceptive attempts to impersonate individuals or organizations using OpenAI moderation. By detecting and blocking such content, it prevents fraudulent activities and ensures the authenticity of user interactions. **Example** Before enabling the impersonation or fraud detection, messages containing impersonation or fraudulent content are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Message): Self-Harm or Suicidal Content Prompt (All Languages) This feature uses OpenAI to detect messages suggesting self-harm, suicidal thoughts, or related instructions. It helps identify and address potentially harmful content, providing a supportive environment and connecting users with appropriate resources when needed. **Example** Before enabling the self-harm or suicidal content detection, messages containing such content are delivered to the receiver, as indicated by double ticks in the message status. After enabling the filter, such messages are not delivered to the receiver, which is indicated by a single tick in the message status. The blocked messages are then visible on the dashboard for monitoring purposes. ### OpenAI (Image): Hate or Harassment Prompt This feature uses a predefined OpenAI moderation prompt to detect hate symbols, extremist insignia, and harassing imagery in images. By automatically identifying and blocking such content, it ensures a respectful and safe environment for all users. **Example** Before enabling the hate or harassment detection for images, images containing hate symbols or harassing content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Explicit or Sexual Content Prompt This feature leverages OpenAI to identify nudity, explicit sexual content, or suggestive imagery unsuitable for general audiences. It ensures that such images are automatically blocked, maintaining a safe and appropriate environment. **Example** Before enabling the explicit or sexual content detection, images containing explicit or suggestive content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Graphic Violence or Gore Prompt This feature uses OpenAI to detect images of extreme violence, gore, or other disturbing content. It ensures that such images are automatically blocked, contributing to a safer and more secure platform. **Example** Before enabling the graphic violence or gore detection, images containing violent or disturbing content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Privacy or Personal Data Prompt This feature identifies images containing personal or sensitive data, such as IDs, addresses, or financial documents, using OpenAI moderation. It helps prevent unauthorized sharing of private information, safeguarding user privacy. **Example** Before enabling the privacy or personal data detection, images containing sensitive information are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Self-Harm or Suicidal Content Prompt This feature uses OpenAI to detect imagery suggesting self-harm, suicidal ideation, or content that promotes self-injury. It helps identify and address potentially harmful content, providing a supportive environment. **Example** Before enabling the self-harm or suicidal content detection, images containing such content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Minor Safety and Exploitation Prompt This feature detects child sexual content, exploitative imagery of minors, or unsafe depictions of children using OpenAI moderation. It proactively blocks such content, protecting minors and maintaining a safe environment. **Example** Before enabling the minor safety and exploitation detection, images containing exploitative or unsafe content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Fraud or Scam Indicators Prompt This feature flags manipulated or fraudulent images, such as fake IDs or doctored screenshots, using OpenAI moderation. It helps prevent fraudulent activities and ensures the authenticity of user interactions. **Example** Before enabling the fraud or scam indicators detection, images containing fraudulent or manipulated content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. *** ### OpenAI (Image): Terrorism or Extremist Promotion Prompt This feature detects extremist propaganda, terrorist symbols, or images promoting violent ideologies using OpenAI moderation. It ensures that such images are automatically blocked, contributing to a safer platform. **Example** Before enabling the terrorism or extremist promotion detection, images containing extremist or violent content are delivered to the receiver. After enabling the filter, such images are not delivered to the receiver. The blocked images are then visible on the dashboard for monitoring purposes. ## Rule Filters, Conditions and Actions ### Filters Filters allow you to narrow down messages based on the Sender or Receiver of a message. For Senders, you can filter by specific properties like UID, Role, Name, and Tags, or see when the sender was created. Similarly, for Receivers, you can filter by properties such as Name, GUID, Tags, Group type or see when the receiver was created, and the Type of receiver (for example, a user or group). This enables targeted filtering based on user or group attributes within the conversation. ### Conditions Conditions allow you to define criteria for blocking messages based on their type—text, image, video, or custom. You can select a keyword list, define a list of words or patterns, for text and custom messages. In addition to selecting specific words, patterns, or lists for text and custom messages, you can also choose filters based on Toxicity, Sentiment, or Sentence Similarity for more advanced moderation and content analysis. You can refine Toxicity filtering by selecting categories such as Identity Attack, Insult, Obscene, Mild Toxicity, or Severe Toxicity. For Sentiment, you can choose to filter messages based on positive or negative sentiment. In Sentence Similarity, you have the option to apply a default or custom list. Additionally, you can set a confidence percentage for each criterion to determine the threshold for blocking messages. For media messages you can select among categories like Violence, Gambling, Alcohol, Drugs and Tobacco, Rude gestures, Explicity nudity, Non-explicit nudity, Swimwear or underwear, Visually disturbing, Hate symbols or Any unsafe content. Additionally, you can set a confidence percentage for each criterion to determine the threshold for blocking messages. ### Actions Actions specify what happens when content matches the conditions. In addition to blocking the message by default, actions include options such as banning or kicking a user from a group and blocking a user. ## Configuring rules ### Create Rule Allows you to define new moderation rules specifying the conditions under which messages should be blocked. Creating a new rule from the dashboard: 1. Click the Add button within the Rules tab. 2. Configure the Rule by saving the following details: * Name: Name for the moderation rule. * Rule ID: The unique identifier of the rule. * Description: Detailed explanation of the rule's purpose. * Filter: List of filters that must be met for the rule to trigger. * Condition: List of conditions that must be met for the rule to trigger. * Action: Choose from a set of actions to be taken when a violation is detected. 3. Save 4. Enable the Rule to start moderating! You can also set this up from your end using the [Create Moderation Rule REST API](https://api-explorer.cometchat.com/reference/create-rule). ### List Rules Fetches the details of the existing list of rules. You can also set this up from your end using the [List Moderation Rules REST API](https://api-explorer.cometchat.com/reference/list-rules). ### Get Rule Fetches the details of a rule. You can set this up from your end using the [Get Moderation Rule REST API](https://api-explorer.cometchat.com/reference/get-rule). ### Update Rule Enables modifications to existing rules. This includes changing conditions, updating actions, or refining parameters to improve accuracy. Updating a rule from the dashboard: 1. Click on "Edit" in the action menu of the rule you want to update. 2. Update the Rule by saving the following details: * Name: Descriptive name for the moderation rule. * Description: Detailed explanation of the rule's purpose. * Filter: List of filters that must be met for the rule to trigger. * Condition: List of conditions that must be met for the rule to trigger. * Action: Choose from a set of actions to be taken when a violation is detected. 3. Save You can also set this up from your end using the [Update Moderation Rule REST API](https://api-explorer.cometchat.com/reference/update-rule). ### Delete Rule Permits the deletion of outdated or unnecessary rules from the system. This helps in maintaining an efficient and relevant set of moderation guidelines. Deleting a rule from the dashboard: * Click "Delete" in the action menu of the rule you want to remove, then confirm. You can also set this up from your end using the [Delete Moderation Rule REST API](https://api-explorer.cometchat.com/reference/delete-rule). ### Rule Revisions The ability to fetch all revisions of a rule in a moderation system allows app owners and collaborators to retrieve a comprehensive history of updates and changes made to specific moderation rules over time. This feature provides detailed insights into how rules have been adjusted and refined to better manage and moderate content on the platform. Viewing the rule revisions on the dashboard: 1. Click "View" in the action menu of the rule for which you wish to see revisions. 2. Navigate to the Rule History section. You can also set this up from your end using the [Get Moderation Rule Revisions REST API](https://api-explorer.cometchat.com/reference/list-rule-revisions). # Webhook Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/moderation/webhooks-overview # Android Connection Service Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/android-connection-service Learn how to send Push Notifications to your Android app using Firebase Cloud Messaging or FCM. Android Push notifications sample app View on Github ## Firebase Project Setup Visit [Firebase Console](https://console.firebase.google.com/) and login/signup using your Gmail ID. ### Step 1: Create a new Firebase Project On your Firebase Console, create a new project. This is a simple 3 step process where: 1. You give a name to your project 2. Add Google Analytics to your project (Optional) 3. Configure Google Analytics account (Optional) Click on Create and you are ready to go. ### Step 2: Add Firebase to your Android App 1. Click on the Android icon as shown on the screen below. 2. Register your Android app by providing the following details: 1. Android Package name 2. App nickname (optional) 3. Debug signing certificate SHA-1 (optional) 3. Download the google-services.json file and place it in the required location in your project. 4. Add Firebase SDK by copying and pasting the snippets in the Project-level build.gradle file. 5. Add Firebase SDK by copying and pasting the snippets in the App-level build.gradle file. 6. Click on 'Continue to Console' to finish the setup. ### Step 3: Download the service account file ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for this extension and save the following. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** * If you are setting it for the first time, Select `V2` to start using the token-based version of the Push Notification extension. * If you already have an app using `V1` and want to migrate your app to use `V2`, then Select `V1 & V2` option. This ensures that the users viewing the older version of your app also receive Push Notifications. * Eventually, when all your users are on the latest version of your app, you can change this option to `V2`, thus turning off `V1` (Topic-based) Push Notifications completely. 2. **Select the platforms that you want to support** * Select from Web, Android, Ionic, React Native, Flutter & iOS. 3. **Notification payload settings** * You can control if the notification key should be in the Payload or not. Learn more about the FCM Messages [here](https://firebase.google.com/docs/cloud-messaging/concept-options). 4. **Push payload message options** The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** * Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications * These are pretty self-explanatory and you can toggle them as per your requirement. ## Android App Setup In the Firebase Project setup, we did the following things: 1. Added google-services.json file to the project. 2. Added the required Firebase SDK snippets to the Project-level build.grade file. 3. Added the required Firebase SDK snippets to the App-level build.gradle file. If you want more details, check the [Firebase Documentation](https://firebase.google.com/docs/cloud-messaging/android/client). ### Step 1: Register the FCM Token on user login 1. Initialize CometChat and then login your user. 2. On successful login, you can register the obtained FCM Token using `CometChat.registerTokenForPushNotification()` function call. (You can see the process of getting the FCM Token in the next step) ```java CometChat.registerTokenForPushNotification(MyFirebaseMessagingService.token, new CometChat.CallbackListener() { @Override public void onSuccess(String s) { Log.e( "onSuccessPN: ",s ); } @Override public void onError(CometChatException e) { Log.e("onErrorPN: ",e.getMessage() ); } }); ``` ```kotlin CometChat.registerTokenForPushNotification(MyFirebaseMessagingService.token, object : CallbackListener() { override fun onSuccess(s: String?) { Log.e("onSuccessPN: ", s) } override fun onError(e: CometChatException) { Log.e("onErrorPN: ", e.message) } }) ``` To fetch the registered token you can use below Firebase method. ```java FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener( new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (!task.isSuccessful()) { return; } token = task.getResult().getToken(); //CometChat.registerTokenForPushNotification(token, CometChat.CallbackListener()); } }); ``` ```kotlin FirebaseInstanceId.getInstance().getInstanceId() .addOnCompleteListener(object : OnCompleteListener() { fun onComplete(task: com.google.android.gms.tasks.Task) { if (!task.isSuccessful()) { return } token = task.getResult().getToken() //CometChat.registerTokenForPushNotification(token,CometChat.CallbackListener()) } }) ``` ### Step 2: Setup ConnectionService. **ConnectionService** is an abstract service used to handle VoIP & other calls. It is part of android.telecom package which helps to handle telecom services. ConnectionService can be used either as System-Managed Service where System defined UI is shown to handle the calls. It can also be used as Self-Managed Service where users can show their own calling UI to handle the calls. *Note - Currently the sample app uses system-managed connection service, So the System UI will be displayed to handle incoming calls.* Learn more about [ConnectionService](https://developer.android.com/reference/android/telecom/ConnectionService). | Files | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [CallConnectionService.java](https://github.com/cometchat/cometchat-push-notification-app-android/blob/v4-push-notifications-extension/app/src/main/java/com/cometchat/pushnotificationsample/CallConnectionService.java) | Custom ConnectionService file which is used to handle incoming & outgoing calls. It is used to manages the ConnectionService with your app. It also handles PhoneAccounts and bind it's services to Telecom. | | [CallConnection.java](https://github.com/cometchat/cometchat-push-notification-app-android/blob/v4-push-notifications-extension/app/src/main/java/com/cometchat/pushnotificationsample/CallConnection.java) | Custom Connection class which is used to handle the callbacks of ConnectionService. Call backs such as onAnswer(), onReject(), onHold(), etc. | | [CallManager.java](https://github.com/cometchat/cometchat-push-notification-app-android/blob/v4-push-notifications-extension/app/src/main/java/com/cometchat/pushnotificationsample/CallConnectionService.java) | It is used to manages the ConnectionService with your app. It also handles PhoneAccounts and bind it's services to Telecom. | ### Step 3: Receive notifications 1. The FCM Token can be received by overriding the `onNewToken()` method. This token is stored as a String variable. You can choose to store it in SharedPreferences as well. 2. To receive messages, you need to override the onMessageReceived(RemoteMessage remoteMessage). 3. [PushNotificationService.java](https://github.com/cometchat/cometchat-push-notification-app-android/blob/v4-push-notifications-extension/app/src/main/java/com/cometchat/pushnotificationsample/PushNotificationService.java) has the code that provides a way you can handle messages received from CometChat users and groups. 4. Since Android O, there have been certain restrictions added for background tasks and users cannot launch intent directly from the service. More details [here](https://developer.android.com/guide/components/activities/background-starts). 5. You also need to add the above-mentioned MyFirebasMessagingService.java fil in your AndroidManifest.xml to make Push notification work in the background as well. ```xml ``` ### Converting Push Notification Payloads to Message Objects CometChat provides a method `CometChatHelper.processMessage()` to convert the message JSON to the corresponding object of `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call`. This code needs to be added to the `onMessageReceived()` method of the `FirebaseMessagingService` class. ```java CometChatHelper.processMessage(new JSONObject(remoteMessage.getData().get("message")); ``` Type of Attachment can be of the following the type\ `CometChatConstants.MESSAGE_TYPE_IMAGE`\ `CometChatConstants.MESSAGE_TYPE_VIDEO`\ `CometChatConstants.MESSAGE_TYPE_AUDIO`\ `CometChatConstants.MESSAGE_TYPE_FILE` Push Notification Payload sample for text and media messages- ```json { "alert": "Nancy Grace: Text Message", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "text": "Text Message" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "142", "sentAt": 1555668711, "category": "message", "type": "text" } } ``` ```json { "alert": "Nancy Grace: has sent an image", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "attachments": [ { "extension": "png", "size": 14327, "name": "extension_leftpanel.png", "mimeType": "image/png", "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" } ], "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "145", "sentAt": 1555671238, "category": "message", "type": "image" } } ``` # Android Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/android-push-notifications The Push Notification extension allows you to send push notifications to mobile apps and desktop browsers. In this section, we will see how to send Push Notifications to your Android app using Firebase Cloud Messaging or FCM. Use Connection Service If you want to use the System's native call service to handle calls, please refer to our guide on [Android - Connection Service](/notifications/android-connection-service) Android Push notifications sample app View on Github ## Firebase Project Setup Visit [Firebase Console](https://console.firebase.google.com) and login/signup using your Gmail ID. ### Step 1: Create a new Firebase Project On your Firebase Console, create a new project. This is a simple 3 step process where: 1. You give a name to your project 2. Add Google Analytics to your project (Optional) 3. Configure Google Analytics account (Optional) Click on Create and you are ready to go. ### Step 2: Add Firebase to your Android App 1. Click on the Android icon as shown on the screen below. 2. Register your Android app by providing the following details: 1. Android Package name 2. App nickname (optional) 3. Debug signing certificate SHA-1 (optional) 3. Download the `google-services.json` file and place it in the required location in your project. 4. Add Firebase SDK by copying and pasting the snippets in the Project-level `build.gradle` file. 5. Add Firebase SDK by copying and pasting the snippets in the App-level `build.gradle` file. 6. Click on 'Continue to Console' to finish the setup. ### Step 3: Download the service account file ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for this extension and save the following. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** * If you are setting it for the first time, Select `V2` to start using the token-based version of the Push Notification extension. * If you already have an app using `V1` and want to migrate your app to use `V2`, then Select `V1 & V2` option. This ensures that the users viewing the older version of your app also receive Push Notifications. * Eventually, when all your users are on the latest version of your app, you can change this option to `V2`, thus turning off `V1` (Topic-based) Push Notifications completely. 2. **Select the platforms that you want to support** * Select from Web, Android, Ionic, React Native, Flutter & iOS. 3. **Notification payload settings** * You can control if the notification key should be in the Payload or not. Learn more about the FCM Messages [here](https://firebase.google.com/docs/cloud-messaging/concept-options). 4. **Push payload message options** The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** * Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications * These are pretty self-explanatory and you can toggle them as per your requirement. ## Android App Setup In the Firebase Project setup, we did the following things: 1. Added google-services.json file to the project. 2. Added the required Firebase SDK snippets to the Project-level build.grade file. 3. Added the required Firebase SDK snippets to the App-level build.gradle file. If you want more details, check the [Firebase Documentation](https://firebase.google.com/docs/cloud-messaging/android/client). ### Step 1: Register the FCM Token on user login 1. Initialize CometChat and then login your user. 2. On successful login, you can register the obtained FCM Token using `CometChat.registerTokenForPushNotification()` function call. (You can see the process of getting the FCM Token in the next step) ```java CometChat.registerTokenForPushNotification(MyFirebaseMessagingService.token, new CometChat.CallbackListener() { @Override public void onSuccess(String s) { Log.e( "onSuccessPN: ",s ); } @Override public void onError(CometChatException e) { Log.e("onErrorPN: ",e.getMessage() ); } }); ``` ```kotlin CometChat.registerTokenForPushNotification(MyFirebaseMessagingService.token, object : CallbackListener() { override fun onSuccess(s: String?) { Log.e("onSuccessPN: ", s) } override fun onError(e: CometChatException) { Log.e("onErrorPN: ", e.message) } }) ``` To fetch the registered token you can use below Firebase method. ```java FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener( new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (!task.isSuccessful()) { return; } token = task.getResult().getToken(); //CometChat.registerTokenForPushNotification(token, CometChat.CallbackListener()); } }); ``` ```kotlin FirebaseInstanceId.getInstance().getInstanceId() .addOnCompleteListener(object : OnCompleteListener() { fun onComplete(task: com.google.android.gms.tasks.Task) { if (!task.isSuccessful()) { return } token = task.getResult().getToken() //CometChat.registerTokenForPushNotification(token,CometChat.CallbackListener()) } }) ``` ### Step 2: Receive notifications 1. The FCM Token can be received by overriding the `onNewToken()` method. This token is stored as a String variable. You can choose to store it in SharedPreferences as well. 2. To receive messages, you need to override the onMessageReceived(RemoteMessage remoteMessage). 3. [PushNotificationService.java](https://github.com/cometchat/cometchat-push-notification-app-android/blob/v4-push-notifications-extension/app/src/main/java/com/cometchat/pushnotificationsample/PushNotificationService.java) has the code that provides a way you can handle messages received from CometChat users and groups. 4. CallNotificationAction.class is a BroadcastReceiver which is used to handle call events when your app is in the background state. 5. Since Android O, there have been certain restrictions added for background tasks and users cannot launch intent directly from the service. More details [here](https://developer.android.com/guide/components/activities/background-starts). 6. We suggest you to create notification channel inside your application class. After Android O, it is necessary to register notification channel to allow notifications of your apps. ```java private void createNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = getString(R.string.app_name); String description = getString(R.string.channel_description); int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel channel = new NotificationChannel("2", name, importance); channel.setDescription(description); channel.enableVibration(true); channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); // Register the channel with the system; you can't change the importance // or other notification behaviors after this NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } ``` * You also need to add both of the above-mentioned files in your AndroidManifest.xml to make Push notification work in the background as well. ```xml ``` ## Advanced ### Sending Custom Notification body Push notification has 2 parts, namely, the notification title and notification body. The title can be: a. Name of the sender in case of one-on-one message. (E.g.: Nancy Grace) b. Name of the sender followed by group name for group messages (E.g.: Nancy Grace @ Hiking Group) The body of the message depends upon the type of message being sent. You can send a custom body by specifying the `pushNotification` key followed by some user-defined string for the notification body inside `metadata` while sending the message. The following code shows an example of a Custom body using a message of category=custom. This is however not just limited to a custom category of messages. ```java String receiverId="cometchat-uid-1"; JSONObject metaData=new JSONObject(); JSONObject customData=new JSONObject(); try { metaData.put("pushNotification","Custom Notification body"); customData.put("yourkey","Your Value"); } catch (JSONException e) { e.printStackTrace(); } CustomMessage customMessage=new CustomMessage(receiverId,CometChatConstants.RECEIVER_TYPE_USER,customData); customMessage.setMetadata(metaData); CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener() { @Override public void onSuccess(CustomMessage customMessage) { Log.d(TAG, "onSuccess: "+customMessage.toString()); } @Override public void onError(CometChatException e) { Log.d(TAG, "onError: "+e.getMessage()); } }); ``` ```kotlin var receiverId:String="cometchat-uid-1" var metaData:JSONObject=JSONObject() var customData:JSONObject= JSONObject() try { metaData.put("pushNotification","Custom Notification Body") customData.put("yourkey","Your Value") } catch (e:JSONException) { e.printStackTrace() } var customMessage = CustomMessage(receiverId,CometChatConstants.RECEIVER_TYPE_USER,customData) customMessage.metadata = metaData; CometChat.sendCustomMessage(customMessage, object :CometChat.CallbackListener() { override fun onSuccess(p0: CustomMessage?) { Log.d(TAG,"onSuccess ${p0?.toString()}") } override fun onError(p0: CometChatException?) { Log.d(TAG,"onError ${p0?.message}") } }) ``` ### Converting Push Notification Payloads to Message Objects CometChat provides a method `CometChatHelper.processMessage()` to convert the message JSON to the corresponding object of `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call`. This code needs to be added to the `onMessageReceived()` method of the `FirebaseMessagingService` class. ```java CometChatHelper.processMessage(new JSONObject(remoteMessage.getData().get("message")); ``` Type of Attachment can be of the following the type\ `CometChatConstants.MESSAGE_TYPE_IMAGE`\ `CometChatConstants.MESSAGE_TYPE_VIDEO`\ `CometChatConstants.MESSAGE_TYPE_AUDIO`\ `CometChatConstants.MESSAGE_TYPE_FILE` Push Notification Payload sample for text and media messages- ```json { "alert": "Nancy Grace: Text Message", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "text": "Text Message" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "142", "sentAt": 1555668711, "category": "message", "type": "text" } } ``` ```json { "alert": "Nancy Grace: has sent an image", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "attachments": [ { "extension": "png", "size": 14327, "name": "extension_leftpanel.png", "mimeType": "image_png", "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" } ], "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "145", "sentAt": 1555671238, "category": "message", "type": "image" } } ``` ### Handle Push Notification Actions. **Step 1. Process push notification payload and grab BaseMessage object** To open a chat view, firstly you will need a BaseMessage object. You can grab this from the push notification payload received in `onMessageReceived(RemoteMessage message)`. You need to call `CometChat.processMessage()` method to process push notification payload. ```java @Override public void onMessageReceived(RemoteMessage remoteMessage) { try { JSONObject messageData = new JSONObject(remoteMessage.getData().get("message")); BaseMessage baseMessage = CometChatHelper.processMessage(messageData); //Process BaseMessage and show Notification } catch (JSONException e) { e.printStackTrace(); } } ``` **Step 2 . Handle Notification Actions** You can launch the chat view after you tap on the Message Notification by creating PendingIntent and set it with NotificationBuilder object. CometChatMessageListActivity is part of UI Kit Library. You can replace CometChatMessageListActivity with your required class. # Capacitor, Cordova & Ionic Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/capacitor-cordova-ionic-push-notifications Learn how to setup Push Notifications for Capacitor, Cordova and Ionic framework using Firebase Cloud Messaging or FCM. Ionic/Cordova Push notifications sample app View on Github ## Firebase Project Setup Visit [Firebase Console](https://console.firebase.google.com/) and login/signup using your Gmail ID. ### Step 1: Create a new Firebase Project On your Firebase Console, create a new project. This is a simple 3 step process where: 1. You give a name to your project 2. Add Google Analytics to your project (Optional) 3. Configure Google Analytics account (Optional) Click on Create and you are ready to go. ### Step 2: Add Firebase to your App React native setup will require 2 files for Android and iOS: 1. For Android, you need to download the `google-services.json` file. You can refer to the [Android Firebase Project Setup - Step 2](/notifications/android-push-notifications#firebase-project-setup) and resume here once done. 2. For iOS, you need to download the `GoogleService-Info.plist` file. You can refer to the [iOS Firebase Project Setup - Step 2](/notifications/ios-fcm-push-notifications#firebase-project-setup) and resume here once done. 3. For web, you need to have the Firebase Config object. You can refer to the [Web Firebase Project Setup - Step 2](/notifications/web-push-notifications#firebase-project-setup) and resume here once done. ### Step 3: Download the service account file ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for this extension and save the following. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** * If you are setting it for the first time, Select `V2` to start using the token-based version of the Push Notification extension. * If you already have an app using `V1` and want to migrate your app to use `V2`, then Select `V1 & V2` option. This ensures that the users viewing the older version of your app also receive Push Notifications. * Eventually, when all your users are on the latest version of your app, you can change this option to `V2`, thus turning off `V1` (Topic-based) Push Notifications completely. 2. **Select the platforms that you want to support** * Select from Web, Android, Ionic, React Native, Flutter & iOS. 3. **Notification payload settings** * You can control if the notification key should be in the Payload or not. Learn more about the FCM Messages [here](https://firebase.google.com/docs/cloud-messaging/concept-options). 4. **Push payload message options** The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** * Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications * These are pretty self-explanatory and you can toggle them as per your requirement. ## App Setup ### Step 1: Initial plugin setup 1. For Cordova & Ionic, there are numerous plugins available via NPM which can be used to set up push notifications for your apps like [FCM Plugin](https://ionicframework.com/docs/v3/native/fcm/) and [Push Plugin](https://ionicframework.com/docs/native/push). 2. To setup Push Notification, you need to follow the steps mentioned in the Plugin's Documentation. At this point, you will have: 1. Separate apps created on the Firebase console. (For Web, Android and iOS). 2. Plugin setup completed as per the respective documentation. ### Step 2: Register FCM Token 1. This step assumes that you already have a React Native app setup with CometChat installed. Make sure that the CometChat object is initialized and user has been logged in. 2. On the success callback of user login, you can fetch the FCM Token and register it with the extension as shown below: ```js // Pseudo-code with async-await syntax // Using the FCM Plugin const APP_ID = 'APP_ID'; const REGION = 'REGION'; const AUTH_KEY = 'AUTH_KEY'; const UID = 'UID'; const APP_SETTINGS = new CometChat.AppSettingsBuilder() .subscribePresenceForAllUsers() .setRegion(REGION) .build(); try { // First initialize the app await CometChat.init(APP_ID, APP_SETTINGS); // Login the user await CometChat.login(UID, AUTH_KEY); // Login is successful so next step // Get the FCM device token // You should have imported the following in the file: // import { FCM } from '@ionic-native_fcm'; const FCM_TOKEN = await fcm.getToken(); // Register the token for Push Notifications (legacy) await CometChat.registerTokenForPushNotification(FCM_TOKEN); } catch (error) { // Handle errors gracefully } ``` 3. Registration also needs to happen in case of token refresh as shown below: ```js // Pseudo-code // You should have imported the following in the file: // import { FCM } from '@ionic-native_fcm'; try { // Listen to whether the token changes return fcm.onTokenRefresh(FCM_TOKEN => { await CometChat.registerTokenForPushNotification(FCM_TOKEN); }); // ... } catch(error) { // Handle errors gracefully } ``` For more details, visit documentation. ### Step 3: Receive Notifications ```js // Pseudo-code import messaging from '@react-native-firebase_messaging'; import { Alert } from 'react-native'; // Implementation can be done in a life-cycle method or hook const unsubscribe = messaging().onMessage(async (remoteMessage) => { Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage)); }); ``` ### Step 4: Stop receiving Notifications 1. On CometChat.logout will stop receiving notifications. 2. As a good practice, you can also delete the FCM Token by calling `deleteToken` on the fcm object. ```js // Pseudo-code using async-await syntax logout = async () => { // User logs out of the app await CometChat.logout(); }; ``` ## Advanced ### Handle Custom Messages To receive notification of `CustomMessage`, you need to set metadata while sending the `CustomMessage`. ```js var receiverID = 'UID'; var customData = { latitude: '50.6192171633316', longitude: '-72.68182268750002', }; var customType = 'location'; var receiverType = CometChat.RECEIVER_TYPE.USER; var metadata = { pushNotification: 'Your Notification Message', }; var customMessage = new CometChat.CustomMessage( receiverID, receiverType, customType, customData ); customMessage.setMetadata(metadata); CometChat.sendCustomMessage(customMessage).then( (message) => { // Message sent successfully. console.log('custom message sent successfully', message); }, (error) => { console.log('custom message sending failed with error', error); // Handle exception. } ); ``` ### Converting push notification payload to message object CometChat SDK provides a method `CometChat.CometChatHelper.processMessage()` to convert the message JSON to the corresponding object of TextMessage, MediaMessage,CustomMessage, Action or Call. ```js var processedMessage = CometChat.CometChatHelper.processMessage(JSON_MESSAGE); ``` Type of Attachment can be of the following the type:\ `CometChatConstants.MESSAGE_TYPE_IMAGE`\ `CometChatConstants.MESSAGE_TYPE_VIDEO`\ `CometChatConstants.MESSAGE_TYPE_AUDIO`\ `CometChatConstants.MESSAGE_TYPE_FILE` Push Notification: Payload Sample for Text Message and Attachment/Media Message ```json { "alert": "Nancy Grace: Text Message", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "text": "Text Message" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "142", "sentAt": 1555668711, "category": "message", "type": "text" } } ``` ```json { "alert": "Nancy Grace: has sent an image", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "attachments": [ { "extension": "png", "size": 14327, "name": "extension_leftpanel.png", "mimeType": "image/png", "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" } ], "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "145", "sentAt": 1555671238, "category": "message", "type": "image" } } ``` # Constraints And Limits Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/constraints-and-limits ## Constraints To implement Notification features, the app must implement certain versions of UI Kits and SDKs. (Note: If you download a UI Kit, it has a corresponding Chat and Call SDK integrated into the same and does not have to be separately downloaded). * All UI Kits above version 4 are supported. (For Flutter, `Calls UI Kit v4.3.0 & above` are supported) * All Calls SDK versions are supported. (For Flutter, `Calls SDK v4.0.9 & above` are supported) * Notifications are supported in iOS Chat SDK v4.0.51 and above, Android Chat SDK v4.0.9 and above, Flutter Chat SDK v4.0.15 and above, React Native Chat SDK v4.0.10 and above, JavaScript Chat SDK v4.0.8 and above and Ionic (Cordova) SDK v4.0.8 and above. * Chat Widgets are not compatible with Push Notifications. It is possible to use Notification features without using UI Kits with an entirely SDK dependent solution with the above-mentioned SDK versions. ### Supported Web Browsers & Versions * Chrome version 50 and above. * Firefox version 44 and above. * Edge version 17 and above. * Opera version 42 and above. ### Supported Platforms & Versions * iOS: v11 and above. * Android: v21 and above. * Flutter: v2.17 and above. * React Native: v0.73 and previous versions. * React: v18 and previous versions. * Angular: v17 and previous versions. * Vue: v3 and previous versions. * Capacitor: v6 and previous versions. ## Limits | Entity / Parameter | Limit | | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | Maximum group size supported for Push Notifications | 1000 members or less | | Maximum group size supported for Email Notifications | 30 members or less | | Maximum group size supported for SMS Notifications | 30 members or less | | Maximum Push tokens by an auth token | 1 | | Maximum SMS length | 160 characters. (If a message exceeds this limit, the remaining content will go as another message) | | Minimum interval between two emails (in minutes) | 1 minute. | | Minimum interval between two SMS (in minutes) | 1 minute. | ## Limitations * iOS platform: * Calling notifications work when using APNS (VoIP). Calling notifications are not supported to work with FCM. (Applicable for native iOS, React Native iOS, Flutter iOS) * Android platform: * Push notifications using FCM work on devices that have Google Mobile Services. Push notifications don’t work on Huawei phones. * Flutter (Android) with FCM: * When the app is in the foreground state, notifications for edited and deleted messages don’t work. The original text is displayed in the notification even though the corresponding message has been edited/deleted. * Browser notifications are not supported on mobile devices. # Customizations Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/email-customization Customizations allow controlling notifications for message events, group events, and call events. Users can set preferences for incoming notifications based on notification schedules, Do Not Disturb (DND) mode, and the mute status of specific conversations. Additional customizations include modifications to notification templates and sounds. These options also ensure that user privacy is maintained while displaying notifications on the device. For more information, refer to [Preferences, Templates & Sounds](/notifications/preferences-templates-sounds) documentation. # Integration Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/email-integration Email notifications integration is possible using SendGrid as a provider or a custom provider. Custom provider allows integration with providers other than SendGrid. ## SendGrid We have partnered with SendGrid for sending Email Notifications and hence you need to set up an account on [SendGrid](https://www.sendgrid.com/) before you start using the extension. ### Get your SendGrid API Key 1. Log in to your SendGrid account. 2. In the left navigation pane, go to Settings and select API Keys. 3. If you don't have an API Key yet, click on Create API Key. 4. Give a name to your API Key and select Full Access to get started. 5. Make a note of the **API key** for later use. ### Create an email template 1. Log in to your SendGrid account. 2. In the left navigation pane, go to Email API and select Dynamic Templates. 3. Click on "Create a Dynamic Template" and give a name to your template. 4. In the Template listing, expand your template and click on "Add Version". 5. Under the "Your Email Designs" tab, select Blank Template. 6. As we have the following HTML template ready for you, select the "Code Editor" option. 7. Paste the code for the email template. You should be able to see the Preview in the Right pane. 8. Click on Settings on the Left to expand the Settings drawer. 9. Enter the Version name and the value for Subject as `{{subject}}` and hit "Save". 10. You have now successfully created a Template with a version. 11. From the Dynamic Templates listing page, expand your Template and make a note of the **Template ID** for later use. 12. The payload sent by the extension to SendGrid is as follows: ```json { "to": { "uid": "cometchat-uid-1", "email": "andrew-joseph@example.com", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Are we meeting on this weekend?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "📷 Has shared an image", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "senderDetails": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp" } } ``` ```json { "to": { "uid": "cometchat-uid-1", "email": "andrew-joseph@example.com", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, "messages": [ { "sender": { "uid": "cometchat-uid-5", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp", "name": "John Paul" }, "message": "Hello all! What's up?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "This is the place I was thinking about", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "groupDetails": { "guid": "cometchat-guid-1", "name": "Hiking Group", "icon": "https://assets.cometchat.io/sampleapp/v2/groups/cometchat-guid-1.webp" } } ``` 13. The email template recommended by us is as follows. Replace "[https://www.YOURSITE.com](https://www.YOURSITE.com)" with your website's URL in the below template. ```html Simple Transactional Email

While you were away...

Hello, {{to.name}}! You have {{messages.length}} new messages{{#if groupDetails}} in {{groupDetails.name}}{{/if}}.

{{#each messages}} {{#if this.message}} {{/if}} {{/each}}


{{this.sender.name}}
{{this.message}}
Visit

To unsubscribe to these notifications, click here.

``` ### Add an unsubscribe group An unsubscribe group will allow your users to unsubscribe to only chat email notifications and will allow you to continue to send other emails to that user via SendGrid. 1. In the left pane, go to Suppressions and select Unsubscribe Groups. 2. Click on "Create New Group" and give it a name and proper description. 3. Save your new group and make a note of the **Unsubscribe Group ID** for later use. ### Store contact details Store the Email IDs of your users by using our [Update Contact details API](https://api-explorer.cometchat.com/reference/notifications-update-contact-details). ### Enable Email notifications 1. Login to [CometChat](https://app.cometchat.com/login) dashboard and select your app. 2. Navigate to **Notifications** > **Notifications** in the left-hand menu. 3. Enable Email notifications feature. ### Save the SendGrid credentials Save the following details: * SendGrid API key * SendGrid Template ID * SendGrid Unsubscribe Group ID * Sender's name * Sender's email The domain used in Sender's Email needs to be Authenticated. Refer to SendGrid's documentation on [Domain Authentication](https://docs.sendgrid.com/ui/account-and-settings/how-to-set-up-domain-authentication) for more details. Use the complete authenticated domain in the sender's email address. For eg, if your domain is example.com and the authenticated domain is em1235.example.com, then the sender's email address should be [sender@em1235.example.com](mailto:sender@em1235.example.com) and not [sender@example.com](mailto:sender@example.com) ### Save user's timezone A user's timezone is required to allow them to set a schedule for receiving notifications. In case the timezone is not registered, the default timezone for * For US region: EST * For EU region: GMT * For IN region: Asia/Kolkata The timezone can be registered for a user from the SDK using the `updateTimezone()` method of `CometChatNotifications` class. This functionality is available in the following SDK versions: 1. Android SDK version 4.0.9 and above 2. iOS SDK version 4.0.51 and above 3. Web SDK version 4.0.8 and above 4. React Native SDK version 4.0.10 and above 5. Ionic Cordova SDK version 4.0.8 and above 6. Flutter SDK version 4.0.15 and above ### Receive notifications Send a message to any user and keep the conversation unread for the designated amount of time to receive an email notification. ### Configure email replies In the SendGrid provider settings, enable the email replies. Optionally, you can set a different sender's email address. Only ensure that the it doesn't contain any "+" symbol in it. Copy the Replies webhook URL as that will be required for Inbound parse configuration on SendGrid's end. Follow the [SendGrid's Inbound parse webhook](https://www.twilio.com/docs/sendgrid/for-developers/parsing-email/setting-up-the-inbound-parse-webhook) steps. Before saving the Inbound Host and URL: 1. Uncheck Spam Check checkbox. 2. Uncheck Send Raw checkbox. Once this setup is successful, users will be able to reply to an email notification and send messages in a particular conversation on CometChat. The parsing of the replies is heavily dependent on the Email client used and the content of the reply. ## Custom Email provider Custom provider allows you to make use of providers apart from SendGrid for triggering Email notifications. This is implemented using webhook URL which gets all the required details that can be used to trigger Email notifications. #### Pre-requisite 1. Your webhook endpoint must be accessible over `HTTPS`. This is essential to ensure the security and integrity of data transmission. 2. This URL should be publicly accessible from the internet. 3. Ensure that your endpoint supports the `HTTP POST` method. Event payloads will be delivered via `HTTP POST` requests in `JSON` format. 4. Configure your endpoint to respond immediately to the CometChat server with a 200 OK response. The response should be sent within 2 seconds of receiving the request. 5. For security, it is recommended to set up Basic Authentication that is usually used for server-to-server calls. This requires you to configure a username and password. Whenever your webhook URL is triggered, the HTTP Header will contain: ```html Authorization: Basic ``` #### Add credentials 1. Click on the "+ Add Credentials" button. 2. Enable the provider. 3. Enter the publically accessible Webhook URL. 4. It is recommended to enable Basic Authentication. 5. Enter the username and password. 6. Enabling the "Trigger only if email address is stored with CometChat" setting requires users' email addresses to be stored with CometChat using the [Update Contact details API](https://api-explorer.cometchat.com/reference/notifications-update-contact-details). When enabled, the webhook is triggered only for those users. If this setting is disabled, the webhook triggers regardless of whether users' email addresses are stored with CometChat. 7. Save the credentials. #### How does it work? The Custom provider is triggered once for an event in one-on-one conversation. In case of notifying the members of a group, the custom provider is triggered once for each user present in that group. For example, if there are 100 members in the group, your webhook will receive 100 HTTP requests. Once for each member of the group. ```json { "trigger": "email-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-1", "email": "andrew-joseph@example.com", // Optional "name": "Andrew Joseph" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Are we meeting on this weekend?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "📷 Has shared an image", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "senderDetails": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp" }, "subject": "New messages from Susan Marie" }, "appId": "app123", "region": "us/eu/in", "webhook": "custom" } ``` ```json { "trigger": "email-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-1", "email": "andrew-joseph@example.com", // Optional "name": "Andrew Joseph" }, "messages": [ { "sender": { "uid": "cometchat-uid-5", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp", "name": "John Paul" }, "message": "Hello all! What's up?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "This is the place I was thinking about", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "groupDetails": { "guid": "cometchat-guid-1", "name": "Hiking Group", "icon": "https://assets.cometchat.io/sampleapp/v2/groups/cometchat-guid-1.webp" }, "subject": "New messages in Hiking Group" }, "appId": "app123", "region": "us/eu/in", "webhook": "custom" } ``` #### Sample server-side code ```javascript const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; app.use(express.json()); // Optional: Basic authentication middleware const basicAuth = (req, res, next) => { const authHeader = req.headers['authorization']; if (!authHeader || !authHeader.startsWith('Basic ')) { return res.status(401).json({ message: 'Unauthorized' }); } next(); }; const triggerEmailNotification = async (to, data) => { let { name, uid, email } = to; let { groupDetails, senderDetails, subject } = data; if (groupDetails) { console.log('Received webhook for group email notification'); } if (senderDetails) { console.log('Received webhook for one-on-one email notification'); } if (email == null) { // Your implementation to fetch Email ID email = await fetchEmailIDFor(uid); } // Your implementation for sending the email notification await sendEmail(email, subject, data.messages); }; app.post('/webhook', basicAuth, (req, res) => { const { trigger, data, appId, region, webhook } = req.body; if ( trigger !== 'email-notification-payload-generated' || webhook !== 'custom' ) { return res.status(400).json({ message: 'Invalid trigger or webhook type' }); } console.log('Received Webhook:', JSON.stringify(req.body, null, 2)); triggerEmailNotification(to, data) .then((result) => { console.log( 'Successfully triggered email notification for', appId, to.uid, result ); }) .catch((error) => { console.error( 'Something went wrong while triggering email notification for', appId, to.uid, error.message ); }); res.status(200).json({ message: 'Webhook received successfully' }); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); ``` ## Next steps Have a look at the available [preferences](/notifications/preferences-templates-sounds#email-notification-preferences) and [templates](/notifications/preferences-templates-sounds#email-notification-templates) for email notifications. # Email Notification Extension (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/email-notification-extension **Legacy Notice**: This extension is already included as part of the core messaging experience and is scheduled for deprecation in the near future. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. ## About the extension The Email Notification extension helps you to notify offline users about unread messages via emails. After you've configured the extension, your users will receive email notifications for unread messages in one-on-one conversations. The Email notifications extension allows you to have the following two integrations: 1. Integration using [Webhook](/notifications/email-notifications#integration-using-webhook) 2. Integration using [SendGrid](/notifications/email-integration#sendgrid) ## Before you begin These steps are required irrespective of the integration. ### 1. Storing user emails You can use our [Update user](https://api-explorer.cometchat.com/reference/update-user) API to set private metadata for a user. We recommend adding this code where you call our [Create user](https://api-explorer.cometchat.com/reference/creates-user) API. Alternatively, just for the sake of testing purposes, you can add this from the CometChat Dashboard as well. 1. Login to [CometChat](https://app.cometchat.com/login). 2. Select your app and go to the "Users" section. 3. Click on the Edit option available under the three dots for the user under consideration. 4. Click on the Edit button on the Details section. 5. Paste the below JSON in the Metadata input box and hit Save. The Metadata is a JSON that should have the `@private` key present and should have the value `email` specified for the user. The format for the private metadata must be as follows: ```json { "@private": { "email":"abc@xyz.com" } } ``` ### 2. Read Receipts Be sure to implement read receipts so that your users receive email notifications for unread messages only. ## Integration using Webhook This method of integration allows you to choose your Email API vendor and send Email notifications as per your needs. ### 1. Create your webhook Build your backend that integrates with the Email API vendor of your choice. Expose a URL that accepts an HTTP POST request.This URL will be the "Webhook URL" to which the extension will send the following details: | Key | Value | Description | | ---- | -------------- | ------------------------------------------------------------- | | to | String (email) | The Email ID of the user to send the notification. | | body | array | An array of message objects that were missed by the receiver. | ```json { "to": "user@email.com", "body": [ { "id": "121", "conversationId": "cometchat-uid-1_user_cometchat-uid-3", "sender": "cometchat-uid-3", "receiverType": "user", "receiver": "cometchat-uid-1", "category": "message", "type": "text", "data": { "text": "1", "entities": { "sender": { "entity": { "uid": "cometchat-uid-3", "name": "Nancy Grace", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "available", "lastActiveAt": 1639650770 }, "entityType": "user" }, "receiver": { "entity": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "status": "offline", "lastActiveAt": 1639587777, "conversationId": "cometchat-uid-1_user_cometchat-uid-3" }, "entityType": "user" } }, "resource": "WEB-3_0_0-b5dee412-339c-48c6-b03a-1639650765951" }, "sentAt": 1639650887, "updatedAt": 1639650887 }, {...}, {...} ] } ``` The subject of the email can be as per your requirement. Moreover, the messages array can be formatted to create the email body using a template of your choice. ### 2. Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Email Notification extension. 3. Open the Settings for this extension where you can fill in the below details. 4. Save your settings. Email replies If you wish to use the Email replies extension, you need use Integration using SendGrid. ## Integration using SendGrid We have partnered with SendGrid for sending Email Notifications and hence you need to set up an account on [SendGrid](https://www.sendgrid.com/) before you start using the extension. ### 1. Get your SendGrid API Key 1. Log in to your SendGrid account. 2. In the left navigation pane, go to Settings -> API Keys. 3. If you don't have an API Key yet, click on Create API Key. Give a name to your API Key and select Full Access to get started. ### 2. Add Email template 1. In the left navigation pane, go to Email API -> Dynamic Templates. 2. Click on "Create a Dynamic Template" and give a name to your template. 3. In the Template listing, expand your template and click on "Add Version". 4. Under the "Your Email Designs" tab, select Blank Template. 5. As we have the following HTML template ready for you, select the "Code Editor" option. 6. Paste the code for the email template. You should be able to see the Preview in the Right pane. 7. Click on Settings on the Left to expand the Settings drawer. 8. Enter the Version name and Subject for your email and hit "Save". 9. You have now successfully created a Template with a version. From the Dynamic Templates listing page, expand your Template and make note of your Template ID. 10. The data sent from the extension to SendGrid for using in the template are as follows: | Key | Value | Description | | ----------- | ------------------------ | --------------------------------------------------- | | messages | Array of message objects | The list of unread messages by the receiver. | | receiver | String | The name of the receiver of the Email notification. | | unreadCount | Int | Number of messages that are unread. | 1. Replace "[https://www.YOURSITE.com](https://www.YOURSITE.com%22)" with your website's URL in the below template. 2. The template filters and displays the TEXT messages in the email. Feel free to modify the template to include MEDIA messages as well. ```html Simple Transactional Email

While you were away...

Hello, {{receiver}}! You have {{unreadCount}} unread messages.

{{#each messages}} {{#if this.data.text}} {{/if}} {{/each}}


{{this.data.entities.sender.entity.name}}
{{this.data.text}}
Visit

To unsubscribe to these notifications, click here.

```
### 3. Add Unsubscribe Group An unsubscribe group will allow your users to unsubscribe to only chat email notifications and will allow you to continue to send other emails to that user via SendGrid. 1. In the left pane, go to Suppressions -> Unsubscribe Groups 2. Click on "Create New Group" and give it a name and proper description. 3. Save your new group and note down the Group ID. ### 4. Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the Email Notification extension. 3. Open the Settings for this extension where you can fill in the below details. 4. Save your settings. Domain Authentication The domain used in Sender's Email needs to be Authenticated. Refer to SendGrid's documentation on [Domain Authentication](https://docs.sendgrid.com/ui/account-and-settings/how-to-set-up-domain-authentication) for more details. ## Receive Email Notifications Send a message to an offline user and watch them receive an email automagically! # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/email-overview ## Introduction Email notifications are useful as a re-engagement tool, prompting users to return to the app after an extended absence. These are useful for providing updates on messages that are unread while the user was away. The email alerts or notifications are dispatched at predetermined intervals and not in real time. ## Key features 1. **Notify users at intervals**: Users who have unread messages can be notified at the specified intervals. The email includes these messages and are triggered for every such conversation. 2. **Contacts management** Once the emails are verified and vetted on your end, they can be shared with the notifications system using APIs. 3. **Preferences management**: Through CometChat's Notification Preferences, users and admins have the ability to customize the notification settings, that help provide pertinent alerts while avoiding notification fatigue. 4. **Ability to set up a schedule**: CometChat's notifications service ensures that the notifications are delivered based on the specified daily timetable, adhering to the user's local time zone. 5. **Ability to mute notifications**: Users have the option to completely mute notifications for the app (DND mode), or selectively mute them for specific users and groups, for a designated duration. 6. **Ability to set up Templates**: CometChat offers developers a set of pre-defined templates that define the content shown in notifications. These templates act as a blueprint for customizing the payload content sent with notifications as per the needs and requirements. # Flutter Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/flutter-push-notifications Learn how to implement Push notifications for the Flutter platform using FCM as well as APNs. This document guides you to set up Flutter push notifications as follows: 1. Using FCM to implement push notifications for messaging on Android and iOS. 2. Using APN to implement push notifications for messaging on iOS. Flutter Push notifications support Push Notifications are supported in Flutter for CometChat SDK v3.0.9 and above. ## FCM: Push notifications for messaging on Android and iOS For Push notifications from FCM to work on both Android and iOS, the push payload has to be of type `Notification message`. A `Notification message` is a push payload that has the notification key in it. These push notifications are handled directly by the OS and as a developer, you cannot customize these notifications. This simple setup can be used for apps that only implement messaging feature of CometChat. Learn more about [FCM messages](https://firebase.google.com/docs/cloud-messaging/concept-options). Flutter Push notifications sample app Implementation using FCM for Android and iOS. View on Github ### Step 1: Install packages Add the following to your pubspec.yaml file under dependencies. ```yaml firebase_core: ^2.8.0 firebase_messaging: ^14.3.0 ``` Install the packages. ```sh flutter pub get ``` ### Step 2: Configure with flutterfire\_cli Use the following command to install `flutterfire_cli` ```sh dart pub global activate flutterfire_cli ``` ```sh flutterfire configure --project= ``` This will ask you for the platforms. Select `android` and `ios`. The CLI tool will add the following files to your directory structure: 1. `google-services.json` to the android folder. 2. `GoogleService-Info.plist` to the ios folder. 3. `firebase_options.dart` to the `lib` folder. In the build.gradle file, change: ```gradle // Change this: classpath 'com.google.gms:google-services:4.3.10' // to classpath 'com.google.gms:google-services:4.3.14' ``` In your Firebase Console, go to project settings and upload the .p8 file obtained from the Apple Developer dashboard along with the Key ID and Team ID. ### Step 3: FCM setup in app This requires you to first set up a global context. It will help you in opening your app once your notification is tapped. Using this global context, you can write a function to navigate to the screen of choice once the notification is tapped. ```dart import 'package:flutter/material.dart'; import 'package:flutter_pn/screens/chat_screen.dart'; class NavigationService { static final GlobalKey navigatorKey = GlobalKey(); static void navigateToChat(String text) { navigatorKey.currentState?.push( MaterialPageRoute(builder: (context) => ChatScreen(chatId: text)), ); } } ``` Once the user has logged in to CometChat, do the following to setup firebase: 1. Write a top-level function that is outside of any call. This function will handle the notifications when the app is not in the foreground. 2. Initialize firebase with the FirebaseOptions from the previous step. 3. Get an instance of firebase messaging 4. Request permissions 5. Set up listeners once the permission is granted: 1. Background notification listener 2. Refreshed token listener that records the FCM token with the extension. 3. Notification tap listeners for background and terminated states of the app. 6. Make a call to save the FCM token with the extension. ### Step 4: Setup for iOS 1. Open the project in XCode (`ios/Runner.xcworkspace` ) 2. Add **Push notifications** capability. 3. Add **Background execution** capability with **Background fetch** & **Remote notification** enabled. 4. Inside the `ios` folder, execute `pod install` . Fore more details refer to the [Firebase documentation](https://firebase.google.com/docs/cloud-messaging/flutter/client#ios). ### Step 5: Run your application Running the app in profile mode for iOS enables you to see the working once the app is terminated. ``` flutter run ``` ``` flutter run --profile ``` ### Step 6: Extension setup (FCM) 1. Login to CometChat dashboard. 2. Go to the extensions section. 3. Enable the Push notifications extension. 4. Click on the settings icon to open the settings. 5. Upload the service account file that is available on the Firebase Console. 6. Make sure that you are including the `notification` key in the payload. Otherwise, this won't work. 7. Push payload message options The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. ## APN: Push notifications for messaging on iOS Apple Push Notifications service or APNs is only available for Apple devices. This will not work on Android devices. This setup ensures that the Push notifications for CometChat messages is sent using APNs `device token`. Flutter Push notifications sample app Implementation using APNs for iOS. View on Github ### Step 1: Install dependencies Add the following to your pubspec.yaml file under dependencies. ```yaml flutter_apns_only: 1.6.0 ``` ### Step 2: Add capabilities 1. Open the project in XCode (`ios/Runner.xcworkspace` ) 2. Add **Push notifications** capability. 3. Add **Background modes** capability with: 1. Remote notifications ### Step 3: Update AppDelegate.swift Add the below to your AppDeletegate.swift file. ```swift if #available(iOS 11.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } ``` ### Step 4: APN setup in app Setup a global context to be able to open your app to a specific screen if the notification is tapped. Using the global context, write a function to navigate to the screen of your choice: ```dart import 'package:flutter/material.dart'; import 'package:flutter_pn/screens/chat_screen.dart'; class NavigationService { static final GlobalKey navigatorKey = GlobalKey(); static void navigateToChat(String text) { navigatorKey.currentState?.push( MaterialPageRoute(builder: (context) => ChatScreen(chatId: text)), ); } } ``` Once the CometChat has been initialized and the user has logged in, do the required setup for the above packages that handle APNs and VoIP notifications. ### Step 5: Run on a device Run your app on a real device as Push notifications don't work on emulators. Use the profile mode to see the behavior when the app is in the background or terminated states. ``` flutter run --profile ``` ### Step 6: Extension setup (APN) 1. Login to CometChat dashboard. 2. Go to the extensions section. 3. Enable the Push notifications extension. 4. Click on the settings icon to open the settings. 5. Save the Team ID, Key ID, Bundle ID and upload the p8 certificate obtained from Apple Developer console. 6. Push payload message options The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 7. Save the settings. # iOS APNs Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/ios-apns-push-notifications Apple Push Notification service or APNs is used to send notifications to iOS devices. With this, you can also use Apple's CallKit for showing the call screen. iOS Push notifications sample app View on Github ## Get APNS Credentials The following steps in this section are written on the assumption that you already have an app ID assigned to your client app. ### Step 1: Create a Certificate Signing Request To obtain a signing certificate required to sign apps for installation on iOS devices, you should first create a certificate signing request (CSR) file through Keychain Access on your Mac. 1. Open the Keychain Access from the utility folder, go to Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority, and then click. 2. The Certificate Information dialog box appears. Enter the email address that you use in your Apple Developer account, and enter a common name for your private key. Don't enter CA email address, choose Saved to disk, and then click the Continue button. 3. Specify the name of your CSR to save and choose the location to save the file on your local disk. Then your CSR file is created, which contains a public/private key pair. ### Step 2: Create an SSL certificate 1. Sign in to your account at the [Apple Developer Member Center](https://developer.apple.com/membercenter). 2. Go to Certificates, Identifiers & Profiles. 3. Create new Certificate by clicking on the + icon. 4. Under Services, select - Apple Push Notification services SSL (Sandbox & Production) 5. Select your App ID from the dropdown. 6. Upload CSR file., upload the CSR file you created through the **Choose File** button. To complete the process, choose Continue. When the certificate is ready, choose Download to save it to your Mac. ### Step 3: Export and update .p8 certificate 1. To generate a .p8 key file, go to [Apple developer account page](https://developer.apple.com/account/), then select Certificates, IDs & Profiles. 2. Select Keys and click on the "+" button to add a new key. 3. In the new key page, type in your key name and check the Apple Push Notification service (APNs) box, then click "Continue" and click "Register". 4. Then proceed to download the key file by clicking Download. 5. Make note of the `Key ID`, `Team ID` and your `Bundle ID` for saving in the Extension's settings. **If you wish to use the .p12 certificate instead, do the following:** 1. Type a name for the .p12 file and save it to your Mac. 2. Browse to the location where you saved your key, select it, and click Open. Add the key ID for the key (available in Certificates, Identifiers & Profiles in the Apple Developer Member Center) and export it. 3. DO NOT provide an export password when prompted. 4. The .p12 file will be required in the next step for uploading in the CometChat Dashboard. ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for this extension and save the following. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** 1. The extension version has to be set to 'V2' or 'V1 & V2' in order to use APNs as the provider. 2. **Select Platforms** 1. You can select the platforms on which you wish to receive Push Notifications. 3. **APNs Settings** 1. You can turn off the Production mode when you create a development build of your application. 2. Upload the .p8 or .p12 certificate exported in the previous step. 4. **Push payload message options** The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** 1. Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications 2. These are pretty self-explanatory and you can toggle them as per your requirement. ## iOS App Setup ### Initial Setup 1. Call `CometChat.init()` method to initialize CometChat in your application. This needs to be called only once. 2. The user has to be logged in using `CometChat.login()` method. On the success callback, register the token with the extension. Two tokens need to be registered, out of which one is APNs token and other is CallKit token: a. `CometChat.registerTokenForPushNotification(token: apnsToken, settings: ["voip":false])`\ b. `CometChat.registerTokenForPushNotification(token: voipToken, settings: ["voip":true])` ```swift let authKey = "XXXX XXXX XXXXX" CometChat.login(UID: UID, authKey: authKey, onSuccess: { (current_user) in DispatchQueue.main.async { if let apnsToken = UserDefaults.standard.value(forKey: "apnsToken") as? String { print("APNS token is: \(apnsToken)") CometChat.registerTokenForPushNotification(token: apnsToken, settings: ["voip":false]) { (success) in print("onSuccess to registerTokenForPushNotification: \(success)") DispatchQueue.main.async {self.activityIndicator.stopAnimating() print("login success with : \(current_user.stringValue())") self.performSegue(withIdentifier: "presentPushNotification", sender: nil) } } onError: { (error) in print("error to registerTokenForPushNotification") } } if let voipToken = UserDefaults.standard.value(forKey: "voipToken") as? String { print("VOIP token is: \(voipToken)") CometChat.registerTokenForPushNotification(token: voipToken, settings: ["voip":true]) { (success) in print("onSuccess to registerTokenForPushNotification: \(success)") DispatchQueue.main.async {self.activityIndicator.stopAnimating() print("login success with : \(current_user.stringValue())") self.performSegue(withIdentifier: "presentPushNotification", sender: nil) } } onError: { (error) in print("error to registerTokenForPushNotification") } } } } }) { (error) in print("error while login", error); } } ``` 3. Import PushKit and CallKit in AppDelegate.Swift file. ```swift import PushKit import CallKit ``` ### Receive Push Notifications 1. Registering for the APNs notifications ```swift var window: UIWindow? var uuid: UUID? var activeCall: Call? var cancelCall: Bool = true var onCall = true var callController = CXCallController() let voipRegistry = PKPushRegistry(queue: DispatchQueue.main) var provider: CXProvider? = nil func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { self.voipRegistration() // [START register_for_notifications] if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() // [END register_for_notifications] return true } // Register for VoIP notifications func voipRegistration() { // Create a push registry object let mainQueue = DispatchQueue.main let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue) voipRegistry.delegate = self voipRegistry.desiredPushTypes = [PKPushType.voIP] } ``` 2. Add AppDelegate extension for receiving Push Notifications ```swift extension AppDelegate : UNUserNotificationCenterDelegate { // Receive displayed notifications for iOS 10 devices. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { print("willPresent notification: \(notification.request.content.userInfo)") if let userInfo = notification.request.content.userInfo as? [String : Any], let messageObject = userInfo["message"], let str = messageObject as? String, let dict = str.stringTodictionary() { if let baseMessage = CometChat.processMessage(dict).0 { switch baseMessage.messageCategory { case .message: if let message = baseMessage as? BaseMessage { switch message.messageType { case .text: print("text Messagge is: \((message as? TextMessage)?.stringValue())") case .image: print("image Messagge is: \((message as? MediaMessage)?.stringValue())") case .video: print("video Messagge is: \((message as? MediaMessage)?.stringValue())") case .audio: print("audio Messagge is: \((message as? MediaMessage)?.stringValue())") case .file: print("file Messagge is: \((message as? MediaMessage)?.stringValue())") case .custom: print("custom Messagge is: \((message as? MediaMessage)?.stringValue())") case .groupMember: break @unknown default: break } } case .action: break case .call: if let call = baseMessage as? Call { print("call is: \(call.stringValue())") } case .custom: if let customMessage = baseMessage as? CustomMessage { print("customMessage is: \(customMessage.stringValue())") } @unknown default: break } } } completionHandler([.alert, .badge, .sound]) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let notification = response.notification.request.content.userInfo print("notification is 11: \(notification)") completionHandler() } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)}) print("Device Token : ",token) let hexString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() print("Device Token 11: ",hexString) UserDefaults.standard.set(hexString, forKey: "apnsToken") CometChat.registerTokenForPushNotification(token: hexString, settings: ["voip":false]) { (success) in print("registerTokenForPushNotification voip: \(success)") } onError: { (error) in print("registerTokenForPushNotification error: \(error)") } } } ``` 3. Add AppDelegate extension for VOIP notifications. Launch CallKit screen when the VOIP notification is received. Once the CallKit screen is displayed, you can Accept or Reject the CometChat call accordingly. ```swift // MARK: CallKit & PushKit extension AppDelegate: PKPushRegistryDelegate , CXProviderDelegate { func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { let deviceToken = pushCredentials.token.reduce("", {$0 + String(format: "%02X", $1) }) print("voip token is: \(deviceToken)") UserDefaults.standard.set(deviceToken, forKey: "voipToken") CometChat.registerTokenForPushNotification(token: deviceToken, settings: ["voip":true]) { (success) in print("registerTokenForPushNotification voip: \(success)") } onError: { (error) in print("registerTokenForPushNotification error: \(error)") } } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { if let userInfo = payload.dictionaryPayload as? [String : Any], let messageObject = userInfo["message"], let dict = messageObject as? [String : Any] { if let baseMessage = CometChat.processMessage(dict).0 { switch baseMessage.messageCategory { case .message: break case .action: break case .call: if let call = baseMessage as? Call { switch call.callStatus { case .initiated: self.activeCall = call self.uuid = UUID() if let name = (call.sender)?.name { let config = CXProviderConfiguration(localizedName: "APNS + Callkit") config.iconTemplateImageData = #imageLiteral(resourceName: "your_app_icon").pngData() config.includesCallsInRecents = false config.ringtoneSound = "ringtone.caf" config.supportsVideo = true provider = CXProvider(configuration: config) provider?.setDelegate(self, queue: nil) let update = CXCallUpdate() update.remoteHandle = CXHandle(type: .generic, value: name.capitalized) if call.callType == .video { update.hasVideo = true }else{ update.hasVideo = false } provider?.reportNewIncomingCall(with: self.uuid!, update: update, completion: { error in if error == nil { self.configureAudioSession() } }) } case .ongoing, .unanswered, .rejected, .busy, .cancelled: if self.activeCall != nil { if self.cancelCall { self.end(uuid: self.uuid!) } } case .ended: break @unknown default: break } } case .custom: break @unknown default: break } } } } internal func configureAudioSession() { do { try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, options: [.mixWithOthers, .allowBluetooth, .defaultToSpeaker]) try AVAudioSession.sharedInstance().setActive(true) } catch let error as NSError { print(error) } } func providerDidReset(_ provider: CXProvider) { if let uuid = self.uuid { onCall = true provider.reportCall(with: uuid, endedAt: Date(), reason: .unanswered) } } func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { if let activeCall = activeCall { startCall() } action.fulfill() } func provider(_ provider: CXProvider, perform action: CXEndCallAction) { NotificationCenter.default.post(name: NSNotification.Name(rawValue: "didRejectButtonPressed"), object: nil, userInfo: nil) end(uuid: self.uuid!) onCall = true if let activeCall = activeCall { CometChat.rejectCall(sessionID: activeCall.sessionID ?? "", status: .rejected, onSuccess: {(rejectedCall) in DispatchQueue.main.async { CometChatSnackBoard.display(message: "CALL_REJECTED".localized(), mode: .info, duration: .short) } }) { (error) in DispatchQueue.main.async { if let errorMessage = error?.errorDescription { CometChatSnackBoard.display(message: "CALL_REJECTED".localized(), mode: .info, duration: .short) } } } provider.reportCall(with: self.uuid!, endedAt: Date(), reason: .remoteEnded) } action.fail() } func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { print(#function) } func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) { action.fulfill() print(#function) } func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) { print(#function) } func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) { print(#function) } func end(uuid: UUID) { print("endUUID",uuid) let endCallAction = CXEndCallAction(call: uuid) let transaction = CXTransaction() transaction.addAction(endCallAction) requestTransaction(transaction, action: "") } func setHeld(uuid: UUID, onHold: Bool) { print("setHeld",uuid) let setHeldCallAction = CXSetHeldCallAction(call: uuid, onHold: onHold) let transaction = CXTransaction() transaction.addAction(setHeldCallAction) requestTransaction(transaction, action: "") } internal func requestTransaction(_ transaction: CXTransaction, action: String = "") { callController.request(transaction) { error in if let error = error { print("Error requesting transaction: \(error)") } else { print("Requested transaction successfully") } } } public func startCall(){ let activeCall = CometChatCall() cancelCall = false activeCall.modalPresentationStyle = .fullScreen if let window = UIApplication.shared.windows.first , let rootViewController = window.rootViewController { var currentController = rootViewController while let presentedController = currentController.presentedViewController { currentController = presentedController } currentController.present(activeCall, animated: true, completion: nil) } } } ``` ## Miscellaneous ### Create view controller for Calls Create a viewController which will start the call when the user starts the call. ```swift import UIKit import CometChatPro import CallKit class CometChatCall: UIViewController { override func viewDidLoad() { super.viewDidLoad() if let appDelegate = UIApplication.shared.delegate as? AppDelegate { if let call = appDelegate.activeCall { if (call.callInitiator as? User)?.uid != CometChat.getLoggedInUser()?.uid { CometChat.acceptCall(sessionID: call.sessionID ?? "") { acceptedCall in DispatchQueue.main.async { let callSettings = CallSettings.CallSettingsBuilder(callView: self.view, sessionId: acceptedCall?.sessionID ?? "").setMode(mode: .MODE_SINGLE).build() CometChat.startCall(callSettings: callSettings) { userJoined in appDelegate.onCall = true } onUserLeft: { onUserLeft in } onUserListUpdated: { onUserListUpdated in } onAudioModesUpdated: { onAudioModesUpdated in } onUserMuted: { onUserMuted in } onCallSwitchedToVideo: { onCallSwitchedToVideo in } onRecordingStarted: { onRecordingStarted in } onRecordingStopped: { onRecordingStopped in } onError: { error in DispatchQueue.main.async { self.dismiss(animated: true, completion: nil) } } onCallEnded: { ended in DispatchQueue.main.async { var str = "" if let uuuid = appDelegate.uuid { print("CometChatCalls", uuuid) } self.dismiss(animated: true, completion: nil) self.dismiss(animated: true) } } } } onError: { error in } }else{ let callSettings = CallSettings.CallSettingsBuilder(callView: self.view, sessionId: call.sessionID ?? "").setMode(mode: .MODE_SINGLE).build() CometChat.startCall(callSettings: callSettings) { userJoined in } onUserLeft: { onUserLeft in } onUserListUpdated: { onUserListUpdated in } onAudioModesUpdated: { onAudioModesUpdated in } onUserMuted: { onUserMuted in } onCallSwitchedToVideo: { onCallSwitchedToVideo in } onRecordingStarted: { onRecordingStarted in } onRecordingStopped: { onRecordingStopped in } onError: { error in DispatchQueue.main.async { self.dismiss(animated: true, completion: nil) } } onCallEnded: { ended in DispatchQueue.main.async { self.dismiss(animated: true, completion: nil) } } } } } } } ``` ### Convert Push Notification payload to Message object CometChat SDK provides a method `CometChat.CometChatHelper.processMessage()` which will take the JSON received in The push notification as input, and return the corresponding `TextMessage`, `MediaMessage`,`CustomMessage` or `Call` object in return. Once the message object is received, you can use the entity as per your requirements. This code needs to be added to the `willPresent notification` method of the `UNUserNotificationCenterDelegate` delegate. ```swift func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { if let userInfo = notification.request.content.userInfo as? [String : Any], let messageObject = userInfo["message"], let str = messageObject as? String, let dict = str.stringTodictionary() { if let baseMessage = CometChat.processMessage(dict).0 { switch baseMessage.messageCategory { case .message: if let message = baseMessage as? BaseMessage { switch message.messageType { case .text: print("text Messagge is: \((message as?TextMessage)?.stringValue())") case .image: print("image Messagge is: \((message as? MediaMessage)?.stringValue())") case .video: print("video Messagge is: \((message as? MediaMessage)?.stringValue())") case .audio: print("audio Messagge is: \((message as? MediaMessage)?.stringValue())") case .file: print("file Messagge is: \((message as? MediaMessage)?.stringValue())") case .custom: print("custom Messagge is: \((message as? MediaMessage)?.stringValue())") case .groupMember: break @unknown default:break} } case .action: break case .call: if let call = baseMessage as? Call { print("call is: \(call.stringValue())") } case .custom: if let customMessage = baseMessage as? CustomMessage { print("customMessage is: \(customMessage.stringValue())") } @unknown default: break } } } completionHandler([.alert, .badge, .sound]) } extension String { func stringTodictionary() -> [String:Any]? { var dictonary:[String:Any]? if let data = self.data(using: .utf8) { do { dictonary = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] if let myDictionary = dictonary { return myDictionary; } } catch let error as NSError { print(error) } } return dictonary; } } ``` # iOS FCM Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/ios-fcm-push-notifications Learn how to send out Push Notifications to your iOS using Firebase Cloud Messaging or FCM. Don't want to use FCM? You can refer to [our setup](/notifications/ios-apns-push-notifications) using the Apple Push Notifications service (APNs). iOS Push notifications sample app View on Github ## Firebase Project Setup Visit [Firebase Console](https://console.firebase.google.com/) and login/signup using your Gmail ID. ### Step 1: Create a new Firebase Project On your Firebase Console, create a new project. This is a simple 3 step process where: 1. You give a name to your project 2. Add Google Analytics to your project (Optional) 3. Configure Google Analytics account (Optional) Click on Create and you are ready to go. ### Step 2: Add Firebase to your iOS App 1. Click on the iOS icon as shown on the screen below. 2. Register your Android app by providing the following details: a. iOS bundle name b. App nickname (optional) c. App Store ID (optional) 3. Download the GoogleService-Info.plist file and place it in the mentioned location of your project. Move your config file into the root of your Xcode project. If prompted, select to add the config file to all targets as follows. 4. We will Add Firebase SDK and Initialisation code later. So, click on 'Next', 'Next', and 'Continue to the Console'. ### Step 3: Download the service account file ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for this extension and save the following settings. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** * If you are setting it for the first time, Select `V2` to start using the token-based version of the Push Notification extension. * If you already have an app using `V1` and want to migrate your app to use `V2`, then Select `V1 & V2` option. This ensures that the users viewing the older version of your app also receive Push Notifications. * Eventually, when all your users are on the latest version of your app, you can change this option to `V2`, thus turning off `V1` (Topic-based) Push Notifications completely. 2. **Select the platforms that you want to support** * Select from Web, Android, Ionic, React Native, Flutter & iOS. 3. **Notification payload settings** * You can control if the notification key should be in the Payload or not. Learn more about the FCM Messages [here](https://firebase.google.com/docs/cloud-messaging/concept-options). 4. **Push payload message options** The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** * Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications * These are pretty self-explanatory and you can toggle them as per your requirement. ## Get APNS Credentials The following steps in this section are written on the assumption that you already have an app ID assigned to your client app. ### Step 1: Create a Certificate Signing Request To obtain a signing certificate required to sign apps for installation on iOS devices, you should first create a certificate signing request (CSR) file through Keychain Access on your Mac. 1. Open the Keychain Access from the utility folder, go to Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority, and then click. 2. The Certificate Information dialog box appears. Enter the email address that you use in your Apple Developer account, and enter a common name for your private key. Don't enter CA email address, choose Saved to disk, and then click the Continue button. 3. Specify the name of your CSR to save and choose the location to save the file on your local disk. Then your CSR file is created, which contains a public/private key pair. ### Step 2: Create an SSL certificate 1. Sign in to your account at the [Apple Developer Member Center](https://developer.apple.com/membercenter). 2. Go to Certificates, Identifiers & Profiles. In the Identifiers > App IDs and select the Push Notifications service under Application Services 3. Click the Edit button. 4. Under the Push Notifications service, choose which SSL certificate to create either Development or Production. 5. In the Generate your certificate pane that appears after the selection, under Upload CSR file., upload the CSR file you created through the Choose File... button. To complete the process, choose Continue. When the certificate is ready, choose Download to save it to your Mac. 6. In order to install the downloaded certificate to the KeyChain Access on your Mac, double-click it. You can find the certificate in the KeyChain Access > login > Certificates. ### Step 3: Export and update .p12 file to Firebase 1. Type a name for the .p12 file and save it to your Mac. 2. Browse to the location where you saved your key, select it, and click Open. Add the key ID for the key (available in Certificates, Identifiers & Profiles in the Apple Developer Member Center) and export it. ### Step 4: Upload your APNs Certificates 1. Go to Firebase console and open your project. 2. Inside your iOS project in the Firebase console, select settings and then select the `Cloud Messaging` tab. 3. Scroll down to iOS app configuration, click the Upload button for APNS certificate. 4. Browse to the location where you saved your APNs Certificates, select it, and click Open. ## iOS App Setup ### Step 1: Initial Firebase Cloud Messaging client setup 1. Add the Firebase SDK, Add the firebase pods that you want to install. You can include a Pod in your Podfile like this: ```swift pod 'Firebase_Core' pod 'Firebase_Messaging' ``` 2. Import the Firebase module in your `ApplicationDelegate:` ```swift import Firebase ``` ```objc @import Firebase; ``` 3. Configure a FirebaseApp shared instance, typically in your application's `application:didFinishLaunchingWithOptions: method:` ```swift FirebaseApp.configure() ``` ```objc [FIRApp configure]; ``` ### Step 2: Register the FCM Token 1. Get the FCM Token for remote notifications, typically in your application's `application:didFinishLaunchingWithOptions: method:` ```swift Messaging.messaging().delegate = self if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { _, _ in }) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() ``` ```objc [FIRMessaging messaging].delegate = self; if ([UNUserNotificationCenter class] != nil) { [UNUserNotificationCenter currentNotificationCenter].delegate = self; UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions: authOptions completionHandler: ^ (BOOL granted, NSError * _Nullable error) { // ... } ]; } else { UIUserNotificationType allNotificationTypes = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes: allNotificationTypes categories: nil]; [application registerUserNotificationSettings: settings]; } [application registerForRemoteNotifications]; ``` ```swift func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("Unable to register for remote notifications: \\(error.localizedDescription)") } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { print("APNs token retrieved: \\(deviceToken)") Messaging.messaging().apnsToken = deviceToken } ``` ```objc -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"Unable to register for remote notifications: %@", error); } -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSLog(@"APNs device token retrieved: %@", deviceToken); [FIRMessaging messaging].APNSToken = deviceToken; } ``` 2. Register the FCM token with our Push Notifications extension on success of CometChat.login ```swift let authKey = "XXXX XXXX XXXXX" CometChat.login(UID: UID, authKey: authKey, onSuccess: { (user) in DispatchQueue.main.async { if let token = UserDefaults.standard.value(forKey: "fcmToken") as? String { CometChat.registerTokenForPushNotification(token: token, onSuccess: { (success) in print("onSuccess to registerTokenForPushNotification: \\(success)") }) { (error) in print("error to registerTokenForPushNotification") } } ``` 3. This also needs to be done when you refresh your FCM Token ```swift extension AppDelegate : MessagingDelegate { // [START refresh_token] func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { print("Firebase registration token: \\(fcmToken)") UserDefaults.standard.set(fcmToken, forKey: "fcmToken") CometChat.registerTokenForPushNotification(token: fcmToken, onSuccess: { (sucess) in print("token registered \\(sucess)") }) { (error) in print("token registered error \\(String(describing: error?.errorDescription))") } let dataDict:[String: String] = ["token": fcmToken] NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict) } } ``` ### Step 3: Start receiving Push Notifications 1. Receive remote notification, typically in your application's `App Delegate:` ```swift func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { // Print full message. print(userInfo) } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping(UIBackgroundFetchResult) -> Void) { // Print full message. print(userInfo) completionHandler(UIBackgroundFetchResult.newData) } ``` ```objc - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // Print full message. NSLog(@"%@", userInfo); } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // Print full message. NSLog(@"%@", userInfo); completionHandler(UIBackgroundFetchResultNewData); } ``` 2. Receive Notification for `CustomMessage`: To receive and display notifications for `CustomMessage`, the developer needs to set `metadata` while sending the `CustomMessage` value as follows: ```swift var receiverID = "cometchat-uid-1"; var message = [ "someRandomKey": "someRandomData" ]; var customMessage = CustomMessage(receiverUid: receiverID, receiverType: ReceiverTypeUser, customData: message); // to display custom notification banner add this , "pushNotification" key is not to modify, although you can modify banner text as shown beow // var customNotificationDisplayText = [ "pushNotification": "notification_banner_text_here"; ]; // set it as metadata of `Custom message` customMessage.metaData = customNotificationDisplayText; CometChat.sendCustomMessage(withMessage: customMessage, onSuccess: { sentMessage in print("sentMessage \\(sentMessage.stringValue)"); }, onError: { error in if let error = error?.errorDescription() { print("error sending custom message \\(error)"); } }); ``` ```objc NSString * receiverID = @ "cometchat-uid-1"; NSDictionary * message = [NSDictionary dictionaryWithObjectsAndKeys: @ "someRandomData", @ "someRandomKey", nil]; CustomMessage * customMessage = [ [CustomMessage alloc] initWithReceiverUid: receiverID receiverType: ReceiverTypeUser customData: message ]; // to display custom notification banner add this // NSDictionary * customNotificationDisplayText = [NSDictionary dictionaryWithObjectsAndKeys: @ "notification_banner_text_here", @ "pushNotification", nil]; [customMessage setMetaData: customNotificationDisplayText]; [CometChat sendCustomMessageWithMessage: customMessage onSuccess: ^ (CustomMessage * _Nonnull sentMessage) { NSLog(@ "sentMessage %@", [sentMessage stringValue]); } onError: ^ (CometChatException * _Nullable error) { NSLog(@ "error sending custom message %@", [error errorDescription]); } ]; ``` Push Notification Payload sample for text and media messages- ```json { "alert": "Nancy Grace: Text Message", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "text": "Text Message" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "142", "sentAt": 1555668711, "category": "message", "type": "text" } } ``` ```json { "alert": "Nancy Grace: has sent an image", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "attachments": [ { "extension": "png", "size": 14327, "name": "extension_leftpanel.png", "mimeType": "image/png", "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" } ], "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "145", "sentAt": 1555671238, "category": "message", "type": "image" } } ``` ## Advanced ### Convert Push Notification payload to Message object CometChat SDK provides a method `CometChat.CometChatHelper.processMessage()` which will take the JSON received in The push notification as input, and return the corresponding `TextMessage`, `MediaMessage`,`CustomMessage` or `Call` object in return. Once the message object is received, you can use the entity as per your requirements. This code needs to be added to the `willPresent notification` method of the `UNUserNotificationCenterDelegate` delegate. ```swift func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { if let userInfo = notification.request.content.userInfo as? [String : Any], let messageObject = userInfo["message"], let str = messageObject as? String, let dict = str.stringTodictionary() { if let baseMessage = CometChat.processMessage(dict).0 { switch baseMessage.messageCategory { case .message: if let message = baseMessage as? BaseMessage { switch message.messageType { case .text: print("text Messagge is: \\((message as?TextMessage)?.stringValue())") case .image: print("image Messagge is: \\((message as? MediaMessage)?.stringValue())") case .video: print("video Messagge is: \\((message as? MediaMessage)?.stringValue())") case .audio: print("audio Messagge is: \\((message as? MediaMessage)?.stringValue())") case .file: print("file Messagge is: \\((message as? MediaMessage)?.stringValue())") case .custom: print("custom Messagge is: \\((message as? MediaMessage)?.stringValue())") case .groupMember: break @unknown default:break} } case .action: break case .call: if let call = baseMessage as? Call { print("call is: \\(call.stringValue())") } case .custom: if let customMessage = baseMessage as? CustomMessage { print("customMessage is: \\(customMessage.stringValue())") } @unknown default: break } } } completionHandler([.alert, .badge, .sound]) } extension String { func stringTodictionary() -> [String:Any]? { var dictonary:[String:Any]? if let data = self.data(using: .utf8) { do { dictonary = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] if let myDictionary = dictonary { return myDictionary; } } catch let error as NSError { print(error) } } return dictonary; } } ``` ### Miscellaneous 1. [Increment App Icon Badge Count](/sdk/ios/increment-app-icon-badge-count) 2. [Launch chat window on tap of push notification](/sdk/ios/launch-chat-window-on-tap-of-push-notification) # Legacy Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/legacy-push-notifications Migrate to Token-based Push Notifications You can check out our new Token-based implementation [here](/notifications/push-notification-extension-overview). The Push Notification extension allows you to send push notifications to mobile apps and desktop browsers. Push notifications will work in all desktop browsers which support [Push API](https://caniuse.com/#feat=push-api). These include: 1. Chrome 50+ 2. Firefox 44+ 3. Edge 17+ 4. Opera 42+ ## Step 1: Add Firebase to your app To configure Firebase Push Notifications for your apps create a `Firebase` project at [Firebase Console](https://console.firebase.google.com/). If you have previously not created a Firebase project for your app Click Add project. If you already have created a project for your app in which you wish to integrate CometChat, select the same project and download the config file. ## Step 2 : Obtain Firebase configuration for your platform ### For Web 1. Sign into Firebase and open your project. 2. On the Overview page, click Add app. 3. Select Add Firebase to your web app. 4. Copy the snippet and add it to your HTML application. ### For Android 1. Sign into Firebase and open your project. 2. On the Overview page, click Add app. 3. Select Add Firebase to your Android app. 4. Follow the on-screen instructions and finally download the google-services.json file. ### For iOS 1. Sign into Firebase and open your project. 2. On the Overview page, click Add app. 3. Select Add Firebase to your iOS app. 4. Enter the relevant details like your bundle ID and download the GoogleService-Info.plist file. 5. Move this plist file to the root of your XCode project. If prompted, select to add the config file to all targets as follows: ### For React Native 1. For React Native to Android, you need to download the `google-services.json` file. 2. For React native to iOS, you need to download the `GoogleServices-Info.plist` file. ### For Capacitor, Cordova & Ionic 1. For React Native to Android, you need to download the `google-services.json` file. 2. For React native to iOS, you need to download the `GoogleServices-Info.plist` file. 3. For web, you will need the Firebase Config object. ## Step 3: Extension setup 1. You need the Firebase Service key which you can get from Firebase console. 1. Open your Firebase app 2. Click on the Settings Cog in the left navigation menu 3. Select Project Settings and go to the Cloud Messaging tab 4. Add a Server Key and copy it for further use. 2. Login to the [CometChat Dashboard](https://app.cometchat.io/login) and select your app. 3. On the Extensions page, enable the Push Notifications extension. 4. Open the Settings for this extension. 5. Enter FCM Server key. 6. Select the platforms of choice. 7. Enter the title for notifications. 8. You can also toggle the triggers for sending Push Notifications. The triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications ## Step 4: Application Setup In order to use the topic-based Push Notifications, you need to subscribe to topics. In case of CometChat, you need to subscribe to 2 different types of topics: 1. Topic to receive Push Notifications for one-on-one messages and calls. 2. Topic to receive Push Notifications for group messages and calls. Also, you can: 1. Subscribe to one topic 2. Subscribe to all the topics Below steps guide you with this process of subscription to topics and specific setup for the platform of your choice. ### For Web #### **1. Installing Firebase SDK** ```sh npm install firebase ``` ```sh yarn add firebase ``` ```js ``` #### **2. Initialize Firebase app** 1. Create a index.html file and initialize the Firebase app. This has to be done only once. 2. Here, you will need the Firebase Configuration object that you copied from the Firebase Console. 3. Also, register the service worker. ```js const config = { apiKey: "AIzaSyBkasdasdasdybyI-ZkFCxNpJLAtYyqeERw5I60yTNs", authDomain: "testAPP.firebaseapp.com", databaseURL: "https://testAPP.firebaseio.com", projectId: "testAPP-229414", storageBucket: "testAPP.appspot.com", messagingSenderId: "app_sender_id", }; firebase.initializeApp(config); ``` ```js if ("serviceWorker" in navigator) { window.addEventListener("load", () => { navigator.serviceWorker.register("/firebase-messaging-sw.js"); }); } ``` #### **3. Request permission for Web Push** 1. Create PushNotification.js file. 2. Insert the following code so that the browser asks for permission to show Push Notifications. 3. If the permission is granted, you will receive a FCM registration token. ```js const requestPermission = async () => { const messaging = firebase.messaging(); const FCM_TOKEN = await messaging .requestPermission() .then(() => messaging.getToken()); .catch(error => console.log(error)); return FCM_TOKEN; } ``` #### **4. Subscribe to topic(s)** 1. In the success callback of CometChat.login(), you can start the subscription process. 2. As mentioned earlier, you can either subscribe to one topic or subscribe to all. 3. The format for the name of user topic is `AppID_user_UID` 4. The format for the name of a group topic is `AppID_group_GUID` ```js var appID = "APP_ID"; var token = "GENERATED_FCM_TOKEN"; var userUID = "UID_OF_LOGGED_IN_USER"; var appToken; CometChat.getJoinedGroups().then((groups) => { CometChat.getAppSettings().then((settings) => { settings.extensions.forEach((ext) => { if (ext.id == "push-notification") { appToken = ext.appToken; } }); var url = "https://push-notification-us.cometchat.io/v1/subscribetomany?appToken=" + appToken; fetch(url, { method: "POST", headers: new Headers({ "Content-Type": "application/json", }), body: JSON.stringify({ appId: appID, fcmToken: token, uid: userUID, groups: groups, platform: "javascript", }), }) .then((response) => { if (response.status < 200 || response.status >= 400) { console.log( "Error subscribing to topics: " + response.status + " - " + response.text() ); } else { console.log("Subscribed to all topics"); } }) .catch((error) => { console.error(error); }); }); }); ``` ```js var token = "generated_FCM_token"; CometChat.getAppSettings().then((settings) => { var appToken; settings.extensions.forEach((ext) => { if (ext.id == "push-notification") { appToken = ext.appToken; } }); var userType = "user"; var UID = "UID"; var appId = "APP_ID"; var region = "REGION_OF_APP"; var topic = appId + "_" + userType + "_" + UID; var url = "https://push-notification-" + region + ".cometchat.io/v1/subscribe?appToken=" + appToken + ""; fetch(url, { method: "POST", headers: new Headers({ "Content-Type": "application/json", }), body: JSON.stringify({ appId: appId, fcmToken: token, topic: topic }), }) .then((response) => { if (response.status < 200 || response.status >= 400) { console.log( "Error subscribing to topic: " + response.status + " - " + response.text() ); } console.log('Subscribed to "' + topic + '"'); }) .catch((error) => { console.error(error); }); }); ``` ```js var token = "generated_FCM_token"; CometChat.getAppSettings().then(settings => { var appToken; settings.extensions.forEach(ext => { if (ext.id == "push-notification){ appToken = ext.appToken; } }); var userType = "group"; var GUID = "GUID"; var appId = "APP_ID"; var region = "REGION_OF_APP"; var topic = appId + "_" + userType + "_" + GUID; var url = "https://push-notification-"+ region +".cometchat.io/v1/subscribe?appToken=" + appToken + ""; fetch(url, { method: "POST", headers: new Headers({ "Content-Type": "application/json" }), body: JSON.stringify({ appId: appId, fcmToken: token, topic: topic }) }) .then(response => { if (response.status < 200 || response.status >= 400) { console.log( "Error subscribing to topic: " + response.status + " - " + response.text() ); } console.log('Subscribed to "' + topic + '"'); }) .catch(error => { console.error(error); }); }); ``` #### **5. Receive Messages** Create a firebase-messaging-sw\.js file which will handle showing notifications ```js importScripts("https://www.gstatic.com/firebasejs/8.3.2/firebase-app.js"); importScripts("https://www.gstatic.com/firebasejs/8.3.2/firebase-messaging.js"); const FIREBASE_CONFIG_SW = { // From Firebase apiKey: "AIzaSyBkasdasdasdybyI-ZkFCxNpJLAtYyqeERw5I60yTNs", authDomain: "testAPP.firebaseapp.com", databaseURL: "https://testAPP.firebaseio.com", projectId: "testAPP-229414", storageBucket: "testAPP.appspot.com", messagingSenderId: "app_sender_id", }; firebase.initializeApp(FIREBASE_CONFIG_SW); const firebaseMessaging = firebase.messaging(); //background firebaseMessaging.setBackgroundMessageHandler(function (payload) { console.log(" Received background message ", payload); // Customize notification here var notificationTitle = "notificationTitle"; var notificationOptions = { body: payload.data.alert, icon: "", }; return self.registration.showNotification( notificationTitle, notificationOptions ); }); // [END background_handler] self.addEventListener("notificationclick", function (event) { event.notification.close(); //handle click event onClick on Web Push Notification }); ``` #### **6. Unsubscribe from topics** Before you logout the user using CometChat.logout() method, you can unsubscribe from topics to stop receiving Push notifications for a logged out user. ```js var appID = "APP_ID"; var token = "GENERATED_FCM_TOKEN"; var appToken; CometChat.getAppSettings().then((settings) => { settings.extensions.forEach((ext) => { if (ext.id == "push-notification") { appToken = ext.appToken; } }); var url = "https://push-notification-us.cometchat.io/v1/unsubscribealltopic?appToken=" + appToken; fetch(url, { method: "DELETE", headers: new Headers({ "Content-Type": "application_json", }), body: JSON.stringify({ appId: appID, fcmToken: token }), }) .then((response) => { if (response.status < 200 || response.status >= 400) { console.log( "Error unsubscribing from topics: " + response.status + " - " + response.text() ); } else { console.log("Unsubscribed from all topics"); } }) .catch((error) => { console.error(error); }); }); ``` ```js var token = "generated_FCM_token"; CometChat.getAppSettings().then((settings) => { var appToken; settings.extensions.forEach((ext) => { if (ext.id == "push-notification") { appToken = ext.appToken; } }); var userType = "user"; var UID = "UID"; var appId = "APP_ID"; var region = "REGION_OF_APP"; var topic = appId + "_" + userType + "_" + UID; var url = "https://push-notification-" + region + ".cometchat.io/v1/unsubscribe?appToken=" + appToken; fetch(url, { method: "DELETE", headers: new Headers({ "Content-Type": "application/json", }), body: JSON.stringify({ appId: appId, fcmToken: token, topic: topic }), }) .then((response) => { if (response.status < 200 || response.status >= 400) { console.log( "Error subscribing to topic: " + response.status + " - " + response.text() ); } else { console.log('Unsubscribed from "' + topic + '"'); } }) .catch((error) => { console.error(error); }); }); ``` ```js var token = "generated_FCM_token"; CometChat.getAppSettings().then((settings) => { var appToken; settings.extensions.forEach((ext) => { if (ext.id == "push-notification") { appToken = ext.appToken; } }); var userType = "group"; var GUID = "GUID"; var appId = "APP_ID"; var region = "REGION_OF_APP"; var topic = appId + "_" + userType + "_" + GUID; var url = "https://push-notification-" + region + ".cometchat.io/v1/unsubscribe?appToken=" + appToken; fetch(url, { method: "DELETE", headers: new Headers({ "Content-Type": "application/json", }), body: JSON.stringify({ appId: appId, fcmToken: token, topic: topic }), }) .then((response) => { if (response.status < 200 || response.status >= 400) { console.log( "Error subscribing to topic: " + response.status + " - " + response.text() ); } else { console.log('Unsubscribed from "' + topic + '"'); } }) .catch((error) => { console.error(error); }); }); ``` #### **7. Handle Custom messages** To receive notification of `CustomMessage`, you need to set metadata while sending the `CustomMessage`. ```js var receiverID = "UID"; var customData = { latitude: "50.6192171633316", longitude: "-72.68182268750002", }; var customType = "location"; var receiverType = CometChat.RECEIVER_TYPE.USER; var metadata = { pushNotification: "Your Notification Message", }; var customMessage = new CometChat.CustomMessage( receiverID, receiverType, customType, customData ); customMessage.setMetadata(metadata); CometChat.sendCustomMessage(customMessage).then( (message) => { // Message sent successfully. console.log("custom message sent successfully", message); }, (error) => { console.log("custom message sending failed with error", error); // Handle exception. } ); ``` ### For Android #### **1. Setup client app** To enable Firebase products in your app, add the `google-services plugin` to your Gradle files. In your root-level (project-level) Gradle file (build.gradle), Check that you have Google's Maven repository. In your module (app-level) Gradle file (usually app/build.gradle), apply the Google Services Gradle plugin and add the dependencies for the Firebase Cloud Messaging. ```gradle buildscript { repositories { // Check that you have the following line (if not, add it): google() // Google's Maven repository } dependencies { // ... // Add the following line: classpath 'com.google.gms:google-services:4.3.3' // Google Services plugin } } allprojects { // ... repositories { // Check that you have the following line (if not, add it): google() // Google's Maven repository // ... } } ``` ```gradle apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' android { //... } dependencies { //.. implementation 'com.google.firebase:firebase-messaging:20.2.4' //.. implementation 'com.cometchat:pro-android-chat-sdk:2.1.0' } ``` #### **2. Using FirebaseMessaging Service & Broadcast Receiver** FirebaseMessagingService provides a method which helps to register token for client app by overriding onNewToken. ```java public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String TAG = "MyFirebaseService"; public static String token; //.. @Override public void onNewToken(String s) { token = s; Log.d(TAG, "onNewToken: "+s); } } ``` #### **3. Subscribe and unsubscribe to topic(s)** 1. After successful login using CometChat.login(), you can start the subscription process. 2. As mentioned earlier, you can either subscribe to one topic or subscribe to all. 3. The format for the name of user topic is `AppID_user_UID` 4. The format for the name of a group topic is `AppID_group_GUID` 5. You can unsubscribe when the user logs out (i.e. before calling the CometChat.logout() method) ```java public static void subscribeUserNotification(String UID) { FirebaseMessaging.getInstance().subscribeToTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_USER +"_" + UID); } public static void unsubscribeUserNotification(String UID) { FirebaseMessaging.getInstance().unsubscribeFromTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_USER +"_" + UID); } public static void subscribeGroupNotification(String GUID) { FirebaseMessaging.getInstance().subscribeToTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_GROUP +"_" + GUID); } public static void unsubscribeGroupNotification(String GUID) { FirebaseMessaging.getInstance().unsubscribeFromTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_GROUP +"_" + GUID); } ``` #### **4. Receive Messages** To receive messages, you need to override the `onMessageReceived (RemoteMessage remoteMessage)`. ```java package com.cometchat.pro.android.pushnotification.utils; import android.app.Notification; import android.app.PendingIntent; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.RingtoneManager; import android.util.Log; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import com.cometchat.pro.android.pushnotification.R; import com.cometchat.pro.android.pushnotification.constants.AppConfig; import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.core.Call; import com.cometchat.pro.helpers.CometChatHelper; import com.cometchat.pro.models.BaseMessage; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; import constant.StringContract; public class MyFirebaseMessagingService extends FirebaseMessagingService { private static final String TAG = "MyFirebaseService"; private JSONObject json; private Intent intent; private int count=0; private Call call; public static String token; private static final int REQUEST_CODE = 12; private boolean isCall; public static void subscribeUserNotification(String UID) { FirebaseMessaging.getInstance().subscribeToTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_USER +"_" + UID).addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void aVoid) { Log.e(TAG, UID+ " Subscribed Success"); } }); } public static void unsubscribeUserNotification(String UID) { FirebaseMessaging.getInstance().unsubscribeFromTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_USER +"_" + UID).addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void aVoid) { Log.e(TAG, UID+ " Unsubscribed Success"); } }); } public static void subscribeGroupNotification(String GUID) { FirebaseMessaging.getInstance().subscribeToTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_GROUP +"_" + GUID).addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void aVoid) { Log.e(TAG, GUID+ " Subscribed Success"); } }); } public static void unsubscribeGroupNotification(String GUID) { FirebaseMessaging.getInstance().unsubscribeFromTopic(AppConfig.AppDetails.APP_ID + "_"+ CometChatConstants.RECEIVER_TYPE_GROUP +"_" + GUID); } @Override public void onNewToken(String s) { token = s; Log.d(TAG, "onNewToken: "+s); } @Override public void onMessageReceived(RemoteMessage remoteMessage) { try { count++; json = new JSONObject(remoteMessage.getData()); Log.d(TAG, "JSONObject: "+json.toString()); JSONObject messageData = new JSONObject(json.getString("message")); BaseMessage baseMessage = CometChatHelper.processMessage(new JSONObject(remoteMessage.getData().get("message"))); if (baseMessage instanceof Call){ call = (Call)baseMessage; isCall=true; } showNotifcation(baseMessage); } catch (JSONException e) { e.printStackTrace(); } } public Bitmap getBitmapFromURL(String strURL) { if (strURL!=null) { try { URL url = new URL(strURL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); InputStream input = connection.getInputStream(); Bitmap myBitmap = BitmapFactory.decodeStream(input); return myBitmap; } catch (IOException e) { e.printStackTrace(); return null; } } else { return null; } } private void showNotifcation(BaseMessage baseMessage) { try { int m = (int) ((new Date().getTime())); String GROUP_ID = "group_id"; NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"2") .setSmallIcon(R.drawable.cc) .setContentTitle(json.getString("title")) .setContentText(json.getString("alert")) .setPriority(NotificationCompat.PRIORITY_HIGH) .setColor(getResources().getColor(R.color.colorPrimary)) .setLargeIcon(getBitmapFromURL(baseMessage.getSender().getAvatar())) .setGroup(GROUP_ID) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); NotificationCompat.Builder summaryBuilder = new NotificationCompat.Builder(this,"2") .setContentTitle("CometChat") .setContentText(count+" messages") .setSmallIcon(R.drawable.cc) .setGroup(GROUP_ID) .setGroupSummary(true); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); if (isCall){ builder.setGroup(GROUP_ID+"Call"); if (json.getString("alert").equals("Incoming audio call") || json.getString("alert").equals("Incoming video call")) { builder.setOngoing(true); builder.setPriority(NotificationCompat.PRIORITY_HIGH); builder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); builder.addAction(0, "Answers", PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, getCallIntent("Answers"), PendingIntent.FLAG_UPDATE_CURRENT)); builder.addAction(0, "Decline", PendingIntent.getBroadcast(getApplicationContext(), 1, getCallIntent("Decline"), PendingIntent.FLAG_UPDATE_CURRENT)); } notificationManager.notify(05,builder.build()); } else { notificationManager.notify(baseMessage.getId(), builder.build()); notificationManager.notify(0, summaryBuilder.build()); } } catch (Exception e) { e.printStackTrace(); } } private Intent getCallIntent(String title){ Intent callIntent = new Intent(getApplicationContext(), CallNotificationAction.class); callIntent.putExtra(StringContract.IntentStrings.SESSION_ID,call.getSessionId()); callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); callIntent.setAction(title); return callIntent; } } ``` `CallNotificationAction.java` is a Broadcast Receiver which is used to handle call events when app is in the background. Since Android O, there have been certain restrictions added for background tasks and users cannot launch intent directly from the service. More details can be found [here](https://developer.android.com/guide/components/activities/background-starts). ```java package com.cometchat.pro.android.pushnotification.utils; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; import androidx.core.app.NotificationManagerCompat; import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.core.Call; import com.cometchat.pro.core.CometChat; import com.cometchat.pro.exceptions.CometChatException; import com.cometchat.pro.models.Group; import com.cometchat.pro.models.User; import constant.StringContract; import screen.CallActivity; public class CallNotificationAction extends BroadcastReceiver { String TAG = "CallNotificationAction"; @Override public void onReceive(Context context, Intent intent) { String sessionID = intent.getStringExtra(StringContract.IntentStrings.SESSION_ID); Log.e(TAG, "onReceive: " + intent.getStringExtra(StringContract.IntentStrings.SESSION_ID)); if (intent.getAction().equals("Answers")) { CometChat.acceptCall(sessionID, new CometChat.CallbackListener() { @Override public void onSuccess(Call call) { Intent acceptIntent = new Intent(context, CometChatCallActivity.class); acceptIntent.putExtra(StringContract.IntentStrings.SESSION_ID,call.getSessionId()); acceptIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(acceptIntent); } @Override public void onError(CometChatException e) { Toast.makeText(context,"Error "+e.getMessage(),Toast.LENGTH_LONG).show(); } }); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.cancel(05); } else { CometChat.rejectCall(sessionID, CometChatConstants.CALL_STATUS_REJECTED, new CometChat.CallbackListener() { @Override public void onSuccess(Call call) { NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.cancel(05); } @Override public void onError(CometChatException e) { } }); } } } ``` You also need to add both of the above mentioned file in your `AndroidManifest.xml` to make Push notification work in Background as well. ```xml ``` **6. Notification Channel** From Android O and above you need to use NotificationChannel to show notifications. You can add the below method in your Application class and call it in *OnCreate().* This method will manage the notification channel for your app. ```java private void createNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = getString(R.string.app_name); String description = getString(R.string.channel_description); int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel channel = new NotificationChannel("2", name, importance); channel.setDescription(description); channel.enableVibration(true); channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); // Register the channel with the system; you can't change the importance // or other notification behaviors after this NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } ``` ### For iOS #### Apple Developer Portal The following steps in this section are written on the assumption that you already have an app ID assigned to your client app **1. Create a Certificate Signing Request** To obtain a signing certificate required to sign apps for installation on iOS devices, you should first create a certificate signing request (CSR) file through Keychain Access on your Mac. 1. Open the Keychain Access from the utility folder, go to Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority, and then click 2. The Certificate Information dialog box appears. Enter the email address that you use in your Apple Developer account, and enter a common name for your private key. Don't enter CA email address, choose Saved to disk, and then click the Continue button. 3. Specify the name of your CSR to save and choose the location to save the file on your local disk. Then your CSR file is created, which contains a public/private key pair. **2. Create an SSL Certificate** 1. Sign in to your account at the [Apple Developer Member Center](https://developer.apple.com/membercenter). 2. Go to Certificates, Identifiers & Profiles. In the Identifiers > App IDs and select the Push Notifications service under Application Services 3. Click the Edit button. 4. Under the Push Notifications service, choose which SSL certificate to create either Development or Production. 5. In the Generate your certificate pane that appears after the selection, under Upload CSR file., upload the CSR file you created through the Choose File... button. To complete the process, choose Continue. When the certificate is ready, choose Download to save it to your Mac. 6. In order to install the downloaded certificate to the KeyChain Access on your Mac, double-click it. You can find the certificate in the KeyChain Access > login > Certificates. **3. Export and update .p12 file to Firebase** 1. Type a name for the .p12 file and save it to your Mac. 2. Browse to the location where you saved your key, select it, and click Open. Add the key ID for the key (available in Certificates, Identifiers & Profiles in the Apple Developer Member Center) and export it. **4. Upload your APNs Certificates** 1. Go to Firebase console and open your project. 2. Inside your iOS project in the Firebase console, select settings and then select the `Cloud Messaging` tab. 3. Scroll down to iOS app configuration, click the Upload button for APNS certificate. 4. Browse to the location where you saved your APNs Certificates, select it, and click Open. #### iOS App Setup **1. FCM Client on iOS** Add the Firebase SDK, Add the firebase pods that you want to install. You can include a Pod in your Podfile like this: ```ruby pod 'Firebase/Core' pod 'Firebase/Messaging' ``` Import the Firebase module in your `AppDelegate`: ```swift import Firebase ``` ```objc @import Firebase; ``` Configure a FirebaseApp shared instance, typically in your application's `application:didFinishLaunchingWithOptions` ```swift FirebaseApp.configure() ``` ```objc [FIRApp configure]; ``` Register for remote notification, typically in your application's \`application:didFinishLaunchingWithOptions\`\`\` ```swift Messaging.messaging().delegate = self if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { _, _ in }) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() ``` ```objc [FIRMessaging messaging].delegate = self; if ([UNUserNotificationCenter class] != nil) { [UNUserNotificationCenter currentNotificationCenter].delegate = self; UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions: authOptions completionHandler: ^ (BOOL granted, NSError * _Nullable error) { // ... } ]; } else { UIUserNotificationType allNotificationTypes = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes: allNotificationTypes categories: nil]; [application registerUserNotificationSettings: settings]; } [application registerForRemoteNotifications]; ``` The FCM Registration token ```swift func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("Unable to register for remote notifications: \\(error.localizedDescription)") } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { print("APNs token retrieved: \\(deviceToken)") Messaging.messaging().apnsToken = deviceToken } ``` ```objc -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"Unable to register for remote notifications: %@", error); } -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSLog(@"APNs device token retrieved: %@", deviceToken); [FIRMessaging messaging].APNSToken = deviceToken; } ``` **2. Subscribe and Unsubscribe to topic(s)** 1. The format for the name of user topic is `AppID_user_UID_ios` 2. The format for the name of a group topic is `AppID_group_GUID_ios` ```swift let userTopic: String = appID + "_user_" + logged_in_user_UID + "_ios" Messaging.messaging().subscribe(toTopic: userTopic) { error in print("Subscribed to \\(userTopic) topic") } ``` ```objc NSString *userTopic = [NSString allow] init]; userTopic = appID + "_user_" + logged_in_user_UID + "_ios"; [[FIRMessaging messaging] subscribeToTopic:@userTopic completion:^(NSError * _Nullable error) { NSLog(@"Subscribed to userTopic topic %@",userTopic); }]; ``` ```swift let groupTopic: String = appID + "_group_" + group_guid + "_ios" Messaging.messaging().subscribe(toTopic: groupTopic) { error in print("Subscribed to \\(groupTopic) topic") } ``` ```objc NSString *groupTopic = [NSString allow] init]; groupTopic = appID + "_group_" + group_guid + "_ios"; [[FIRMessaging messaging] subscribeToTopic:@groupTopic completion:^(NSError * _Nullable error) { NSLog(@"Subscribed to userTopic topic %@",groupTopic); }]; ``` ```swift /** * log out from `CometChat` and unsubscribe from `FCM` push notifications */ CometChat.logout(onSuccess: { (success) in Messaging.messaging().unsubscribe(fromTopic: userTopic) Messaging.messaging().unsubscribe(fromTopic: groupTopic) }) {(error) in } ``` ```objc /** * log out from `CometChat` and unsubscribe from `FCM` push notifications */ [CometChat logoutOnSuccess:^(NSString * _Nonnull logoutSuccess) { [[FIRMessaging messaging] unsubscribeFromTopic:userTopic]; [[FIRMessaging messaging] unsubscribeFromTopic:groupTopic]; } onError:^(CometChatException * _Nonnull error) { NSLog(@"error in login %@",[error errorDescription]); }]; ``` **3. Receive Remote notifications** This typically happens in your application's AppDelegate ```swift func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { // Print full message. print(userInfo) } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping(UIBackgroundFetchResult) -> Void) { // Print full message. print(userInfo) completionHandler(UIBackgroundFetchResult.newData) } ``` ```objc - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // Print full message. NSLog(@"%@", userInfo); } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // Print full message. NSLog(@"%@", userInfo); completionHandler(UIBackgroundFetchResultNewData); } ``` Receive and display notifications for `CustomMessage`, you need to set the `metadata` while sending the `CustomMessage`: ```swift var receiverID = "cometchat-uid-1"; var message = [ "someRandomKey": "someRandomData" ]; var customMessage = CustomMessage(receiverUid: receiverID, receiverType: ReceiverTypeUser, customData: message); // to display custom notification banner add this , "pushNotification" key is not to modify, although you can modify banner text as shown beow // var customNotificationDisplayText = [ "pushNotification": "notification_banner_text_here"; ]; // set it as metadata of `Custom message` customMessage.metaData = customNotificationDisplayText; CometChat.sendCustomMessage(withMessage: customMessage, onSuccess: { sentMessage in print("sentMessage \\(sentMessage.stringValue)"); }, onError: { error in if let error = error?.errorDescription() { print("error sending custom message \\(error)"); } }); ``` ```objc NSString * receiverID = @ "cometchat-uid-1"; NSDictionary * message = [NSDictionary dictionaryWithObjectsAndKeys: @ "someRandomData", @ "someRandomKey", nil]; CustomMessage * customMessage = [ [CustomMessage alloc] initWithReceiverUid: receiverID receiverType: ReceiverTypeUser customData: message ]; // to display custom notification banner add this // NSDictionary * customNotificationDisplayText = [NSDictionary dictionaryWithObjectsAndKeys: @ "notification_banner_text_here", @ "pushNotification", nil]; [customMessage setMetaData: customNotificationDisplayText]; [CometChat sendCustomMessageWithMessage: customMessage onSuccess: ^ (CustomMessage * _Nonnull sentMessage) { NSLog(@ "sentMessage %@", [sentMessage stringValue]); } onError: ^ (CometChatException * _Nullable error) { NSLog(@ "error sending custom message %@", [error errorDescription]); } ]; ``` ### For React Native #### **1. Installing Firebase SDK** Install the react-native-firebase package in your project. ```sh npm install @react-native-firebase/app @react-native-firebase/messaging ``` ```sh yarn add @react-native-firebase/app @react-native-firebase/messaging ``` **2. Android Setup** To allow the Android app to securely connect to your Firebase project, a configuration file must be downloaded and added to your project. Download the `google-services.json` file and place it inside of your project at the following location: /android/app/google-services.json. **Configure Firebase in Android:** To allow Firebase on Android to use the credentials, the google-services plugin must be enabled on the project. This requires modification to two files in the Android directory. Add the google-services plugin as a dependency inside of your `/android/build.gradle`. Execute the plugin by adding the following to your `/android/app/build.gradle` file. ```gradle buildscript { dependencies { // ... other dependencies classpath 'com.google.gms:google-services:4.3.3' // Add me --- _\\ } } ``` ```gradle apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' // <- Add this line ``` #### **3. iOS Setup** To allow the iOS app to securely connect to your Firebase project, a configuration file must be downloaded and added to your project. On the Firebase console, add a new iOS application and enter your project details. The "iOS bundle ID" must match your local project bundle ID. The bundle ID can be found within the "General" tab when opening the project with Xcode. Download the GoogleService-Info.plist file. Using Xcode, open the projects /ios/\{projectName}.xcodeproj file (or /ios/\{projectName}.xcworkspace if using Pods). Right-click on the project name and "Add files" to the project, as demonstrated below: Select the downloaded `GoogleService-Info.plist` file from your computer, and ensure the "Copy items if needed" checkbox is enabled. **Configure Firebase in iOS:** To allow Firebase on iOS to use the credentials, the Firebase iOS SDK must be configured during the bootstrap phase of your application. To do this, open your /ios/\{projectName}/AppDelegate.m file, and add the following: At the top of the file, import the Firebase SDK: ```swift #import ``` Within your existing `didFinishLaunchingWithOptions` method, add the following to the top of the method: ```objc - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Add me --- \\_ if ([FIRApp defaultApp] == nil) { [FIRApp configure]; } // Add me --- _\\ // ... } ``` In the Firebase console, you have to include either APNs Authentication Key or APNs Certificate in Project Settings > Cloud Messaging in order to receive push notifications. Turn on the following two capabilities in Xcode: a. Push Notifications & b. Background Modes - Check only Remote Notifications. Lastly, Open your projects /ios/Podfile and add any of the globals shown below to the top of the file: ```ruby # Override Firebase SDK Version $FirebaseSDKVersion = '6.29.0' ``` **4. Handling Push Notifications** You can refer to the below code for handling Push Notifications in React Native. ```js import React from "react"; import { SafeAreaView, StyleSheet, View, Text, StatusBar, TouchableOpacity, Alert, Platform, } from "react-native"; import messaging from "@react-native-firebase/messaging"; import { CometChat } from "@cometchat/chat-sdk-react-native"; import { decode, encode } from "base-64"; if (!global.btoa) { global.btoa = encode; } if (!global.atob) { global.atob = decode; } var topics = []; this.DOMParser = require("xmldom").DOMParser; class App extends React.Component { async componentDidMount() { this.checkPermission(); this.createNotificationListeners(); } async checkPermission() { const authStatus = await messaging.requestPermission(); const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED || authStatus === messaging.AuthorizationStatus.PROVISIONAL; if (enabled) { await messaging.getToken(); } } createNotificationListeners() { this.messageListener = messaging.onMessage(async (remoteMessage) => { Alert.alert("A new FCM message arrived!", JSON.stringify(remoteMessage)); }); } subscribeForPushNotification() { var appSettings = new CometChat.AppSettingsBuilder() .subscribePresenceForAllUsers() .setRegion(region) .build(); CometChat.init("APP_ID", appSettings).then( () => { CometChat.login("UID", "API_KEY").then((user) => { CometChat.getJoinedGroups().then((groups) => { let isiOS = Platform.OS === "ios"; var userTopic = appId + "_user_" + user.getUid(); if (isiOS) { var userTopicIos = userTopic + "_ios"; topics.push(userTopicIos); } else { var userTopicIos = userTopic + "_notification"; topics.push(userTopic); } groups.forEach((group) => { var groupTopic = appId + "_group_" + group; if (isiOS) { var groupTopicIos = groupTopic + "_ios"; topics.push(groupTopicIos); } else { var groupTopicIos = groupTopic + "_notification"; topics.push(groupTopic); } }); topics.forEach(async (topic) => { console.log("subscribing to topic => ", topic); await messaging.subscribeToTopic(topic); }); }); }); }, (error) => { console.log("Initialization failed with error:", error); } ); } unsubscribeFromPushNotification() { topics.forEach(async (topic) => { await messaging.unsubscribeFromTopic(topic); }); } render() { return ( <> CometChat Push Notification { this.subscribeForPushNotification(); }} style={styles.linkContainer} > Subscribe for push notification { this.unsubscribeFromPushNotification(); }} style={styles.linkContainer} > Unsubscribe from push notification ); } } const styles = StyleSheet.create({ body: { backgroundColor: "#fff", justifyContent: "space-around", alignItems: "center", flex: 1, height: "100%", }, linkContainer: { justifyContent: "center", alignItems: "center", paddingVertical: 8, backgroundColor: "#ddd", borderRadius: 40, height: 40, width: "80%", }, separator: { backgroundColor: "#ddd", height: 1, width: "100%", }, }); export default App; ``` #### **5. Subscribe to and u nsubscribe from topics** Refer to the JavaScript section above for subscription and unsubscription code. ### For Capacitor, Cordova & Ionic **1. Firebase Plugins** For Cordova & Ionic, there are numerous plugins available via NPM which can be used to set up push notifications for your apps like [FCM Plugin](https://ionicframework.com/docs/v3/native/fcm/) and [Push Plugin](https://ionicframework.com/docs/native/push). To setup Push Notification, you need to follow the steps mentioned in the Plugin's Documentation. You need to make different apps on the firebase console for each platform respectively (Android, iOS). **2. Subscribe and unsubscribe process** Refer to the JavaScript section above for subscription and unsubscription code. **3. Receiving Push notifications** Here you can use the callback provided by the plugin. For eg: If you are using the [FCM Plugin](https://ionicframework.com/docs/v3/native/fcm/) you can receive the messages as follows: ```js this.fcm.onNotification().subscribe((data) => { console.log("here you receive the message", data); }); ``` This should ideally be added in the app.component.ts file and should be called in the success of the platform.ready(). For other plugins, you can refer to the documentation provided by the plugin to check how messages can be received using that plugin. Once you have started receiving messages, you can act on the received messages accordingly as per your requirements. ### Converting Push payload to message object CometChat SDK provides a method `CometChat.CometChatHelper.processMessage()` to convert the message JSON to the corresponding object of `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call`. This code needs to be added to the `onMessageReceived()` method of the `FirebaseMessagingService` class. ```js let processedMessage = CometChat.CometChatHelper.processMessage(JSON_MESSAGE); ``` ```java CometChatHelper.processMessage(new JSONObject(remoteMessage.getData().get("message")); ``` ```swift func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { if let userInfo = (notification.request.content.userInfo as? [String : Any]){ let messageObject = userInfo["message"] if let someString = messageObject as? String { if let dict = someString.stringTodictionary(){ print("BaseMessage Object: \\(CometChat.processMessage(dict))") } } } } extension String { func stringTodictionary() -> [String:Any]? { var dictonary:[String:Any]? if let data = self.data(using: .utf8) { do { dictonary = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] if let myDictionary = dictonary { return myDictionary; } } catch let error as NSError { print(error) } } return dictonary; } } ``` ```js let processedMessage = CometChat.CometChatHelper.processMessage(JSON_MESSAGE); ``` ```js let processedMessage = CometChat.CometChatHelper.processMessage(JSON_MESSAGE); ``` Attachments can be of the following types: `CometChatConstants.MESSAGE_TYPE_IMAGE`\ `CometChatConstants.MESSAGE_TYPE_VIDEO`\ `CometChatConstants.MESSAGE_TYPE_AUDIO`\ `CometChatConstants.MESSAGE_TYPE_FILE` # Notification Logs Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/logs ## Summary Notification logs enable you to track Push, Email, and SMS notifications triggered for CometChat events. Notification logs provide insights into why a notification was not triggered for a specific event (maybe due to preferences). Additionally, responses from providers are logged to analyze success and failure patterns from the provider's end. ## Logs availability When enabled, logging remains active for 7 days and automatically disables afterward. Logs collected during this period are available for review for up to 14 days—seven days while logging is active and an additional seven days after logging stops. After this period, the logs are permanently deleted. ## Supported providers Push notification logging is supported for FCM, APNs, and custom providers. Email notification logs are generated for SendGrid and custom providers. SMS notification logging is supported for Twilio and custom providers. ## Supported events Push notification logs are generated for **messages** and **replies** sent in one-on-one and group coversations, for message actions like **message edited**, **deleted** and **reactions** and in case of groups, it also logs the **group events**. SMS and Email notifications are supported for **messages** and **replies** sent in one-on-one and group conversations. ## Available filters The Get logs API supports various query parameters to filter logs for better insights. More details about the usage can be found in the [API explorer documentation](https://api-explorer.cometchat.com/reference/notifications-logs). # Migration Guide Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/migration-guide-push-notifications ## Why is Migration required? ### Changed Implementation 1. Push Notifications extension was initially implemented using `TOPICS`. 2. The extension now offers a Token-based approach which simplifies the overall process of implementation for a developer and does most of the heavy lifting. 3. This transition involves changes in the front-end code of your app. 4. Most of the complex code of registering and unregistering to topics has been removed and replaced with one method to register the FCM Token with the extension. ### Your app's user base 1. You may release a new app having the Token-based Push Notifications implementation. But your user base won't update the app at the same time. 2. In such a scenario, we give you the flexibility to use both versions of Push Notifications at the same time until all your users are on the latest version of your app. 3. Once you are confident that all the users of your app are on the latest version, you can use just the token-based push notifications ## How to migrate? 1. Login to CometChat dashboard and go to Push Notifications extension settings and under "Version and related settings", set the Extension version to `V1 & V2`. 2. Release your app with the new implementation by following the respective platform-specific guides to start using Token-based Push Notifications in your app: 3. 1. [JavaScript](/notifications/web-push-notifications) (Web) 2. [Android](/notifications/android-push-notifications) 3. [iOS](/notifications/ios-fcm-push-notifications) 4. [Flutter](/notifications/flutter-push-notifications) 5. [React Native](/notifications/react-native-push-notifications) 6. [Ionic/Cordova](/notifications/capacitor-cordova-ionic-push-notifications) 4. For Android and iOS we also have setup that allows the usage of Native calling screens: 1. [Android - Connection Service](/notifications/android-connection-service) 2. [iOS - APNs](/notifications/ios-apns-push-notifications) # Mute Functionality Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/mute-functionality Learn how to enable your users to mute notifications for certain conversations You can silence one-on-one and/or group conversations for a specific amount of time using the Mute functionality. Aside from that, you can include a Push Notifications section in your apps' settings. Your users can use this feature to turn off Push Notifications for certain chats or to opt-out of receiving Push Notifications altogether. ## Mute or Unmute Chats Chat comprises anything related to messages like: 1. New Message (Text, media, or Custom messages like Polls) 2. Edited Message 3. Deleted Message 4. Response in threads ### Mute Chats You can specify the UIDs and/or GUIDs to be muted. You can mute chats for these conversations for a specific amount of time. | Parameters | Value | Description | | ---------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | uids | Array of UIDs | This parameter allows you to mute one-on-one chat for the mentioned UIDs. | | guids | Array of GUIDs | This parameter allows you to mute group chat for the mentioned GUIDs. | | timeInMS | String consisting of UNIX timestamp | This parameter allows you to mute chats for a specific amount of time for the required UIDs or GUIDs After the mentioned duration, the Push Notifications are received. Eg: "1628425767881" | This functionality uses the `callExtension()` method provided by CometChat SDK. ```js CometChat.callExtension('push-notification', 'POST', 'v2/mute-chat', { "uids": ["cometchat-uid-1"], "guids": ["cometchat-guid-1"], "timeInMS": "1628610749081" }).then(response => { // Success }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray uids = new JSONArray(); JSONArray guids = new JSONArray(); uids.add("cometchat-uid-1"); guids.add("cometchat-guid-1"); body.put("uids", uids); body.put("guids", guids); body.put("timeInMS", "1628425767881"); CometChat.callExtension("push-notification", "POST", "/v2/mute-chat", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .post, endPoint: "v2/mute-chat", body: ["uids":["cometchat-uid-1"], "guids":["cometchat-guid-1"], "timeInMS":"1628610749081"] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### Unmute Chats Used to unmute the chats for certain conversations before the mentioned time during muting. | Parameters | Value | Description | | ---------- | -------------- | --------------------------------------------------------------------------- | | uids | Array of UIDs | This parameter allows you to unmute one-on-one chat for the mentioned UIDs. | | guids | Array of GUIDs | This parameter allows you to unmute group chat for the mentioned GUIDs. | This functionality uses the `callExtension()` method provided by CometChat SDK. ```js CometChat.callExtension('push-notification', 'POST', 'v2/unmute-chat', { "uids": ["cometchat-uid-1"], "guids": ["cometchat-guid-1"] }).then(response => { // Success }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray uids = new JSONArray(); JSONArray guids = new JSONArray(); uids.add("cometchat-uid-1"); guids.add("cometchat-guid-1"); body.put("uids", uids); body.put("guids", guids); CometChat.callExtension("push-notification", "POST", "/v2/unmute-chat", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .post, endPoint: "v2/unmute-chat", body: ["uids":["cometchat-uid-1"], "guids":["cometchat-guid-1"]] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ## Mute or Unmute Calls You can mute the notifications for one-on-one or group calls. This works for Default calling (video or audio calls) offered by CometChat. ### Mute Calls You can specify the UIDs and/or GUIDs to be muted. You can mute calls for these conversations for the said amount of time. | Parameters | Value | Description | | ---------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | uids | Array of UIDs | This parameter allows you to mute one-on-one calls for the mentioned UIDs. | | guids | Array of GUIDs | This parameter allows you to mute group calls for the mentioned GUIDs. | | timeinMS | String consisting of UNIX timestamp | This parameter allows you to mute calls for a specific amount of time for the required UIDs or GUIDs After the mentioned duration, the Push Notifications are received. Eg: "1628425767881" | This functionality uses the `callExtension()` method provided by CometChat SDK. ```js CometChat.callExtension('push-notification', 'POST', 'v2/mute-calls', { "uids": ["cometchat-uid-1"], "guids": ["cometchat-guid-1"], "timeInMS": "1628610749081" }).then(response => { // Success }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray uids = new JSONArray(); JSONArray guids = new JSONArray(); uids.add("cometchat-uid-1"); guids.add("cometchat-guid-1"); body.put("uids", uids); body.put("guids", guids); body.put("timeInMS", "1628425767881"); CometChat.callExtension("push-notification", "POST", "/v2/mute-calls", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .post, endPoint: "v2/mute-calls", body: ["uids":["cometchat-uid-1"], "guids":["cometchat-guid-1"], "timeInMS":"1628610749081"] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### Unmute Calls Used to unmute calls for certain conversations before the mentioned time during muting. | Parameters | Value | Description | | ---------- | -------------- | ---------------------------------------------------------------------------- | | uids | Array of UIDs | This parameter allows you to unmute one-on-one calls for the mentioned UIDs. | | guids | Array of GUIDs | This parameter allows you to unmute group calls for the mentioned GUIDs. | Used to unmute the calls for certain conversations before the mentioned time during muting. ```js CometChat.callExtension('push-notification', 'POST', 'v2/unmute-calls', { "uids": ["cometchat-uid-1"], "guids": ["cometchat-guid-1"] }).then(response => { // Success }) .catch(error => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); JSONArray uids = new JSONArray(); JSONArray guids = new JSONArray(); uids.add("cometchat-uid-1"); guids.add("cometchat-guid-1"); body.put("uids", uids); body.put("guids", guids); CometChat.callExtension("push-notification", "POST", "/v2/unmute-calls", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .post, endPoint: "v2/unmute-calls", body: ["uids":["cometchat-uid-1"], "guids":["cometchat-guid-1"]] as [String : Any], onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ## User Settings Apart from the feature to mute/unmute a set of UIDs or GUIDs using the above APIs, apps can have push notifications according to the user settings. The following user settings can be set: | Settings | Description | | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Do Not Disturb | When turned ON, the "Do Not Disturb" parameter disables the Push Notifications entirely for the user. The user stops receiving push notifications until this setting is explicitly turned OFF. This overrides all the following settings. | | Allow only Mentions | Until turned OFF, the notifications are only sent for text messages for the mentioned receiver of the message | | Mute all one-on-one chat | This parameter can be used to mute chat notifications for all one-on-one conversations. The user will not receive push notifications until this is turned OFF. | | Mute all group chat | This parameter can be used to mute chat notifications for all group conversations. The user will not receive push notifications until the parameter is turned OFF. | | Mute all one-on-one calls | This preference can be used to mute call notifications for all one-on-one conversations. The user will not receive push notifications until the parameter is turned OFF. | | Mute all group calls | This parameter can be used to mute call notifications for all group conversations. The user will not receive push notifications until this is turned OFF. | ### Save User Settings The User settings object needs to be submitted as follows. All the fields are mandatory: ```json { "user-settings": { "dnd": "", "chat": { "allow_only_mentions": "", "mute_group_actions": "", "mute_all_guids": "", "mute_all_uids": "" }, "call": { "mute_all_guids": "", "mute_all_uids": "" } } } ``` This functionality uses the `callExtension()` method provided by CometChat SDK. ```js const userSettings = { "user-settings": { "dnd": false, "chat": { "allow_only_mentions": true, "mute_group_actions": false, "mute_all_guids": false, "mute_all_uids": false }, "call": { "mute_all_guids": false, "mute_all_uids":false } } }; CometChat.callExtension('push-notification', 'POST', 'v2/user-settings', userSettings).then(response => { // Success }) .catch(error => { // Error occured }); ``` ```java JSONObject chatSettings = new JSONObject(); chatSettings.put('allow_only_mentions', false); chatSettings.put('mute_group_actions', false); chatSettings.put('mute_all_guids', false); chatSettings.put('mute_all_uids', false); JSONObject callSettings = new JSONObject(); callSettings.put('mute_all_guids', false); callSettings.put('mute_all_uids', false); JSONObject userSettings = new JSONObject(); userSettings.put('dnd', true); userSettings.put('chat', chatSettings); userSettings.put('call', callSettings); CometChat.callExtension("push-notification", "GET", "/v2/user-settings", null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .get, endPoint: "v2/user-settings", body: { "user-settings": { "dnd": true_false, "chat": { "allow_only_mentions": true_false, "mute_group_actions": true_false, "mute_all_guids": true_false, "mute_all_uids": true_false }, "call": { "mute_all_guids": true_false, "mute_all_uids":true_false } } }, onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` ### Fetch User Settings Fetches all the user settings that are saved by the user. This also returns the list of muted UIDs and GUIDs along with the said time for muting. This functionality uses the `callExtension()` method provided by CometChat SDK. ```js CometChat.callExtension('push-notification', 'GET', 'v2/user-settings', null).then(response => { // Success }) .catch(error => { // Error occured }); ``` ```java CometChat.callExtension("push-notification", "GET", "/v2/user-settings", null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .get, endPoint: "v2/user-settings", body: nil, onSuccess: { (response) in // Success }) { (error) in // Error occured } ``` # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/overview Notifications play a crucial role in alerting users to activity within conversations, such as new messages, replies, reactions, and more. CometChat facilitates user engagement through various notification methods, including: ### Push Notifications Deliver instant updates and improve user engagement. CometChat has the following offerings. * [Push Notifications](/notifications/push-overview) * [Push Notifications extension (Legacy)](/notifications/push-notification-extension-overview) ### Email Notifications Dispatch updates at intervals to re-engage users with extended absence using Emails. * [Email Notifications](/notifications/email-overview) * [Email Notifications extension (Legacy)](/notifications/email-notification-extension). ### SMS Notifications Dispatch updates at intervals to re-engage users with extended absence using SMS. * [SMS Notifications](/notifications/sms-overview) * [SMS Notifications extension (Legacy)](/notifications/sms-notification-extension). # Preferences, Templates & Sounds Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/preferences-templates-sounds ## Common Preferences Login to CometChat dashboard and navigate to the Notifications section. Under Preferences tab, set the event preferences at the CometChat app-level and decide if users have the capability to override these settings. When **"Override"** toggle is enabled, users will have the capability to modify the default value that has been set. ### Group preferences #### Dashboard configuration As the name suggests, these preferences help you to configure Notifications for events generated in group conversations. | Categories | Events | Available preferences | Can user override? | | --------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | Conversations | New messages | • Don't notify
• **Notify for all messages (Default)**
• Notify for messages with mentions | • **Yes (Default)**
• No | | | New replies | • Don't notify
• **Notify for all replies (Default)**
• Notify for replies with mentions | • **Yes (Default)**
• No | | Message actions | Message is edited | • Don't notify
• **Notify (Default)** | • Yes
• **No (Default)** | | | Message is deleted | • Don't notify
• **Notify (Default)** | • Yes
• **No (Default)** | | | Message receives a reaction | • Don't notify
• Notify for reactions received on all messages
• **Notify for reactions received on own messages (Default)** | • **Yes (Default)**
• No | | Group actions | A member leaves | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | | | A new member is added | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | | | A new member joins | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | | | A member is kicked | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | | | A member is banned | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | | | A member is unbanned | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | | | A member's scope changes | • **Don't notify (Default)**
• Notify | • **Yes (Default)**
• No | Regarding Message edited & Message deleted events Push notifications should be triggered for the message edited and message deleted events in order to retract the notification displaying the original message. Turning them off is not recommended. #### Client-side implementation **1. Fetch group preferences** `CometChatNotifications.fetchPreferences()` method retrieves the notification preferences as an instance of `NotificationPreferences` class. If the user has not configured any preferences, the default preferences defined by the CometChat administrator via the dashboard will be returned. ```js // This is applicable for web, React native, Ionic cordova const preferences = await CometChatNotifications.fetchPreferences(); // Display Group preferences const groupPreferences = preferences.getGroupPreferences(); const groupMessagesPreference = groupPreferences.getMessagesPreference(); const groupRepliesPreference = groupPreferences.getRepliesPreference(); const groupReactionsPreference = groupPreferences.getReactionsPreference(); const memberLeftPreference = groupPreferences.getMemberLeftPreference(); const memberAddedPreference = groupPreferences.getMemberAddedPreference(); const memberJoinedPreference = groupPreferences.getMemberJoinedPreference(); const memberKickedPreference = groupPreferences.getMemberKickedPreference(); const memberBannedPreference = groupPreferences.getMemberBannedPreference(); const memberUnbannedPreference = groupPreferences.getMemberUnbannedPreference(); const memberScopeChangedPreference = groupPreferences.getMemberScopeChangedPreference(); ``` ```kotlin CometChatNotifications.fetchPreferences(new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Display group preferences GroupPreferences groupPreferences = notificationPreferences.getGroupPreferences(); MessagesOptions groupMessagesPreference = groupPreferences.getMessagesPreference(); RepliesOptions groupRepliesPreference = groupPreferences.getRepliesPreference(); ReactionsOptions groupReactionsPreference = groupPreferences.getReactionsPreference(); MemberActionsOptions memberAddedPreference = groupPreferences.getMemberAddedPreference(); MemberActionsOptions memberLeftPreference = groupPreferences.getMemberLeftPreference(); MemberActionsOptions memberJoinedPreference = groupPreferences.getMemberJoinedPreference(); MemberActionsOptions memberKickedPreference = groupPreferences.getMemberKickedPreference(); MemberActionsOptions memberBannedPreference = groupPreferences.getMemberBannedPreference(); MemberActionsOptions memberUnbannedPreference = groupPreferences.getMemberUnbannedPreference(); MemberActionsOptions memberScopeChangedPreference = groupPreferences.getMemberScopeChangedPreference(); } @Override public void onError(CometChatException e) { // Something went wrong while fetching notification preferences } }); ``` ```swift CometChatNotifications.fetchPreferences { notificationPreferences in // Display group preferences let groupPreferences = notificationPreferences.groupPreferences; let groupMessages = groupPreferences?.messagesPreference; let groupReplies = groupPreferences?.repliesPreference; let groupReactions = groupPreferences?.reactionsPreference; let left = groupPreferences?.memberLeftPreference; let added = groupPreferences?.memberAddedPreference; let joined = groupPreferences?.memberJoinedPreference; let kicked = groupPreferences?.memberKickedPreference; let banned = groupPreferences?.memberBannedPreference; let unbanned = groupPreferences?.memberUnbannedPreference; let scope = groupPreferences?.memberScopeChangedPreference; } onError: { error in // Something went wrong while fetching notification preferences. print("fetchPreferences: \(error.errorCode) \(error.errorDescription)"); } ``` ```dart CometChatNotifications.fetchPreferences( onSuccess: (notificationPreferences) { // Display group preferences GroupPreferences? groupPreferences = notificationPreferences.groupPreferences; MessagesOptions? messagesPreference = groupPreferences?.messages; RepliesOptions? repliesPreference = groupPreferences?.replies; ReactionsOptions? reactionsPreference = groupPreferences?.reactions; MemberActionsOptions? memberAddedPreference = groupPreferences?.memberAdded; MemberActionsOptions? memberJoinedPreference = groupPreferences?.memberJoined; MemberActionsOptions? memberLeftPreference = groupPreferences?.memberLeft; MemberActionsOptions? memberKickedPreference = groupPreferences?.memberKicked; MemberActionsOptions? memberBannedPreference = groupPreferences?.memberBanned; MemberActionsOptions? memberUnbannedPreference = groupPreferences?.memberUnbanned; MemberActionsOptions? memberScopeChangedPreference = groupPreferences?.memberScopeChanged; }, onError: (e) { debugPrint("fetchPreferences:error ${e.toString()}"); }); ``` **2. Update group preferences** `CometChatNotifications.updatePreferences()` method is used to update a user's notification preferences. The "**override**" toggle defined in the dashboard is crucial when updating preferences. If any preference is non-overridable, the method doesn't generate an error; it instead returns the `NotificationPreferences` object with the updated values where overrides are allowed. This functionality can be beneficial for temporarily superseding certain user preferences to ensure notifications for a specific event are delivered. Nonetheless, it is advisable to use this approach temporarily to avoid confusing users with unexpected changes to their notification settings. It is unnecessary to specify all values; only set and save the preferences that have been changed. Since the user is performing this action, enums have values as `SUBSCRIBE` or `DONT_SUBSCRIBE`. It is equivalent to "Notify" and "Don't notify" respectively, from the dashboard preferences. ```js // This is applicable for web, React native, Ionic cordova // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. const updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. const groupPreferences = new GroupPreferences(); // Change group preferences groupPreferences.setMessagesPreference(MessagesOptions.DONT_SUBSCRIBE); groupPreferences.setRepliesPreference(RepliesOptions.DONT_SUBSCRIBE); groupPreferences.setReactionsPreference(ReactionsOptions.DONT_SUBSCRIBE); groupPreferences.setMemberAddedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberKickedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberJoinedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberLeftPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberBannedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberUnbannedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberScopeChangedPreference( MemberActionsOptions.SUBSCRIBE ); // Load the updates in the NotificationPreferences instance. updatedPreferences.setGroupPreferences(groupPreferences); // Update the preferences and receive the udpated copy. const preferences = await CometChatNotifications.updatePreferences( updatedPreferences ); ``` ```kt // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. NotificationPreferences updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. GroupPreferences groupPreferences = new GroupPreferences(); // Change group preferences groupPreferences.setMessagesPreference(MessagesOptions.DONT_SUBSCRIBE); groupPreferences.setRepliesPreference(RepliesOptions.DONT_SUBSCRIBE); groupPreferences.setReactionsPreference(ReactionsOptions.DONT_SUBSCRIBE); groupPreferences.setMemberAddedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberKickedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberJoinedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberLeftPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberBannedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberUnbannedPreference(MemberActionsOptions.SUBSCRIBE); groupPreferences.setMemberScopeChangedPreference(MemberActionsOptions.SUBSCRIBE); // Load the updates in the NotificationPreferences instance. updatedPreferences.setGroupPreferences(groupPreferences); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Updated notificationPreferences } @Override public void onError(CometChatException e) { // Something went wrong } }); ``` ```swift // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. let updatedPreferences = CometChatNotifications.NotificationPreferences(); // Instantiate the preferences that you want to update. let groupPreferences = CometChatNotifications.GroupPreferences(); // Change group preferences groupPreferences.set(messagesPreference: .DONT_SUBSCRIBE) groupPreferences.set(repliesPreference: .DONT_SUBSCRIBE) groupPreferences.set(reactionsPreference: .DONT_SUBSCRIBE) groupPreferences.set(memberAddedPreference: .SUBSCRIBE) groupPreferences.set(memberKickedPreference: .SUBSCRIBE) groupPreferences.set(memberJoinedPreference: .SUBSCRIBE) groupPreferences.set(memberLeftPreference: .SUBSCRIBE) groupPreferences.set(memberBannedPreference: .SUBSCRIBE) groupPreferences.set(memberUnbannedPreference: .SUBSCRIBE) groupPreferences.set(memberScopeChangedPreference: .SUBSCRIBE) // Load the updates in the NotificationPreferences instance. updatedPreferences.set(groupPreferences: groupPreferences) // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences) { updatedPreferences in print("updatePreferences: \(updatedPreferences)") } onError: { error in print("updatePreferences: \(error.errorCode) \(error.errorDescription)") } ``` ```dart // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences NotificationPreferences updatedPreferences = NotificationPreferences(); GroupPreferences groupPreferences = GroupPreferences( messages: MessagesOptions.SUBSCRIBE_TO_MENTIONS, replies: RepliesOptions.SUBSCRIBE_TO_ALL, reactions: ReactionsOptions.SUBSCRIBE_TO_REACTIONS_ON_ALL_MESSAGES, memberAdded: MemberActionsOptions.SUBSCRIBE, memberJoined: MemberActionsOptions.SUBSCRIBE, memberLeft: MemberActionsOptions.SUBSCRIBE, memberKicked: MemberActionsOptions.SUBSCRIBE, memberBanned: MemberActionsOptions.SUBSCRIBE, memberUnbanned: MemberActionsOptions.SUBSCRIBE, memberScopeChanged: MemberActionsOptions.SUBSCRIBE, ); updatedPreferences.groupPreferences = groupPreferences; // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, onSuccess: (preferencesAfterUpdate) { debugPrint("updatePreferences:success"); // Use the preferencesAfterUpdate }, onError: (e) { debugPrint("updatePreferences:error: ${e.toString()}"); }); ``` ### One-on-one preferences #### Dashboard configuration As the name suggests, these preferences help you to configure Notifications for events generated in one-on-one conversations. | Categories | Events | Available preferences | Can user override? | | --------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | Conversations | New messages | • Don't notify
• **Notify for all messages (Default)**
• Notify for messages with mentions | • **Yes (Default)**
• No | | | New replies | • Don't notify
• **Notify for all replies (Default)**
• Notify for replies with mentions | • **Yes (Default)**
• No | | Message actions | Message is edited | • Don't notify
• **Notify (Default)** | - Yes
• **No (Default)** | | | Message is deleted | • Don't notify
• **Notify (Default)** | - Yes
• **No (Default)** | | | Message receives a reaction | • Don't notify
• Notify for reactions received on all messages
• **Notify for reactions received on own messages (Default)** | • **Yes (Default)**
• No | Regarding Message edited & Message deleted events Push notifications should be triggered for the message edited and message deleted events in order to retract the notification displaying the original message. Turning them off is not recommended. #### Client-side implementation `CometChatNotifications.fetchPreferences()` method retrieves the notification preferences saved by the user as an instance of `NotificationPreferences` class. If the user has not configured any preferences, the default preferences defined by the CometChat administrator via the dashboard will be returned. **1. Fetch one-on-one preferences** ```js // This is applicable for web, React native, Ionic cordova const preferences = await CometChatNotifications.fetchPreferences(); // Display One-on-One preferences const oneOnOnePreferences = preferences.getOneOnOnePreferences(); const oneOnOneMessagesPreference = oneOnOnePreferences.getMessagesPreference(); const oneOnOneRepliesPreference = oneOnOnePreferences.getRepliesPreference(); const oneOnOneReactionsPreference = oneOnOnePreferences.getReactionsPreference(); ``` ```kotlin CometChatNotifications.fetchPreferences(new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Display one-on-one preferences OneOnOnePreferences oneOnOnePreferences = notificationPreferences.getOneOnOnePreferences(); MessagesOptions oneOnOneMessagesPreference = oneOnOnePreferences.getMessagesPreference(); RepliesOptions oneOnOneRepliesPreference = oneOnOnePreferences.getRepliesPreference(); ReactionsOptions oneOnOneReactionsPreference = oneOnOnePreferences.getReactionsPreference(); } @Override public void onError(CometChatException e) { // Something went wrong while fetching notification preferences } }); ``` ```swift CometChatNotifications.fetchPreferences { notificationPreferences in // Display one-on-one preferences let oneOnOnePreferences = notificationPreferences.oneOnOnePreferences; let oneMessages = oneOnOnePreferences?.messagesPreference; let oneReplies = oneOnOnePreferences?.repliesPreference; let oneReactions = oneOnOnePreferences?.reactionsPreference; } onError: { error in // Something went wrong while fetching notification preferences. print("fetchPreferences: \(error.errorCode) \(error.errorDescription)"); } ``` ```dart CometChatNotifications.fetchPreferences( onSuccess: (notificationPreferences) { // Display one-on-one preferences OneOnOnePreferences? oneOnOnePreferences = notificationPreferences.oneOnOnePreferences; MessagesOptions? oneOnOneMessagesPreference = oneOnOnePreferences?.messages; RepliesOptions? oneOnOneRepliesPreference = oneOnOnePreferences?.replies; ReactionsOptions? oneOnOneReactionsPreference = oneOnOnePreferences?.reactions; }, onError: (e) { debugPrint("fetchPreferences:error ${e.toString()}"); }); ``` **2. Update one-on-one preferences** `CometChatNotifications.updatePreferences()` method is used to update a user's notification preferences. The "**override**" toggle defined in the dashboard is crucial when updating preferences. If any preference is non-overridable, the method doesn't generate an error; it instead returns the `NotificationPreferences` object with the updated values where overrides are allowed. This functionality can be beneficial for temporarily superseding certain user preferences to ensure notifications for a specific event are delivered. Nonetheless, it is advisable to use this approach temporarily to avoid confusing users with unexpected changes to their notification settings. It is unnecessary to specify all values; only set and save the preferences that have been changed. ```js // This is applicable for web, React native, Ionic cordova // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. const updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. const oneOnOnePreferences = new OneOnOnePreferences(); // Change one-on-one preferences oneOnOnePreferences.setMessagesPreference(MessagesOptions.DONT_SUBSCRIBE); oneOnOnePreferences.setRepliesPreference(RepliesOptions.DONT_SUBSCRIBE); oneOnOnePreferences.setReactionsPreference(ReactionsOptions.DONT_SUBSCRIBE); // Load the updates in the NotificationPreferences instance. updatedPreferences.setOneOnOnePreferences(oneOnOnePreferences); // Update the preferences and receive the udpated copy. const preferences = await CometChatNotifications.updatePreferences( updatedPreferences ); ``` ```kotlin // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. NotificationPreferences updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. OneOnOnePreferences oneOnOnePreferences = new OneOnOnePreferences(); // Change one-on-one preferences oneOnOnePreferences.setMessagesPreference(MessagesOptions.DONT_SUBSCRIBE); oneOnOnePreferences.setRepliesPreference(RepliesOptions.DONT_SUBSCRIBE); oneOnOnePreferences.setReactionsPreference(ReactionsOptions.DONT_SUBSCRIBE); // Load the updates in the NotificationPreferences instance. updatedPreferences.setOneOnOnePreferences(oneOnOnePreferences); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Updated notificationPreferences } @Override public void onError(CometChatException e) { // Something went wrong } }); ``` ```swift // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. let updatedPreferences = CometChatNotifications.NotificationPreferences(); // Instantiate the preferences that you want to update. let oneOnOnePreferences = CometChatNotifications.OneOnOnePreferences(); // Change one-on-one preferences oneOnOnePreferences.set(messagesPreference: .DONT_SUBSCRIBE) oneOnOnePreferences.set(repliesPreference: .DONT_SUBSCRIBE) oneOnOnePreferences.set(reactionsPreference: .DONT_SUBSCRIBE) // Load the updates in the NotificationPreferences instance. updatedPreferences.set(oneOnOnePreferences: oneOnOnePreferences) // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences) { updatedPreferences in print("updatePreferences: \(updatedPreferences)") } onError: { error in print("updatePreferences: \(error.errorCode) \(error.errorDescription)") } ``` ```dart // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences NotificationPreferences updatedPreferences = NotificationPreferences(); // Instantiate the preferences that you want to update. OneOnOnePreferences oneOnOnePreferences = OneOnOnePreferences( messages: MessagesOptions.SUBSCRIBE_TO_ALL, replies: RepliesOptions.SUBSCRIBE_TO_MENTIONS, reactions: ReactionsOptions.SUBSCRIBE_TO_REACTIONS_ON_ALL_MESSAGES); // Load the updates in the NotificationPreferences instance. updatedPreferences.oneOnOnePreferences = oneOnOnePreferences; // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, onSuccess: (preferencesAfterUpdate) { debugPrint("updatePreferences:success"); // Use the preferencesAfterUpdate }, onError: (e) { debugPrint("updatePreferences:error: ${e.toString()}"); }); ``` ### Mute preferences #### Dashboard configuration These preferences allow you to control whether the users will be able to modify mute preferences. | Mute preferences | Can user configure? | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | Mute all notifications (DND) | • **Yes (Default)** - *Users can activate the Do Not Disturb (DND) feature.*
• No | | Mute group conversations | • **Yes (Default)** - *Users can mute notifications for chosen group conversations for a specified duration.*
• No | | Mute one-on-one conversations | • **Yes (Default)** - *Users can mute notifications for chosen one-on-one conversations for a specified duration.*
• No | #### Client-side implementation **1. Fetch mute preferences** `CometChatNotifications.fetchPreferences()` method retrieves the notification preferences saved by the user as an instance of `NotificationPreferences` class. If the user has not configured any preferences, the default preferences defined by the CometChat administrator via the dashboard will be utilized. You can use the `CometChatNotifications.getMutedConversations()` method to display a list of conversations that have been muted by users. The method will return an array of `MutedConversations` object. ```js // This is applicable for web, React native, Ionic cordova // Fetch mute preferences const preferences = await CometChatNotifications.fetchPreferences(); // Display Mute preferences const mutePreferences = preferences.getMutePreferences(); const DNDPreference = mutePreferences.getDNDPreference(); // Fetch muted conversations const mutedConversations = await CometChatNotifications.getMutedConversations(); ``` ```kotlin // Fetch mute preferences CometChatNotifications.fetchPreferences(new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Display mute preferences MutePreferences mutePreferences = notificationPreferences.getMutePreferences(); DNDOptions dndPreference = mutePreferences.getDNDPreference(); } @Override public void onError(CometChatException e) { // Something went wrong while fetching notification preferences } }); // Fetch muted conversations CometChatNotifications.getMutedConversations(new CometChat.CallbackListener>() { @Override public void onSuccess(List mutedConversations) { // List of muted conversations } @Override public void onError(CometChatException e) { // Fetching muted conversations failed. } }); ``` ```swift CometChatNotifications.fetchPreferences { notificationPreferences in // Display mute preferences let mutePreferences = notificationPreferences.mutePreferences; let dndPreference = mutePreferences?.DNDPreference; } onError: { error in // Something went wrong while fetching notification preferences. print("fetchPreferences: \(error.errorCode) \(error.errorDescription)"); } // Fetch muted conversations CometChatNotifications.getMutedConversations { mutedConversations in print("getMutedConversations: \(mutedConversations)") } onError: { error in print("getMutedConversations: \(error.errorCode) \(error.errorDescription)") } ``` ```dart // Fetch mute preferences CometChatNotifications.fetchPreferences( onSuccess: (notificationPreferences) { // Display mute preferences MutePreferences? mutePreferences = notificationPreferences.mutePreferences; DNDOptions? dndPreference = mutePreferences?.dnd; }, onError: (e) { debugPrint("fetchPreferences:error ${e.toString()}"); }); // Fetch muted conversations CometChatNotifications.getMutedConversations( onSuccess: (mutedConversations) { debugPrint("getMutedConversations:success"); // use mutedConversations }, onError: (e) { debugPrint("getMutedConversations:error ${e.toString()}"); }); ``` **2. Update mute preferences** `CometChatNotifications.updatePreferences()` method is used to update a user's notification preferences. The "**override**" toggle defined in the dashboard is crucial when updating preferences. If any preference is non-overridable, the method doesn't generate an error; it instead returns the `NotificationPreferences` object with the updated values where overrides are allowed. This functionality can be beneficial for temporarily superseding certain user preferences to ensure notifications for a specific event are delivered. Nonetheless, it is advisable to use this approach temporarily to avoid confusing users with unexpected changes to their notification settings. It is unnecessary to specify all values; only set and save the preferences that have been changed. **To mute** one or more group or one-on-one conversations, utilize the `CometChatNotifications.muteConversations()` method. This method requires an array of `MutedConversation` objects, each containing the following properties: | Property | Type | Description | | -------- | ------ | ------------------------------------------------------------- | | `id` | String | This can either be `uid` or `guid`. | | `type` | String | This can either be `oneOnOne` or `group`. | | `until` | Number | This is a valid timestamp from the future. Eg: 1710696964705. | **To unmute** one or more group or one-on-one conversations that were muted by the user, utilize the `CometChatNotifications.unmuteConversations()` method. This method requires an array of `UnmutedConversation` objects, each containing the following properties: | Property | Type | Description | | -------- | ------ | ----------------------------------------- | | `id` | String | This can either be `uid` or `guid`. | | `type` | String | This can either be `oneOnOne` or `group`. | ```js // This is applicable for web, React native, Ionic cordova // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. const updatedPreferences = new NotificationPreferences(); const mutePreferences = new MutePreferences(); // Change mute preferences mutePreferences.setDNDPreference(DNDOptions.ENABLED); // Load the updates in the NotificationPreferences instance. updatedPreferences.setMutePreferences(mutePreferences); // Update the preferences and receive the udpated copy. const notificationPreferences = await CometChatNotifications.updatePreferences( updatedPreferences ); // Mute conversations const until = Date.now() + 86400000; // Mute for 1 day const mutedUser = new MutedConversation(); mutedUser.setId('cometchat-uid-1'); mutedUser.setType(CometChatNotifications.MutedConversationType.ONE_ON_ONE); mutedUser.setUntil(until); const mutedGroup = new MutedConversation(); mutedGroup.setId('cometchat-guid-1'); mutedGroup.setType(CometChatNotifications.MutedConversationType.GROUP); mutedGroup.setUntil(until); await CometChatNotifications.muteConversations([mutedUser, mutedGroup]); // Unmute conversations const unmutedUser = new UnmutedConversation(); unmutedUser.setId('cometchat-uid-1'); unmutedUser.setType(CometChatNotifications.MutedConversationType.ONE_ON_ONE); const unmuteList = [unmutedUser]; await CometChatNotifications.unmuteConversations(unmuteList); ``` ```kotlin // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. NotificationPreferences updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. MutePreferences mutePreferences = new MutePreferences(); // Change mute preferences mutePreferences.setDNDPreference(DNDOptions.ENABLED); // Load the updates in the NotificationPreferences instance. updatedPreferences.setMutePreferences(mutePreferences); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Updated notificationPreferences } @Override public void onError(CometChatException e) { // Something went wrong } }); // Mute conversations long until = System.currentTimeMillis() + 86400000; // Mute for 1 day MutedConversation mutedUser = new MutedConversation(); mutedUser.setId("cometchat-uid-1"); mutedUser.setType(MutedConversationType.ONE_ON_ONE); mutedUser.setUntil(until); MutedConversation mutedGroup = new MutedConversation(); mutedGroup.setId("cometchat-guid-1"); mutedGroup.setType(MutedConversationType.GROUP); mutedGroup.setUntil(until); List allMuted = new ArrayList<>(); allMuted.add(mutedUser); allMuted.add(mutedGroup); CometChatNotifications.muteConversations(allMuted, new CometChat.CallbackListener() { @Override public void onSuccess(String s) { // Mute success } @Override public void onError(CometChatException e) { // Mute failed } }); // Unmute conversations UnmutedConversation u = new UnmutedConversation(); u.setId("cometchat-uid-1"); u.setType(MutedConversationType.ONE_ON_ONE); List unmuteList = new ArrayList<>(); unmuteList.add(u); CometChatNotifications.unmuteConversations(unmuteList, new CometChat.CallbackListener() { @Override public void onSuccess(String s) { // Unmute success } @Override public void onError(CometChatException e) { // Unmute failed } }); ``` ```swift // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. let updatedPreferences = CometChatNotifications.NotificationPreferences(); // Instantiate the preferences that you want to update. let mutePreferences = CometChatNotifications.MutePreferences(); // Change mute preferences mutePreferences.set(DNDPreference:.ENABLED) // Load the updates in the NotificationPreferences instance. updatedPreferences.set(mutePreferences: mutePreferences); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences) { updatedPreferences in print("updatePreferences: \(updatedPreferences)") } onError: { error in print("updatePreferences: \(error.errorCode) \(error.errorDescription)") } // Mute conversations let untilInterval = Date().addingTimeInterval(86400) // Mute for 1 day let until = Int(untilInterval.timeIntervalSince1970 * 1000) // Convert to milliseconds var mutedUser = CometChatNotifications.MutedConversation() mutedUser.id = "cometchat-uid-1" mutedUser.type = .ONE_ON_ONE mutedUser.until = until var mutedGroup = CometChatNotifications.MutedConversation() mutedGroup.id = "cometchat-guid-1" mutedGroup.type = .GROUP mutedGroup.until = until let allMuted = [mutedUser, mutedGroup] CometChatNotifications.muteConversations(allMuted) { success in print("muteConversations: \(success)") } onError: { error in print("muteConversations: \(error.errorCode) \(error.errorDescription)") } // Unmute conversations var unmutedUser = CometChatNotifications.UnmutedConversation() unmutedUser.id = "cometchat-uid-1" unmutedUser.type = .ONE_ON_ONE let unmuteList = [unmutedUser] CometChatNotifications.unmuteConversations(unmuteList) { success in print("unmuteConversations: \(success)") } onError: { error in print("unmuteConversations: \(error.errorCode) \(error.errorDescription)") } ``` ```dart // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences NotificationPreferences updatedPreferences = NotificationPreferences(); MutePreferences mutePreferences = MutePreferences(dnd: DNDOptions.DISABLED); updatedPreferences.mutePreferences = mutePreferences; // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, onSuccess: (preferencesAfterUpdate) { debugPrint("updatePreferences:success"); // Use the preferencesAfterUpdate }, onError: (e) { debugPrint("updatePreferences:error: ${e.toString()}"); }); // Mute conversations int current = DateTime.now().millisecondsSinceEpoch; int oneDayMillis = 24 * 60 * 60 * 1000; int until = current + oneDayMillis; MutedConversation mutedUser = MutedConversation( id: "cometchat-uid-1", type: MutedConversationType.ONE_ON_ONE, until: until); MutedConversation mutedGroup = MutedConversation( id: "cometchat-guid-1", type: MutedConversationType.GROUP, until: until); List mutedConversations = []; mutedConversations.add(mutedUser); mutedConversations.add(mutedGroup); CometChatNotifications.muteConversations( mutedConversations, onSuccess: (response) { debugPrint("muteConversations:success ${response.toString()}"); }, onError: (e) { debugPrint("muteConversations:error ${e.toString()}"); }, ); // Unmute conversations UnmutedConversation unmutedUser = UnmutedConversation(id: "cometchat-uid-1", type: MutedConversationType.ONE_ON_ONE); List unmuteList = []; unmuteList.add(unmutedUser); CometChatNotifications.unmuteConversations(unmuteList, onSuccess: (response) { debugPrint("unmuteConversations:success ${response.toString()}"); },onError: (e) { debugPrint("unmuteConversations:success ${e.toString()}"); }); ``` ### Notification schedule #### Dashboard configuration Notifications will be delivered based on the specified daily timetable, adhering to the user's local time zone. Select **"None"** to disable Notifications for that day. For instance, this can be applied to weekends, such as Saturday and Sunday. | Day | From | To | Can user override? | | --------- | ---------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------- | | Monday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | • **Yes (Default)** - *Users can configure a personalized notification schedule.*
• No | | Tuesday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | | | Wednesday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | | | Thursday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | | | Friday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | | | Saturday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | | | Sunday | • 0 to 2359 **(Default: 0)**
• None | • Upto 2359 **(Default: 2359)** | | #### Client-side implementation **1. Fetch schedule preferences** `CometChatNotifications.fetchPreferences()` method retrieves the notification preferences saved by the user as an instance of `NotificationPreferences` class. If the user has not configured any preferences, the default preferences defined by the CometChat administrator via the dashboard will be utilized. ```js // This is applicable for web, React native, Ionic cordova const preferences = await CometChatNotifications.fetchPreferences(); // Display schedule preferences const mutePreferences = preferences.getMutePreferences(); const schedulePreference = mutePreferences.getSchedulePreference(); const mondaySchedule = schedulePreference.get(DayOfWeek.MONDAY); const tuesdaySchedule = schedulePreference.get(DayOfWeek.TUESDAY); const wednesdaySchedule = schedulePreference.get(DayOfWeek.WEDNESDAY); const thursdaySchedule = schedulePreference.get(DayOfWeek.THURSDAY); const fridaySchedule = schedulePreference.get(DayOfWeek.FRIDAY); const saturdaySchedule = schedulePreference.get(DayOfWeek.SATURDAY); const sundaySchedule = schedulePreference.get(DayOfWeek.SUNDAY); // This action can be performed on other days of the week. const mondayFrom = mondaySchedule?.getFrom(); const mondayTo = mondaySchedule?.getTo(); const mondayDnd = mondaySchedule?.getDND(); ``` ```kotlin CometChatNotifications.fetchPreferences(new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Display schedule preferences MutePreferences mutePreferences = notificationPreferences.getMutePreferences(); Map scheduleMap = mutePreferences.getSchedulePreference(); DaySchedule monday = scheduleMap.get(DayOfWeek.MONDAY); DaySchedule tuesday = scheduleMap.get(DayOfWeek.TUESDAY); DaySchedule wednesday = scheduleMap.get(DayOfWeek.WEDNESDAY); DaySchedule thrusday = scheduleMap.get(DayOfWeek.THURSDAY); DaySchedule friday = scheduleMap.get(DayOfWeek.FRIDAY); DaySchedule saturday = scheduleMap.get(DayOfWeek.SATURDAY); DaySchedule sunday = scheduleMap.get(DayOfWeek.SUNDAY); // This action can be performed on other days of the week. int mondayFrom = monday.getFrom(); int mondayTo = monday.getTo(); boolean mondayDnd = monday.getDnd(); } @Override public void onError(CometChatException e) { // Something went wrong while fetching notification preferences } }); ``` ```swift CometChatNotifications.fetchPreferences { notificationPreferences in // Display schedule preferences let mutePreferences = notificationPreferences.mutePreferences; let schedulePref = mutePreferences?.schedulePreference; let mondaySchedule = schedulePref?[.MONDAY]; let tuesdaySchedule = schedulePref?[.TUESDAY]; let wednesdaySchedule = schedulePref?[.WEDNESDAY]; let thursdaySchedule = schedulePref?[.THURSDAY]; let fridaySchedule = schedulePref?[.FRIDAY]; let saturdaySchedule = schedulePref?[.SATURDAY]; let sundaySchedule = schedulePref?[.SUNDAY]; // This action can be performed on other days of the week. let mondayFrom = mondaySchedule?.from; let mondayTo = mondaySchedule?.to; let mondayDND = mondaySchedule?.dnd; } onError: { error in // Something went wrong while fetching notification preferences. print("fetchPreferences: \(error.errorCode) \(error.errorDescription)"); } ``` ```dart CometChatNotifications.fetchPreferences( // Display schedule preferences MutePreferences? mutePreferences = notificationPreferences.mutePreferences; Map? scheduleMap = mutePreferences?.schedule; DaySchedule? mondaySchedule = scheduleMap?[DayOfWeek.MONDAY]; DaySchedule? tuesdaySchedule = scheduleMap?[DayOfWeek.TUESDAY]; DaySchedule? wednesdaySchedule = scheduleMap?[DayOfWeek.WEDNESDAY]; DaySchedule? thursdaySchedule = scheduleMap?[DayOfWeek.THURSDAY]; DaySchedule? fridaySchedule = scheduleMap?[DayOfWeek.FRIDAY]; DaySchedule? saturdaySchedule = scheduleMap?[DayOfWeek.SATURDAY]; DaySchedule? sundaySchedule = scheduleMap?[DayOfWeek.SUNDAY]; // This action can be performed on other days of the week. int? mondayFrom = mondaySchedule?.from; int? mondayTo = mondaySchedule?.to; bool? mondayDnd = mondaySchedule?.dnd; }, onError: (e) { debugPrint("fetchPreferences:error ${e.toString()}"); }); ``` **2. Update schedule preferences** `CometChatNotifications.updatePreferences()` method is used to update a user's notification preferences. The "**override**" toggle defined in the dashboard is crucial when updating preferences. If any preference is non-overridable, the method doesn't generate an error; it instead returns the `NotificationPreferences` object with the updated values where overrides are allowed. This functionality can be beneficial for temporarily superseding certain user preferences to ensure notifications for a specific event are delivered. Nonetheless, it is advisable to use this approach temporarily to avoid confusing users with unexpected changes to their notification settings. It is unnecessary to specify all values; only set and save the preferences that have been changed. ```js // This is applicable for web, React native, Ionic cordova // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. const updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. const mutePreferences = new MutePreferences(); // Change schedule preferences const scheduleMap = new Map(); const mondaySchedule = new DaySchedule(2015, 2345, false); scheduleMap.set(DayOfWeek.MONDAY, mondaySchedule); mutePreferences.setSchedulePreference(scheduleMap); // Load the updates in the NotificationPreferences instance. updatedPreferences.setOneOnOnePreferences(oneOnOnePreferences); updatedPreferences.setGroupPreferences(groupPreferences); updatedPreferences.setMutePreferences(mutePreferences); // Update the preferences and receive the udpated copy. const preferences = await CometChatNotifications.updatePreferences(updatedPreferences); ``` ```kotlin // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. NotificationPreferences updatedPreferences = new NotificationPreferences(); // Instantiate the preferences that you want to update. MutePreferences mutePreferences = new MutePreferences(); // Change schedule preferences Map scheduleMap = new ArrayMap(); DaySchedule mondaySchedule = new DaySchedule(); mondaySchedule.setFrom(2015); mondaySchedule.setTo(2345); mondaySchedule.setDnd(false); scheduleMap.put(DayOfWeek.MONDAY, mondaySchedule); mutePreferences.setSchedulePreference(scheduleMap); // Load the updates in the NotificationPreferences instance. updatedPreferences.setMutePreferences(mutePreferences); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Updated notificationPreferences } @Override public void onError(CometChatException e) { // Something went wrong } }); ``` ```swift // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. let updatedPreferences = CometChatNotifications.NotificationPreferences(); // Instantiate the preferences that you want to update. let mutePreferences = CometChatNotifications.MutePreferences(); // Change schedule preferences var dictionary = [CometChatNotifications.DayOfWeek:CometChatNotifications.DaySchedule](); dictionary[.MONDAY] = CometChatNotifications.DaySchedule(from: 2015, to: 2345, dnd: false) mutePreferences.set(schedulePreference: dictionary) // Load the updates in the NotificationPreferences instance. updatedPreferences.set(mutePreferences: mutePreferences); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences) { updatedPreferences in print("updatePreferences: \(updatedPreferences)") } onError: { error in print("updatePreferences: \(error.errorCode) \(error.errorDescription)") } ``` ```dart // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences NotificationPreferences updatedPreferences = NotificationPreferences(); // Instantiate the preferences that you want to update. MutePreferences mutePreferences = MutePreferences(dnd: DNDOptions.DISABLED); Map scheduleMap = {}; DaySchedule mondaySchedule = DaySchedule(from: 2015, to: 2345, dnd: false); scheduleMap[DayOfWeek.MONDAY] = mondaySchedule; mutePreferences.schedule = scheduleMap; updatedPreferences.mutePreferences = mutePreferences; // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, onSuccess: (preferencesAfterUpdate) { debugPrint("updatePreferences:success"); // Use the preferencesAfterUpdate }, onError: (e) { debugPrint("updatePreferences:error: ${e.toString()}"); }); ``` ### Bypass preferences for mentions End users who have enabled Do Not Disturb (DND), muted a conversation, or set up a schedule will still receive notifications when they are mentioned in a new message or reply, if this setting is enabled. ### Calls preferences Push notifications are triggered for calling events. These notifications are not delivered via Email or SMS. | Events | Available preferences | Can user override? | | --------------- | ------------------------------------------ | ------------------ | | Call initiated | • Don't notify
• **Notify (Default)** | No | | Call ongoing | • Don't notify
• **Notify (Default)** | No | | Call cancelled | • Don't notify
• **Notify (Default)** | No | | Call rejected | • Don't notify
• **Notify (Default)** | No | | Call unanswered | • Don't notify
• **Notify (Default)** | No | | Call busy | • Don't notify
• **Notify (Default)** | No | | Call ended | • Don't notify
• **Notify (Default)** | No | ### Reset preferences `CometChatNotifications.resetPreferences()` method is used to reset the preferences for a user to their default state. The default state of preferences is defined by the CometChat administrator via the dashboard. ```js // This is applicable for web, React native, Ionic cordova const defaultPreferences = await CometChatNotifications.resetPreferences(); ``` ```kotlin CometChatNotifications.resetPreferences(new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences defaultPreferences) { // Display the defaultPreferneces. } @Override public void onError(CometChatException e) { // Something went wrong. } }); ``` ```swift CometChatNotifications.resetPreferences { defaultPreferences in print("resetPreferences: defaultPreferences \(defaultPreferences)"); } onError: { error in print("resetPreferences: \(error.errorCode) \(error.errorDescription)"); } ``` ```dart CometChatNotifications.resetPreferences(onSuccess: (defaultPreferences) { debugPrint("resetPreferences:success"); // defaultPreferences are available after reset. },onError: (e) { debugPrint("resetPreferences:error ${e.toString()}"); }); ``` ## Push notification preferences The notification payload sent to FCM, APNs, or custom providers can be customized to include the CometChat message object for new messages and replies. To comply with the 4 KB payload size limit required by FCM and APNs, specific parts of the message object can be excluded to reduce the payload size. Additionally, a custom payload in the form of a JSON object can be included in the push payload. | Payload setting | Available preferences | | -------------------------------- | ----------------------------------------------------------------- | | Include CometChat message object | • **false (Default)**
• true | | Include Sender's metadata | • false
• **true (Default)** | | Include Receiver's metadata | • false
• **true (Default)** | | Include message metadata | • false
• **true (Default)** | | Trim CometChat text message | • **false (Default)**
• true | | Custom JSON | No defaults for this value. If not set, this key is not included. | ## Email notification preferences | Preference | Values | Description | | -------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Notify for unread messages only | • **true (Default)**
• false | • Email notifications are sent only when there are unread messages in a conversation.
• When set to `false`, the notifications are sent irrespective of whether there are unread messages or not. | | The interval between two emails (in minutes) | 120 | • By default, the notifications are triggered after 120 minutes.
• The minimum allowed value is 1 minute.
• The maximum is 1440 minutes (24 hours). | | Maximum emails per day | 20 | • By default, a maximum of 20 email notifications can be sent to a user on a given day.
• The minimum value can be set to 1.
• The maximum can be 30. | | Maximum emails per conversation per day | 2 | • By default, a maximum of 2 email notifications can be sent to a user for a given conversation on a given day.
• The minimum value can be set to 1.
• The maximum can be 30. | | Include CometChat message object | • **false (Default)**
• true | If enabled, the message object will be included in the email notification payload. | | Include Sender's metadata | • **false (Default)**
• true | If enabled, the sender's metadata will be included in the message object (applicable only when the message object is included). | | Include Receiver's metadata | • **false (Default)**
• true | If enabled, the receiver's metadata will be included in the message object (applicable only when the message object is included). | | Include message metadata | • **false (Default)**
• true | If enabled, the message metadata will be included in the message object (applicable only when the message object is included). | ## SMS notification preferences | Preference | Values | Description | | -------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Notify for unread messages only | • **true (Default)**
• false | • SMS notifications are sent only when there are unread messages in a conversation.
• When set to `false`, the notifications are sent irrespective of whether there are unread messages or not. | | The interval between two emails (in minutes) | 120 | • By default, the notifications are triggered after 120 minutes.
• The minimum allowed value is 1 minute.
• The maximum is 1440 minutes (24 hours). | | Maximum SMS per day | 20 | • By default, a maximum of 20 SMS notifications can be sent to a user on a given day.
• The minimum value can be set to 1.
• The maximum can be 30. | | Maximum SMS per conversation per day | 2 | • By default, a maximum of 2 SMS notifications can be sent to a user for a given conversation on a given day.
• The minimum value can be set to 1.
• The maximum can be 30. | | Include CometChat message object | • **false (Default)**
• true | If enabled, the message object will be included in the SMS notification payload. | | Include Sender's metadata | • **false (Default)**
• true | If enabled, the sender's metadata will be included in the message object (applicable only when the message object is included). | | Include Receiver's metadata | • **false (Default)**
• true | If enabled, the receiver's metadata will be included in the message object (applicable only when the message object is included). | | Include message metadata | • **false (Default)**
• true | If enabled, the message metadata will be included in the message object (applicable only when the message object is included). | ## Common templates and sounds Templates are designed to specify the content displayed in notifications on the user's device for different events. Templates incorporate `placeholders`, which reference specific pieces of information determined by properties from the event. **For example**, New message event has the following structure: ```json { "data": { "id": "17", "conversationId": "group_cometchat-guid-1", "sender": "cometchat-uid-2", "receiverType": "group", "receiver": "cometchat-guid-1", "category": "message", "type": "text", "data": { "text": "Hello! How are you?", "entities": { "sender": { "entity": { "uid": "cometchat-uid-2", "name": "George Alan", "role": "default", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", "status": "available", "lastActiveAt": 1707901272 }, "entityType": "user" }, "receiver": { "entity": { "guid": "cometchat-guid-1", "icon": "https://assets.cometchat.io/sampleapp/v2/groups/cometchat-guid-1.webp", "name": "Hiking Group", "type": "public", "owner": "cometchat-uid-1", "createdAt": 1706014061, "conversationId": "group_cometchat-guid-1", "onlineMembersCount": 3 }, "entityType": "group" } }, }, "sentAt": 1707902030, "updatedAt": 1707902030 } } ``` The sender's name is accessible via `data.entities.sender.name`, so the placeholder for the sender's name will be `{{message.data.entities.sender.name}}`. This `placeholder` is substituted within the template with the actual name of the sender aka the `substitution value`. As an administrator, you can configure: 1. **Default templates** - Use these templates to display previews by leveraging the information contained in the event. 2. **Privacy templates** - Employ these templates to present generic content in the notification. ### Privacy setting #### Dashboard configuration Configure which template will be used for displaying the content of the notifications displayed on user's devices. The available preferences are: 1. Use default template - Enforces the use of default templates for all the users. 2. Use privacy template - Enforces the use of privacy templates for all the users. 3. **Use default templates with user privacy override (Default)** - Uses default templates by default, but allows the users to enable privacy to hide the previews. #### Client-side implementation **1. Fetch privacy setting** The method `CometChatNotifications.fetchPreferences()` retrieves the notification preferences saved by the user as an instance of `NotificationPreferences` class. If the user has not configured any preferences, the default preferences defined by the CometChat administrator via the dashboard will be utilized. ```js // This is applicable for web, React native, Ionic cordova const preferences = await CometChatNotifications.fetchPreferences(); // Display a toggle for use privacy option TODO const usePrivacyTemplate = preferences.getUsePrivacyTemplate(); ``` ```kotlin CometChatNotifications.fetchPreferences(new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Display a toggle for use privacy option boolean usePrivacyTemplate = notificationPreferences.getUsePrivacyTemplate(); } @Override public void onError(CometChatException e) { // Something went wrong while fetching notification preferences } }); ``` ```swift CometChatNotifications.fetchPreferences { notificationPreferences in // Display a toggle for use privacy option let usePrivacyTemplate = notificationPreferences.usePrivacyTemplate; } onError: { error in // Something went wrong while fetching notification preferences. print("fetchPreferences: \(error.errorCode) \(error.errorDescription)"); } ``` ```dart CometChatNotifications.fetchPreferences( onSuccess: (notificationPreferences) { // Display a toggle for use privacy option bool? usePrivacyTemplate = notificationPreferences.usePrivacyTemplate; }, onError: (e) { debugPrint("fetchPreferences:error ${e.toString()}"); }); ``` **2. Update privacy setting** `CometChatNotifications.updatePreferences()` method is used to update a user's notification preferences. The "**override**" toggle defined in the dashboard is crucial when updating preferences. If any preference is non-overridable, the method doesn't generate an error; it instead returns the `NotificationPreferences` object with the updated values where overrides are allowed. This functionality can be beneficial for temporarily superseding certain user preferences to ensure notifications for a specific event are delivered. Nonetheless, it is advisable to use this approach temporarily to avoid confusing users with unexpected changes to their notification settings. It is unnecessary to specify all values; only set and save the preferences that have been changed. ```js // This is applicable for web, React native, Ionic cordova // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. const updatedPreferences = new NotificationPreferences(); // To update the preference for privacy template updatedPreferences.setUsePrivacyTemplate(true); // Update the preferences and receive the udpated copy. const notificationPreferences = await CometChatNotifications.updatePreferences( updatedPreferences ); ``` ```kotlin // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. NotificationPreferences updatedPreferences = new NotificationPreferences(); // To update the preference for privacy template updatedPreferences.setUsePrivacyTemplate(true); // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, new CometChat.CallbackListener() { @Override public void onSuccess(NotificationPreferences notificationPreferences) { // Updated notificationPreferences } @Override public void onError(CometChatException e) { // Something went wrong } }); ``` ```swift // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences. let updatedPreferences = CometChatNotifications.NotificationPreferences(); // To update the preference for privacy template updatedPreferences.set(usePrivacyTemplate: true) // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences) { prefs in print("updatePreferences: \(prefs)") } onError: { error in print("updatePreferences: \(error.errorCode) \(error.errorDescription)") } ``` ```dart // The example demonstrates modifying all values; however, modifying only the changed values is sufficient. // Instantiate the NotificationPreferences NotificationPreferences updatedPreferences = NotificationPreferences(); // To update the preference for privacy template updatedPreferences.usePrivacyTemplate = true; // Update the preferences. CometChatNotifications.updatePreferences(updatedPreferences, onSuccess: (preferencesAfterUpdate) { debugPrint("updatePreferences:success"); // Use the preferencesAfterUpdate }, onError: (e) { debugPrint("updatePreferences:error: ${e.toString()}"); }); ``` ### Text message templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body | `{{message.data.text}}` | New message | ### Media message templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body for Image | 📷 Has sent an image | New image message | | Body for Audio | 🔈 Has sent an audio | New audio message | | Body for Audio | 🎥 Has sent a video | New video message | | Body for Audio | 📄 Has sent a file | New file message | ### Custom message templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body | `{{message.data.text}}` | `{{message.data.text}}` | | Body (Fallback) | New message | New message | **Note:** The "Body (Fallback)" value is utilized when any placeholders within the "Body" fail to resolve to an appropriate substitution value. **For example**, if `{{message.data.text}}` in the aforementioned scenario evaluates to `null` or `undefined`, the "Body (Fallback)" value will be utilized. Ideally, the "Body (Fallback)" value should not contain any placeholders to prevent additional resolution failures. ### Interactive form templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body | `{{data.interactiveData.title}}` | New message | ### Interactive card templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body | `{{data.interactiveData.title}}` | New message | ### Interactive scheduler templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body | New invite | New invite | ### Custom Interactive message templates | Template for | Default template values | Privacy template values | | ------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Title (One-on-one) | `{{message.data.entities.sender.entity.name}}` | `{{message.data.entities.sender.entity.name}}` | | Title (Group) | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | `{{message.data.entities.sender.entity.name}}` @ `{{message.data.entities.receiver.entity.name}}` | | Body | New message | New message | ### Sounds The sound files must be included within the app's bundle. These values are set within the notification payload as values of the "sound" field. **Sound for Call Notifications:** Specify the name of the sound file you wish to play for call notifications. **Sound for Chat Notifications:** Specify the name of the sound file you wish to play for chat notifications. ## Email notification templates You can use a default template or a privacy template in case you consider the information to be displayed as sensitive. The data available for email's subject template is as follows: ```json { "to": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Are we meeting on this weekend?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "📷 Has shared an image", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "senderDetails": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp" } } ``` ```json { "to": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Hello all! What's up?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "This is the place I was thinking about", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "groupDetails": { "guid": "cometchat-guid-1", "name": "Hiking Group", "icon": "https://assets.cometchat.io/sampleapp/v2/groups/cometchat-guid-1.webp" } } ``` Considering the above data, an email's subject can be formatted as follows: | Subject for | Template | Final subject | | ----------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | | Group notification | Hello `{{to.name}}`! You have `{{messages.length}}` message(s) in `{{groupDetails.name}}`. | Hello **Andrew Joseph**! You have **2** message(s) in **Hiking Group**. | | One-on-one notification | Hello `{{to.name}}`! You have `{{messages.length}}` message(s) from `{{senderDetails.name}}`. | Hello **Andrew Joseph**! You have **2** message(s) from **Susan Marie**. | ## SMS notification templates You can use a default template or a privacy template in case you consider the information to be displayed as sensitive. The data available for SMS template is as follows: ```json { "to": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Are we meeting on this weekend?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "📷 Has shared an image", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "senderDetails": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp" } } ``` ```json { "to": { "uid": "cometchat-uid-1", "name": "Andrew Joseph", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Hello all! What's up?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "This is the place I was thinking about", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "groupDetails": { "guid": "cometchat-guid-1", "name": "Hiking Group", "icon": "https://assets.cometchat.io/sampleapp/v2/groups/cometchat-guid-1.webp" } } ``` Considering the above data, an SMS can be formatted as follows: | SMS for | Template | Final content | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | | Group notification | You've received `{{messages.length}}` message(s) in `{{groupDetails.name}}`! Read them at [https://your-website.com](https://your-website.com). | You've received **2** message(s) in Hiking Group! Read them at [https://your-website.com](https://your-website.com). | | One-on-one notification | You've received `{{messages.length}}` message(s) from `{{senderDetails.name}}`! Read them at [https://your-website.com/chat](https://your-website.com/chat). | You've received **2** message(s) from **Susan Marie**! Read them at [https://your-website.com/chat](https://your-website.com/chat). | Replace [https://your-website.com/chat](https://your-website.com/chat) with the URL of your actual website. # Customizations Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/push-customization Customizations allow controlling notifications for message events, group events, and call events. Users can set preferences for incoming notifications based on notification schedules, Do Not Disturb (DND) mode, and the mute status of specific conversations. Additional customizations include modifications to notification templates and sounds. These options also ensure that user privacy is maintained while displaying notifications on the device. For more information, refer to [Preferences, Templates & Sounds](/notifications/preferences-templates-sounds) documentation. # Integration Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/push-integration ## Enable Push notifications 1. Login to [CometChat](https://app.cometchat.com/login) dashboard and select your app. 2. Navigate to **Notifications** > **Notifications** in the left-hand menu. 3. Enable the Push notifications feature. 4. Continue to configure Push notifications by clicking on "Configure". ## Add Providers Firebase Cloud Messaging (FCM) and Apple Push Notification Service (APNS) are the two primary supported providers for sending push notifications. ### Add FCM credentials #### Pre-requisite Generate a service account key for your Firebase application by navigating to the "Service accounts" section within the "Project settings" of the Firebase Cloud Messaging Dashboard. Generate new private key and download the JSON file. This will be required in the next steps. #### Add credentials 1. Select the "+ Add Credentials" button. 2. In the dialogue that appears, provide a unique, memorable identifier for your provider. 3. Upload the service account JSON file you previously acquired. 4. Specify whether the push payload should include the "notification" key. Additional information on this configuration is available in FCM's documentation - [About FCM messages](https://firebase.google.com/docs/cloud-messaging/concept-options). Similarly, you can add multiple FCM Credentials in case you have multiple FCM projects for your apps. ### Add APNS credentials #### Pre-requisite 1. To generate a .p8 key file, go to [Apple developer account](https://developer.apple.com/account), then select "Certificates, IDs & Profiles". 2. Select Keys and click on the "+" button to add a new key. 3. In the new key page, type in your key name and check the Apple Push Notification service (APNs) box, then click "Continue" and click "Register". 4. Then proceed to download the key file by clicking Download. 5. Make note of the Key ID, Team ID and your Bundle ID. These are required in the next steps. Additional information on this configuration is available in Apple's documentation - [Create a private key to access a service](https://developer.apple.com/help/account/manage-keys/create-a-private-key/) #### Add credentials 1. Select the "+ Add Credentials" button. 2. Enable the toggle if your app is in the Production. For apps under development, the toggle has to be disabled. 3. In the dialogue that appears, provide a unique, memorable identifier for your provider. 4. Store the Key ID, Team ID, Bundle ID for your app. 5. Upload the .p8 file 6. Enable "Include content-available" if you want to receive background notifications. However, this is not recommended as the background notifications are throttled. Additional information is available in Apple's documentation - [Pushing background updates to your App](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app) 7. Enable "Include mutable-content" if you want to modify the notification before it is displayed to the user. Additional information is available in Apple's documentation - [Modifying content on newly delivered notifications](https://developer.apple.com/documentation/usernotifications/modifying-content-in-newly-delivered-notifications) Similarly, you can add multiple APNS Credentials in case you have multiple apps with different Bundle IDs. ### Add Custom provider credentials Custom providers allow you to make use of providers apart from FCM and APNs. This is implemented using webhook URL which gets all the required details that can be used to trigger Push notifications. #### Pre-requisite 1. Your webhook endpoint must be accessible over `HTTPS`. This is essential to ensure the security and integrity of data transmission. 2. This URL should be publicly accessible from the internet. 3. Ensure that your endpoint supports the `HTTP POST` method. Event payloads will be delivered via `HTTP POST` requests in `JSON` format. 4. Configure your endpoint to respond immediately to the CometChat server with a 200 OK response. The response should be sent within 2 seconds of receiving the request. 5. For security, it is recommended to set up Basic Authentication that is usually used for server-to-server calls. This requires you to configure a username and password. Whenever your webhook URL is triggered, the HTTP Header will contain: ```html Authorization: Basic ``` 6. Your frontend application should implement the logic to get the push token and register it to your backend when the user logs in and unregister the push token when the user logs out. 7. To enable multi-device logins, you can map the push tokens to the user's auth tokens. Where each new login makes use of a new auth token. #### Add credentials 1. Click on the "+ Add Credentials" button. 2. Enable the provider. 3. Enter the publically accessible Webhook URL. 4. It is recommended to enable Basic Authentication. 5. Enter the username and password. 6. Save the credentials. #### How does it work? The Custom provider is triggered once for an event in one-on-one conversation. In case of notifying the members of a group, the custom provider is triggered once for each user present in that group. For example, if there are 100 members in the group, your webhook will receive 100 HTTP requests. Once for each member of the group. Below are the sample payloads for different events: ```json { "trigger": "push-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-2" }, "notificationDetails": { // Notification details "title": "Andrew Joseph", // The title of the notification to be displayed "body": "Hello!", // The body of the notification to be displayed // Sender's details "sender": "cometchat-uid-1", // UID of the user who sent the message. "senderName": "Andrew Joseph", // Name of the user who sent the message. "senderAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", // Avatar URL of the user. // Receiver's details "receiver": "cometchat-uid-2", // UID or GUID of the receiver. "receiverName": "George Alan", // Name of the user or group. "receiverAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", // Avatar URL of the receiver. "receiverType": "user", // Values can be "user" or "group" // Message details "tag": "123", // The ID of the message that can be used as the ID of the notification to be displayed. "conversationId": "cometchat-uid-1_user_cometchat-uid-2", // The ID of the conversation that the message belongs to. "type": "chat", "sentAt": "1741847453000", "message": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited or deleted. "custom": {Custom JSON} // Custom JSON object is added in case it is configured in the preferences. } }, "appId": "app123", "region": "us/eu/in", "webhook": "custom" } ``` ```json { "trigger": "push-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-2" }, "notificationDetails": { // Notification details "title": "Caller", // The title of the notification to be displayed "body": "AUDIO CALL", // "AUDIO CALL" or "VIDEO CALL" // Sender's details "sender": "cometchat-uid-1", // UID of the user who sent the message. "senderName": "Andrew Joseph", // Name of the user who sent the message. "senderAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", // Avatar URL of the user. // Receiver's details "receiver": "cometchat-uid-2", // UID or GUID of the receiver. "receiverName": "George Alan", // Name of the user or group. "receiverAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", // Avatar URL of the receiver. "receiverType": "user", // "user" or "group" // Message details "tag": "123", // The ID of the message that can be used as the ID of the notification to be displayed. "conversationId": "cometchat-uid-1_user_cometchat-uid-2", // The ID of the conversation that the call belongs to. "type": "call", // Call details "callAction": "initiated", // "initiated" or "cancelled" or "unanswered" or "ongoing" or "rejected" or "ended" or "busy" "sessionId": "v1.123.aik2", // The unique sessionId of the call that can be used as an identifier in CallKit or ConnectionService. "callType": "audio", // "audio" or "video" "sentAt": "1741847453000", "custom": {Custom JSON} // Custom JSON object is added in case it is configured in the preferences. } }, "appId": "app123", "region": "us/eu/in", "webhook": "custom" } ``` ```json { "trigger": "push-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-2" }, "notificationDetails": { // Notification details "title": "Andrew Joseph", "body": "Reacted to your message: 😎", // Sender's details "sender": "cometchat-uid-1", "senderName": "Andrew Joseph", "senderAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", // Receiver's details "receiver": "cometchat-uid-1", "receiverName": "Andrew Joseph", "receiverAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", "receiverType": "user", // Message details "tag": "58", "conversationId": "cometchat-uid-1_user_cometchat-uid-2", "type": "chat", "sentAt": "1741847453000", "custom": {Custom JSON} // Custom JSON object is added in case it is configured in the preferences. } }, "appId": "app123", "region": "us", "webhook": "custom" } ``` ```json { "trigger": "push-notification-payload-generated", "data": { "to": { "uid": "g-messages-none" }, "notificationDetails": { // Notification details "title": "Hiking group", "body": "Andrew Joseph has left", // Similarly for joined, kicked, banned, unbanned, added events // Sender details "sender": "cometchat-uid-1", "senderName": "Andrew Joseph", "senderAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", // Receiver details "receiver": "cometchat-guid-1", "receiverName": "Hiking group", "receiverType": "group", // Message details "tag": "cometchat-guid-1", "conversationId": "group_cometchat-guid-1", "type": "chat", "sentAt": "1741847453000", "custom": {Custom JSON} // Custom JSON object is added in case it is configured in the preferences. } }, "appId": "app123", "region": "us", "webhook": "custom" } ``` #### Sample server-side code ```typescript const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; app.use(express.json()); // Optional: Basic authentication middleware const basicAuth = (req, res, next) => { const authHeader = req.headers['authorization']; if (!authHeader || !authHeader.startsWith('Basic ')) { return res.status(401).json({ message: 'Unauthorized' }); } next(); }; const triggerPushNotification = async (to, notificationDetails) => { const { name, uid } = to; const { type, notificationTitle, notificationBody } = notificationDetails; if (type == 'call') { console.log('Push notification for calling event'); // Use the following details to send a call notification. const { callAction, sessionId, callType } = notificationDetails; } if (type == 'chat') { console.log('Push notification for messaging event'); } const token = await fetchPushToken(uid); // Your implementation for sending the Push notification await sendPushNotification(token, notificationTitle, notificationBody); }; app.post('/webhook', basicAuth, (req, res) => { const { trigger, data, appId, region, webhook } = req.body; if ( trigger !== 'push-notification-payload-generated' || webhook !== 'custom' ) { return res.status(400).json({ message: 'Invalid trigger or webhook type' }); } console.log('Received Webhook:', JSON.stringify(req.body, null, 2)); triggerPushNotification(to, data) .then((result) => { console.log( 'Successfully triggered Push notification for', appId, to.uid, result ); }) .catch((error) => { console.error( 'Something went wrong while triggering Push notification for', appId, to.uid, error.message ); }); res.status(200).json({ message: 'Webhook received successfully' }); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); ``` ## Tokens management ### Register push token after login Push tokens, obtained from the APIs or SDKs provided by the platforms or frameworks in use, must be registered on behalf of the logged in user with the CometChat backend. For this purpose, CometChat SDKs v4+ offer the following functions: Push token registration should be completed in two scenarios: 1. Following the success of `CometChat.login()` & receiving user's permission to receiver Push notifications. 2. When a refresh token becomes available. To register a token, use the `CometChatNotifications.registerPushToken()` method from the SDK. This method accepts the following parameters. | Parameter | Type | Description | | ------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `pushToken` | String | The `pushToken` can contain:

• Firebase (FCM) token
• Device token (iOS only)
• VoIP token (iOS only) | | `platform` | String | The `platform` can take the following values:

• PushPlatforms.FCM\_ANDROID
• PushPlatforms.FCM\_FLUTTER\_ANDROID
• PushPlatforms.FCM\_FLUTTER\_iOS
• PushPlatforms.APNS\_FLUTTER\_DEVICE
• PushPlatforms.APNS\_FLUTTER\_VOIP
• PushPlatforms.FCM\_iOS
• PushPlatforms.APNS\_iOS\_DEVICE
• PushPlatforms.APNS\_iOS\_VOIP
• PushPlatforms.FCM\_WEB
• PushPlatforms.FCM\_REACT\_NATIVE\_ANDROID
• PushPlatforms.FCM\_REACT\_NATIVE\_iOS
• PushPlatforms.APNS\_REACT\_NATIVE\_DEVICE
• PushPlatforms.APNS\_REACT\_NATIVE\_VOIP
• PushPlatforms.FCM\_IONIC\_CORDOVA\_ANDROID
• PushPlatforms.FCM\_IONIC\_CORDOVA\_iOS
• PushPlatforms.APNS\_IONIC\_CORDOVA\_DEVICE
• PushPlatforms.APNS\_IONIC\_CORDOVA\_VOIP | | `providerId` | String | The `providerId` should match with:

• Any one of the FCM provider identifiers in case of an FCM token.
• Any one of the APNS provider identifiers in case of Device or VoIP tokens. | ```js // This is applicable for web, React native, Ionic cordova // CometChat.init() success. // CometChat.login() success. // User has granted permission to display push notifications. // For web CometChatNotifications.registerPushToken( pushToken, CometChatNotifications.PushPlatforms.FCM_WEB, "fcm-provider-2" ) .then((payload) => { console.log("Token registration successful"); }) .catch((err) => { console.log("Token registration failed:", err); }); // For React Native Android CometChatNotifications.registerPushToken( pushToken, CometChatNotifications.PushPlatforms.FCM_REACT_NATIVE_ANDROID, "fcm-provider-2" ) .then((payload) => { console.log("Token registration successful"); }) .catch((err) => { console.log("Token registration failed:", err); }); // For React Native iOS CometChatNotifications.registerPushToken( pushToken, CometChatNotifications.PushPlatforms.FCM_REACT_NATIVE_iOS, "fcm-provider-2" ) .then((payload) => { console.log("Token registration successful"); }) .catch((err) => { console.log("Token registration failed:", err); }); // For Ionic cordova Android CometChatNotifications.registerPushToken( pushToken, CometChatNotifications.PushPlatforms.FCM_IONIC_CORDOVA_ANDROID, "fcm-provider-2" ) .then((payload) => { console.log("Token registration successful"); }) .catch((err) => { console.log("Token registration failed:", err); }); // For Ionic cordova iOS CometChatNotifications.registerPushToken( pushToken, CometChatNotifications.PushPlatforms.FCM_IONIC_CORDOVA_iOS, "fcm-provider-2" ) .then((payload) => { console.log("Token registration successful"); }) .catch((err) => { console.log("Token registration failed:", err); }); // Similary, use this method to register refresh token. ``` ```kotlin // CometChat.init() success. // CometChat.login() success. // User has granted permission to display push notifications. CometChatNotifications.registerPushToken(pushToken, PushPlatforms.FCM_ANDROID, "fcm-provider-2", new CometChat.CallbackListener() { @Override public void onSuccess(String s) { Log.e(TAG, "onSuccess: CometChat Notification Registered : "+s ); listener.onSuccess(s); } @Override public void onError(CometChatException e) { Log.e(TAG, "onError: Notification Registration Failed : "+e.getMessage()); listener.onError(e); } }); // Similary, use this method to register refresh token. ``` ```swift // CometChat.init() success. // CometChat.login() success. // User has granted permission to display push notifications. CometChatNotifications.registerPushToken(pushToken: pushToken, platform: CometChatNotifications.PushPlatforms.FCM_iOS, providerId: "apns-provider-2", onSuccess: { (success) in print("registerPushToken: \(success)") }) { (error) in print("registerPushToken: \(error.errorCode) \(error.errorDescription)") } // Similary, use this method to register refresh token. ``` ```dart // CometChat.init() success. // CometChat.login() success. // User has granted permission to display push notifications. // For Android (FCM) CometChatNotifications.registerPushToken( PushPlatforms.FCM_FLUTTER_ANDROID, providerId: "fcm-provider-1", fcmToken: token, onSuccess: (response) { debugPrint("registerPushToken:success ${response.toString()}"); }, onError: (e) { debugPrint("registerPushToken:error ${e.toString()}"); }, ); // For iOS (FCM) CometChatNotifications.registerPushToken( PushPlatforms.FCM_FLUTTER_iOS, providerId: "fcm-provider-1", fcmToken: token, onSuccess: (response) { debugPrint("registerPushToken:success ${response.toString()}"); }, onError: (e) { debugPrint("registerPushToken:error ${e.toString()}"); }, ); // For ios (APNS Device token) CometChatNotifications.registerPushToken( PushPlatforms.APNS_FLUTTER_DEVICE, providerId: "apns-provider-1", deviceToken: token, onSuccess: (response) { debugPrint("registerPushToken:success ${response.toString()}"); }, onError: (e) { debugPrint("registerPushToken:error ${e.toString()}"); }, ); // For ios (APNS VoIP token) CometChatNotifications.registerPushToken( PushPlatforms.APNS_FLUTTER_VOIP, providerId: "apns-provider-1", voipToken: token, onSuccess: (response) { debugPrint("registerPushToken:success ${response.toString()}"); }, onError: (e) { debugPrint("registerPushToken:error ${e.toString()}"); }, ); // Similary, use this method to register refresh token. ``` ### Unregister push token before logout Typically, push token unregistration should occur prior to user logout, using the `CometChat.logout()` method. For token unregistration, use the `CometChatNotifications.unregisterPushToken()` method provided by the SDKs. ```js // This is applicable for web, React native, Ionic cordova await CometChatNotifications.unregisterPushToken(); // Followed by CometChat.logout(); ``` ```kotlin CometChatNotifications.unregisterPushToken(new CometChat.CallbackListener() { @Override public void onSuccess(String s) { // Success callback } @Override public void onError(CometChatException e) { // Error callback } }); // Followed by CometChat.logout(); ``` ```swift CometChatNotifications.unregisterPushToken { success in print("unregisterPushToken: \(success)") } onError: { error in print("unregisterPushToken: \(error.errorCode) \(error.errorDescription)") } // Followed by CometChat.logout(); ``` ```dart CometChatNotifications.unregisterPushToken(onSuccess: (response) { debugPrint("unregisterPushToken:success ${response.toString()}"); }, onError: (e) { debugPrint("unregisterPushToken:error ${e.toString()}"); }); ``` ## Handle incoming Push notifications Push notifications should be managed primarily when the app is in the background or in a terminated state. For web and mobile applications, the Firebase Cloud Messaging (FCM) SDK offers handler functions to receive Push Notifications. For iOS applications, the FCM SDK can be used as described previously, or alternatively, PushKit can be implemented for better integration and management of chat and call (VoIP) notifications. The push payload delivered to the user's device includes the following information, which can be customized to suit the desired notification style: ```json { // Notification details "title": "Andrew Joseph", // The title of the notification to be displayed "body": "Hello!", // The body of the notification to be displayed // Sender's details "sender": "cometchat-uid-1", // UID of the user who sent the said message. "senderName": "Andrew Joseph", // Name of the user who sent the said message. "senderAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-1.webp", // Avatar URL of the user. // Receiver's details "receiver": "cometchat-uid-2", // UID or GUID of the receiver. "receiverName": "George Alan", // Name of the user or group. "receiverAvatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-2.webp", // Avatar URL of the receiver. "receiverType": "user", // Values can be "user" or "group" // Message details "tag": "123", // The ID of the said message that can be used as the ID of the notification to be displayed. "conversationId": "cometchat-uid-1_user_cometchat-uid-2", // The ID of the conversation that the said message belongs to. "type": "chat", // Values can be "call" or "chat". If this is "call", the below details will be available. // Call details "callAction": "initiated", // Values can be "initiated" or "cancelled" or "unanswered" or "ongoing" or "rejected" or "ended" or "busy" "sessionId": "v1.123.aik2", // The unique sessionId of the said call that can be used as unique identifier in CallKit or ConnectionService. "callType": "audio", // Values can be "audio" or "video" "sentAt": "1741847453000", "message": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited or deleted. "custom": {Custom JSON} // Custom JSON object is added in case it is configured in the preferences. } ``` ## Sample apps Check out our sample apps for understanding the implementation. Push notifications sample app for the web View on Github Push notifications sample app for React Native View on Github Push notifications sample app for iOS View on Github Push notifications sample app for Android View on Github Push notifications sample app for Flutter View on Github # Push Notification Extension (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/push-notification-extension-overview **Legacy Notice**: This extension is already included as part of the core messaging experience and is scheduled for deprecation in the near future. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. Learn how to send push notifications to mobile apps and desktop browsers. Push notifications will work in iOS and Android apps as well as desktop browsers that support [Push API](https://caniuse.com/#feat=push-api). These browsers include: 1. Chrome 50+ 2. Firefox 44+ 3. Edge 17+ 4. Opera 42+ ## Migration Guide 1. If you are already using the Legacy (Topic-based) Push Notifications, you can check out our [Two-step migration guide](/notifications/migration-guide-push-notifications). ## Implementation 1. If you are new and want to implement Token-based Push Notifications in your app, follow our platform-specific guides: 1. [JavaScript](/notifications/web-push-notifications) (Web) 2. [Android](/notifications/android-push-notifications) 3. [iOS](/notifications/ios-fcm-push-notifications) 4. [Flutter](/notifications/flutter-push-notifications) 5. [React Native](/notifications/react-native-push-notifications) 6. [Capacitor, Cordova & Ionic](/notifications/capacitor-cordova-ionic-push-notifications) 2. For Android and iOS we also have setup that allows the usage of Native calling screens: 1. [Android - Connection Service](/notifications/android-connection-service) 2. [iOS - APNs](/notifications/ios-apns-push-notifications) 3. [Token management](/notifications/token-management) to manage FCM and APNs tokens for the logged-in user. 4. [Mute functionality](/notifications/mute-functionality) to mute certain conversations or implement DND. # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/push-overview ## Introduction Push notifications are a crucial aspect of modern applications, providing real-time updates and enhancing user engagement. CometChat's Push Notification service offers a range of features and customization options to enable businesses to deliver timely alerts and keep users connected to their applications. ## Key Features 1. **Support for multiple providers**: CometChat provides support for **Firebase Cloud Messaging (FCM)** and **Apple Push Notification Service (APNS)**. This approach, involving multiple providers, provides flexibility in notification delivery, independent of the recipient's platform. It also enables CometChat to respond effectively to the evolving push notification landscape, maintaining consistent delivery across Android, iOS, and web platforms. 2. **Support for multiple platforms**: CometChat provides multi-platform support, compatible with an extensive array of mobile and web platforms. This includes native mobile platforms such as Android and iOS, web frameworks like React, Angular, and Vue.js, and hybrid environments including React Native and Flutter. 3. **Tokens management**: CometChat's Push Notification service provides developers with functions and APIs for easy tokens management, ensuring that push notifications are delivered reliably to intended user's devices. 4. **Preferences management**: Through CometChat's Notification Preferences, users and admins have the ability to customize the notification settings, that help provide pertinent alerts while avoiding notification fatigue. 5. **Ability to set up a schedule**: CometChat's Push notifications service ensures that the notifications are delivered based on the specified daily timetable, adhering to the user's local time zone. 6. **Ability to mute notifications**: Users have the option to completely mute push notifications for the app (DND mode), or selectively mute them for specific users and groups, for a designated duration. 7. **Ability to set up Templates and Sounds**: CometChat offers developers a set of pre-defined templates that define the content shown in push notifications. These templates act as a blueprint for customizing the payload content sent with push notifications as per the needs and requirements. *** ## Triggering Events In CometChat various user actions and interactions within the chat environment can trigger push notifications to ensure users stay updated and engaged. Here are some common events that typically trigger push notifications: * **New Messages**: Whenever a user sends a new message in a one-on-one or group chat, CometChat can trigger a push notification to alert other participants about the incoming message. * **Replies**: When a user replies to a specific message within a chat, it can trigger a push notification to notify relevant users about the reply, ensuring they are aware of the ongoing conversation. * **Message Edited or Deleted**: Notifications are triggered when a user edits or deletes a message, informing relevant users about the changes made to the message content. * **Mentions**: If a user is mentioned by another user using their username or handle in a message, CometChat can trigger a push notification to notify the mentioned user about the mention, prompting their attention to the message. * **Reactions**: Users can react to messages with emojis or symbols. When a user reacts to a message, CometChat can trigger a push notification to the original sender or other participants in the chat to notify them about the reaction. * **Group Actions**: Notifications are triggered for group actions such as member joins, member bans, and member leaves, ensuring group members are informed about changes in group dynamics. * **Calling Events**: CometChat supports real-time audio and video calling features. Events related to incoming calls, missed calls or call invitations can trigger push notifications to alert users about these calling events, ensuring they don't miss important calls. # React Native Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/react-native-push-notifications Learn how to set up Push notifications for React Native using Firebase Cloud Messaging or FCM. React Native Push notifications sample app View on Github ## Firebase Project Setup Visit [Firebase](https://console.firebase.google.com/) and login/signup using your Gmail ID. ### Step 1: Create a new Firebase Project Head over to the [Firebase Console](https://console.firebase.google.com/) to create a new project. This is a simple 3 step process where: 1. You give a name to your project 2. Add Google Analytics to your project (Optional) 3. Configure Google Analytics account (Optional) Click on Create and you are ready to go. ### Step 2: Add Firebase to your App React native setup will require 2 files for Android and iOS: 1. For Android, you need to download the google-services.json file from the Firebase console. 2. For iOS, you need to download the GoogleService-Info.plist file from the Firebase console. ### Step 3: Download the service account file ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open up the settings and save the following settings. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** * If you are setting it for the first time, Select `V2` to start using the token-based version of the Push Notification extension. * If you already have an app using `V1` and want to migrate your app to use `V2`, then Select `V1 & V2` option. This ensures that the users viewing the older version of your app also receive Push Notifications. * Eventually, when all your users are on the latest version of your app, you can change this option to `V2`, thus turning off `V1` (Topic-based) Push Notifications completely. 2. **Select the platforms that you want to support** * Select from Web, Android, Ionic, React Native, Flutter & iOS. 3. **Notification payload settings** * You can control if the notification key should be in the Payload or not. Learn more about the FCM Messages [here](https://firebase.google.com/docs/cloud-messaging/concept-options). 4. **Push payload message options** The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** * Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications * These are pretty self-explanatory and you can toggle them as per your requirement. ## App Setup ### Step 1: Initial plugin setup 1. For React Native, there are numerous plugins available via NPM which can be used to set up push notifications for your apps. [react-native-firebase](https://www.npmjs.com/package/react-native-firebase) and [react-native-notifications](https://www.npmjs.com/package/react-native-notifications) are just the two out of many available. 2. To setup Push Notification, you need to follow the steps mentioned in the Plugin's Documentation. At this point, you will have: 1. Two separate apps created on the Firebase console. (For Android and iOS). 2. Plugin setup completed as per the respective documentation and our reference. ### Step 2: Register FCM Token 1. This step assumes that you already have a React Native app setup with CometChat installed. Make sure that the CometChat object is initialized and user has been logged in. 2. On the success callback of user login, you can fetch the FCM Token and register it with the extension as shown below: ```js // Pseudo-code with async-await syntax const APP_ID = 'APP_ID'; const REGION = 'REGION'; const AUTH_KEY = 'AUTH_KEY'; const UID = 'UID'; const APP_SETTINGS = new CometChat.AppSettingsBuilder() .subscribePresenceForAllUsers() .setRegion(REGION) .build(); try { // First initialize the app await CometChat.init(APP_ID, APP_SETTINGS); // Login the user await CometChat.login(UID, AUTH_KEY); // Get the FCM device token // You should have imported the following in the file: // import messaging from '@react-native-firebase/messaging'; const FCM_TOKEN = await messaging().getToken(); // Register the token with Push Notifications (Legacy) await CometChat.registerTokenForPushNotification(FCM_TOKEN); } catch (error) { // Handle errors gracefully } ``` 3. Registration also needs to happen in case of token refresh as shown below: ```js // Pseudo-code // You should have imported the following in the file: // import messaging from '@react-native-firebase/messaging'; try { // Listen to whether the token changes return messaging().onTokenRefresh(FCM_TOKEN => { await CometChat.registerTokenForPushNotification(FCM_TOKEN); }); // ... } catch(error) { // Handle errors gracefully } ``` For React Native Firebase reference, visit the link below: ### Step 3: Receive Notifications ```js // Pseudo-code import messaging from '@react-native-firebase/messaging'; import { Alert } from 'react-native'; // Implementation can be done in a life-cycle method or hook const unsubscribe = messaging().onMessage(async (remoteMessage) => { Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage)); }); ``` We send Data Notifications and you need to handle displaying notifications at your end. For eg: Using Notifee ### Step 4: Stop receiving Notifications 1. Simply logout the CometChat user and you will stop receiving notifications. 2. As a good practice, you can also delete the FCM Token by calling `deleteToken` on the messaging object. ```js // Pseudo-code using async-await syntax logout = async () => { // User logs out of the app await CometChat.logout(); // You should have imported the following in the file: // import messaging from '@react-native-firebase/messaging'; // This is a good practice. await messaging().deleteToken(); }; ``` ## Advanced ### Handle Custom Messages To receive notification of `CustomMessage`, you need to set metadata while sending the `CustomMessage`. ```js var receiverID = 'UID'; var customData = { latitude: '50.6192171633316', longitude: '-72.68182268750002', }; var customType = 'location'; var receiverType = CometChat.RECEIVER_TYPE.USER; var metadata = { pushNotification: 'Your Notification Message', }; var customMessage = new CometChat.CustomMessage( receiverID, receiverType, customType, customData ); customMessage.setMetadata(metadata); CometChat.sendCustomMessage(customMessage).then( (message) => { // Message sent successfully. console.log('custom message sent successfully', message); }, (error) => { console.log('custom message sending failed with error', error); // Handle exception. } ); ``` ### Converting push notification payload to message object CometChat SDK provides a method `CometChat.CometChatHelper.processMessage()` to convert the message JSON to the corresponding object of TextMessage, MediaMessage,CustomMessage, Action or Call. ```js var processedMessage = CometChat.CometChatHelper.processMessage(JSON_MESSAGE); ``` Type of Attachment can be of the following the type\ 1.`CometChatConstants.MESSAGE_TYPE_IMAGE`\ 2.`CometChatConstants.MESSAGE_TYPE_VIDEO`\ 3.`CometChatConstants.MESSAGE_TYPE_AUDIO`\ 4.`CometChatConstants.MESSAGE_TYPE_FILE` Push Notification: Payload Sample for Text Message and Attachment/Media Message ```json { "alert": "Nancy Grace: Text Message", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "text": "Text Message" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "142", "sentAt": 1555668711, "category": "message", "type": "text" } } ``` ```json { "alert": "Nancy Grace: has sent an image", "sound": "default", "title": "CometChat", "message": { "receiver": "cometchat-uid-4", "data": { "attachments": [ { "extension": "png", "size": 14327, "name": "extension_leftpanel.png", "mimeType": "image/png", "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" } ], "entities": { "receiver": { "entityType": "user", "entity": { "uid": "cometchat-uid-4", "role": "default", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "status": "offline" } }, "sender": { "entityType": "user", "entity": { "uid": "cometchat-uid-3", "role": "default", "name": "Nancy Grace", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-3.webp", "status": "offline" } } }, "url": "https://s3-eu-west-1.amazonaws.com/data.cometchat.com/1255466c41bd7f/media/1555671238_956450103_extension_leftpanel.png" }, "sender": "cometchat-uid-3", "receiverType": "user", "id": "145", "sentAt": 1555671238, "category": "message", "type": "image" } } ``` ### Integrating ConnectionService and CallKit Using CometChat Push Notification * Currently we can only handle default calling notification * Whenever the user answers the call we use RNCallKeep.backToForeground(); method to bring the app in to foreground but in some devices you might need to add few more permissions for this to work For example, In MIUI 11 you need to permission for Display pop-up windows while running in the background * When the iOS app is in lock state we are not able to open the app so the call start on callkeep it self and you can hear the audio but if you want a video call then the user has to unlock the phone click on the app icon on call screen. * If you want to use the callkit and connection service in foreground then you might consider turning the callNotifications settings in UI kit settings. For more information in UI kit settings check the [documentation](/ui-kit/react-native/getting-started#initialise-cometchatuikit). #### Setup push notification * Android Kindly follow the instruction for setting Firebase Cloud Messaging explained [here](/notifications/react-native-push-notifications) * iOS For iOS we use Apple Push Notification service or APNs to send push notification and VOIP notification. To configure this we need to follow some additional steps #### Step 1: Create a Certificate Signing Request To obtain a signing certificate required to sign apps for installation on iOS devices, you should first create a certificate signing request (CSR) file through Keychain Access on your Mac. 1. Open the Keychain Access from the utility folder, go to Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority, and then click. 2. The Certificate Information dialog box appears. Enter the email address that you use in your Apple Developer account, and enter a common name for your private key. Don't enter CA email address, choose Saved to disk, and then click the Continue button. \ \
\
3. Specify the name of your CSR to save and choose the location to save the file on your local disk. Then your CSR file is created, which contains a public/private key pair. #### Step 2: Create an SSL certificate 1. Sign in to your account at the [Apple Developer Member Center](https://developer.apple.com/membercenter). 2. Go to Certificates, Identifiers & Profiles. 3. Create new Certificate by clicking on the + icon. 4. Under Services, select - Apple Push Notification services SSL (Sandbox & Production) 5. Select your App ID from the dropdown. 6. Upload CSR file., upload the CSR file you created through the **Choose File** button. To complete the process, choose Continue. When the certificate is ready, choose Download to save it to your Mac. #### Step 3: Export and update .p8 certificate 1. To generate a .p8 key file, go to [Apple developer account page](https://developer.apple.com/account/), then select Certificates, IDs & Profiles. 2. Select Keys and click on the "+" button to add a new key. 3. In the new key page, type in your key name and check the Apple Push Notification service (APNs) box, then click "Continue" and click "Register". 4. Then proceed to download the key file by clicking Download. 5. Make note of the `Key ID`, `Team ID` and your `Bundle ID` for saving in the Extension's settings. **If you wish to use the .p12 certificate instead, do the following:** 1. Type a name for the .p12 file and save it to your Mac. 2. Browse to the location where you saved your key, select it, and click Open. Add the key ID for the key (available in Certificates, Identifiers & Profiles in the Apple Developer Member Center) and export it. 3. DO NOT provide an export password when prompted. 4. The .p12 file will be required in the next step for uploading in the CometChat Dashboard. #### Extension settings #### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for this extension and save the following. #### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** The extension version has to be set to 'V2' or 'V1 & V2' in order to use APNs as the provider. 2. **Select Platforms** You can select the platforms on which you wish to receive Push Notifications. 3. **Firebase Cloud Messaging Settings** This includes the FCM Server key that you can fetch from the Firebase Dashboard. 4. **APNs Settings** You can turn off the Production mode when you create a development build of your application. Upload the .p12 certificate exported in the previous step. 5. **Push Notifications Title** This is usually the name of your app. 6. **Notification Triggers** Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications These are pretty self-explanatory and you can toggle them as per your requirement. #### Installation We need to add two packages for this * React-native-CallKeep This package also require some additional installation steps. Follow [this](https://github.com/react-native-webrtc/react-native-callkeep) link to install react-native-callkeep ```sh npm install react-native-callkeep //or yarn add react-native-callkeep ``` * React Native VoIP Push Notification This package also require some additional installation steps. Follow [this](https://github.com/react-native-webrtc/react-native-voip-push-notification#readme) link to install react-native-voip-push-notification. ```sh npm install react-native-voip-push-notification # --- if using pod cd ios/ && pod install ``` #### App Setup First you need to Setup CallKeep at the start of the app in Index.js ```js const options = { ios: { appName: 'My app name', }, android: { alertTitle: 'Permissions required', alertDescription: 'This application needs to access your phone accounts', cancelButton: 'Cancel', okButton: 'ok', imageName: 'phone_account_icon', foregroundService: { channelId: 'com.company.my', channelName: 'Foreground service for my app', notificationTitle: 'My app is running on background', notificationIcon: 'Path to the resource icon of the notification', }, }, }; RNCallKeep.setup(options); RNCallKeep.setAvailable(true); let callKeep = new CallKeepHelper(); ``` In order to handle connectionService and CallKit we have made a helper call. ```js import { CometChat } from '@cometchat/chat-sdk-react-native'; import { Platform } from 'react-native'; import uuid from 'react-native-uuid'; import RNCallKeep, { AnswerCallPayload } from 'react-native-callkeep'; import { navigate } from '../StackNavigator'; import messaging from '@react-native-firebase/messaging'; import VoipPushNotification from 'react-native-voip-push-notification'; import invokeApp from 'react-native-invoke-app'; import KeepAwake from 'react-native-keep-awake'; import { AppState } from 'react-native'; import _BackgroundTimer from 'react-native-background-timer'; export default class CallKeepHelper { constructor(msg) { if (msg) { CallKeepHelper.msg = msg; } this.setupEventListeners(); this.registerToken(); this.checkLoggedInUser(); this.addLoginListener(); CallKeepHelper.callEndedBySelf = false; } static FCMToken = null; static voipToken = null; static msg = null; static callEndedBySelf = null; static callerId = ''; static callerId1 = ''; static isLoggedIn = false; checkLoggedInUser = async () => { try { let user = await CometChat.getLoggedinUser(); if (user) { if (user) { CallKeepHelper.isLoggedIn = true; } } } catch (error) { console.log('error checkLoggedInUser', error); } }; addLoginListener = () => { var listenerID = 'UNIQUE_LISTENER_ID'; CometChat.addLoginListener( listenerID, new CometChat.LoginListener({ loginSuccess: (e) => { CallKeepHelper.isLoggedIn = true; this.registerTokenToCometChat(); }, }) ); }; registerTokenToCometChat = async () => { if (!CallKeepHelper.isLoggedIn) { return false; } try { if (Platform.OS == 'android') { if (CallKeepHelper.FCMToken) { let response = await CometChat.registerTokenForPushNotification( CallKeepHelper.FCMToken ); } } else { if (CallKeepHelper.FCMToken) { let response = await CometChat.registerTokenForPushNotification( CallKeepHelper.FCMToken, { voip: false } ); } if (CallKeepHelper.voipToken) { let response = await CometChat.registerTokenForPushNotification( CallKeepHelper.voipToken, { voip: true } ); } } } catch (error) {} }; registerToken = async () => { try { const authStatus = await messaging().requestPermission(); const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED || authStatus === messaging.AuthorizationStatus.PROVISIONAL; if (enabled) { if (Platform.OS == 'android') { let FCM = await messaging().getToken(); CallKeepHelper.FCMToken = FCM; this.registerTokenToCometChat(); } else { VoipPushNotification.registerVoipToken(); let FCM = await messaging().getAPNSToken(); CallKeepHelper.FCMToken = FCM; this.registerTokenToCometChat(); } } } catch (error) {} }; endCall = ({ callUUID }) => { if (CallKeepHelper.callerId) RNCallKeep.endCall(CallKeepHelper.callerId); _BackgroundTimer.start(); setTimeout(() => { this.rejectCall(); }, 3000); }; rejectCall = async () => { if ( !CallKeepHelper.callEndedBySelf && CallKeepHelper.msg && CallKeepHelper.msg.call?.category !== 'custom' ) { var sessionID = CallKeepHelper.msg.sessionId; var status = CometChat.CALL_STATUS.REJECTED; let call = await CometChat.rejectCall(sessionID, status); _BackgroundTimer.stop(); } else { _BackgroundTimer.stop(); } }; static displayCallAndroid = () => { this.IsRinging = true; CallKeepHelper.callerId = CallKeepHelper.msg.conversationId; RNCallKeep.displayIncomingCall( CallKeepHelper.msg.conversationId, CallKeepHelper.msg.sender.name, CallKeepHelper.msg.sender.name, 'generic' ); setTimeout(() => { if (this.IsRinging) { this.IsRinging = false; RNCallKeep.reportEndCallWithUUID(CallKeepHelper.callerId, 6); } }, 15000); }; // NOTE: YOU MIGHT HAVE TO MAKE SOME CHANGES OVER HERE AS YOU AS YOUR IMPLEMENTATION OF REACT-NATIVE-UI-KIT MIGHT BE DIFFERENT. YOU JUST NEED TO CALL THE ACCEPT CALL METHOD AND NAVIGATE TO CALL SCREEN. answerCall = ({ callUUID }) => { this.IsRinging = false; CallKeepHelper.callEndedBySelf = true; setTimeout( () => navigate({ index: 0, routes: [ { name: 'Conversation', params: { call: CallKeepHelper.msg } }, ], }), 2000 ); // RNCallKeep.endAllCalls(); RNCallKeep.backToForeground(); if (Platform.OS == 'ios') { if (AppState.currentState == 'active') { RNCallKeep.endAllCalls(); _BackgroundTimer.stop(); } else { this.addAppStateListener(); } } else { RNCallKeep.endAllCalls(); _BackgroundTimer.stop(); } }; addAppStateListener = () => { AppState.addEventListener('change', (newState) => { if (newState == 'active') { RNCallKeep.endAllCalls(); _BackgroundTimer.stop(); } }); }; didDisplayIncomingCall = (DidDisplayIncomingCallArgs) => { if (DidDisplayIncomingCallArgs.callUUID) { if (Platform.OS == 'ios') { CallKeepHelper.callerId = DidDisplayIncomingCallArgs.callUUID; } } if (DidDisplayIncomingCallArgs.error) { console.log({ message: `Callkeep didDisplayIncomingCall error: ${DidDisplayIncomingCallArgs.error}`, }); } this.IsRinging = true; setTimeout(() => { if (this.IsRinging) { this.IsRinging = false; // 6 = MissedCall // https://github.com/react-native-webrtc/react-native-callkeep#constants RNCallKeep.reportEndCallWithUUID( DidDisplayIncomingCallArgs.callUUID, 6 ); } }, 15000); }; setupEventListeners() { if (Platform.OS == 'ios') { CometChat.addCallListener( 'this.callListenerId', new CometChat.CallListener({ onIncomingCallCancelled: (call) => { RNCallKeep.endAllCalls(); }, }) ); RNCallKeep.addEventListener('didLoadWithEvents', (event) => { for (let i = 0; i < event.length; i++) { if (event[i]?.name == 'RNCallKeepDidDisplayIncomingCall') { CallKeepHelper.callerId = event[i]?.data?.callUUID; } } }); VoipPushNotification.addEventListener('register', async (token) => { CallKeepHelper.voipToken = token; this.registerTokenToCometChat(); }); VoipPushNotification.addEventListener('notification', (notification) => { let msg = CometChat.CometChatHelper.processMessage( notification.message ); CallKeepHelper.msg = msg; }); VoipPushNotification.addEventListener( 'didLoadWithEvents', async (events) => { if (!events || !Array.isArray(events) || events.length < 1) { return; } for (let voipPushEvent of events) { let { name, data } = voipPushEvent; if ( name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent ) { CallKeepHelper.voipToken = data; } else if ( name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent ) { let msg = CometChat.CometChatHelper.processMessage(data.message); CallKeepHelper.msg = msg; } } } ); } RNCallKeep.addEventListener('endCall', this.endCall); RNCallKeep.addEventListener('answerCall', this.answerCall); } removeEventListeners() { RNCallKeep.removeEventListener('endCall'); RNCallKeep.removeEventListener('didDisplayIncomingCall'); RNCallKeep.removeEventListener('didLoadWithEvents'); VoipPushNotification.removeEventListener('didLoadWithEvents'); VoipPushNotification.removeEventListener('register'); VoipPushNotification.removeEventListener('notification'); } } ``` #### Android In android we are going to use Firebase push notification to display Call notification So basically when ever we receive a push notification for call we display call notification. we need to add a listener to listen to notification when the app is background or foreground state. ```js messaging().setBackgroundMessageHandler(async (remoteMessage) => { RNCallKeep.setup(options); RNCallKeep.setAvailable(true); try { //Converting the message payload into CometChat Message. let msg = CometChat.CometChatHelper.processMessage( JSON.parse(remoteMessage.data.message) ); if (msg.category == 'call') { //need to check if the notification we received for Call initiated or ended if (msg.action == 'initiated') { CallKeepHelper.msg = msg; //setting the msg object in call keep helper class CallKeepHelper.displayCallAndroid(); //this method is used to display incoming calls in android t } else { //if sender cancels the call before receiver accept or reject call then we also need to stop our notification RNCallKeep.endCall(msg.conversationId); } } } catch (e) { console.log(e); } }); ``` #### iOS In iOS we use APNs push and voip push notification to display push notification and display call CallKit for calls. The notification are handled in Native iOS You need to add the code in AppDelegate.m file to display CallKit ```objc //add this import at the top or the file #import "RNCallKeep.h" #import "RNFBMessagingModule.h" #import #import "RNVoipPushNotificationManager.h" _* <------ add this function *_ - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type { // Register VoIP push token (a property of PKPushCredentials) with server [RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:(NSString *)type]; } - (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(PKPushType)type { // --- The system calls this method when a previously provided push token is no longer valid for use. No action is necessary on your part to re-register the push type. Instead, use this method to notify your server not to send push notifications using the matching push token. } // --- Handle incoming pushes - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion { // --- NOTE: apple forced us to invoke callkit ASAP when we receive voip push // --- see: react-native-callkeep // --- Retrieve information from your voip push payload NSDictionary *content = [payload.dictionaryPayload valueForKey:@"aps"]; NSDictionary *sender = [content valueForKey:@"alert"]; NSString *uuid =[[[NSUUID UUID] UUIDString] lowercaseString]; NSString *callerName=[sender valueForKey:@"title"]; NSString *handle = [sender valueForKey:@"title"]; // --- Process the received push [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type]; [RNCallKeep reportNewIncomingCall: uuid handle: handle handleType: @"generic" hasVideo: NO localizedCallerName: callerName supportsHolding: YES supportsDTMF: YES supportsGrouping: YES supportsUngrouping: YES fromPushKit: YES payload: nil withCompletionHandler: completion]; } ``` # Customizations Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/sms-customization Customizations allow controlling notifications for message events, group events, and call events. Users can set preferences for incoming notifications based on notification schedules, Do Not Disturb (DND) mode, and the mute status of specific conversations. Additional customizations include modifications to notification templates and sounds. These options also ensure that user privacy is maintained while displaying notifications on the device. For more information, refer to [Preferences, Templates & Sounds](/notifications/preferences-templates-sounds) documentation. # Integration Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/sms-integration SMS Notifications integration is possible using Twilio as a provider or a custom provider. With Custom SMS provider, you can integrate using SMS providers other than Twilio. ## Twilio We have partnered with Twilio for sending SMS Notifications so need to set up an account on [Twilio](https://www.twilio.com/) before you start using the extension. ### Create a new App on Twilio 1. Once you log in to Twilio, create a new app. 2. Make a note of **Account SID** and **Auth Token** for later use. 3. Click on "Get a Trial number" to get the Sender number. (Use the paid number if you already have one) 4. Make a note of the sender's **phone number** for later use. ### Store contact details Store the phone number of your users by using our [Update Contact details API](https://api-explorer.cometchat.com/reference/notifications-update-contact-details). ### Enable SMS Notifications 1. Login to [CometChat](https://app.cometchat.com/login) dashboard and select your app. 2. Navigate to **Notifications** > **Notifications** in the left-hand menu. 3. Enable SMS notifications feature. ### Save Twilio credentials Save the following details: * Twilio Account SID * Twilio Auth token * Twilio sender phone number ### Save user's timezone A user's timezone is required to allow them to set a schedule for receiving notifications. In case the timezone is not registered, the default timezone for * For US region: EST * For EU region: GMT * For IN region: Asia/Kolkata The timezone can be registered for a user from the SDK using the `updateTimezone()` method of `CometChatNotifications` class. This functionality is available in the following SDK versions: 1. Android SDK version 4.0.9 and above 2. iOS SDK version 4.0.51 and above 3. Web SDK version 4.0.8 and above 4. React Native SDK version 4.0.10 and above 5. Ionic Cordova SDK version 4.0.8 and above 6. Flutter SDK version 4.0.15 and above ### Receive notifications Send a message to any user and keep the conversation unread for the designated amount of time to receive an SMS notification. ## Custom SMS provider Custom provider allows you to make use of providers apart from Twilio for triggering SMS notifications. This is implemented using webhook URL which gets all the required details that can be used to trigger SMS notifications. #### Pre-requisite 1. Your webhook endpoint must be accessible over `HTTPS`. This is essential to ensure the security and integrity of data transmission. 2. This URL should be publicly accessible from the internet. 3. Ensure that your endpoint supports the `HTTP POST` method. Event payloads will be delivered via `HTTP POST` requests in `JSON` format. 4. Configure your endpoint to respond immediately to the CometChat server with a 200 OK response. The response should be sent within 2 seconds of receiving the request. 5. For security, it is recommended to set up Basic Authentication that is usually used for server-to-server calls. This requires you to configure a username and password. Whenever your webhook URL is triggered, the HTTP Header will contain: ```html Authorization: Basic ``` #### Add credentials 1. Click on the "+ Add Credentials" button. 2. Enable the provider. 3. Enter the publically accessible Webhook URL. 4. It is recommended to enable Basic Authentication. 5. Enter the username and password. 6. Enabling the "Trigger only if phone number is stored with CometChat" setting requires users' phone numbers to be stored with CometChat using the [Update Contact details API](https://api-explorer.cometchat.com/reference/notifications-update-contact-details). When enabled, the webhook is triggered only for those users. If this setting is disabled, the webhook triggers regardless of whether users' phone numbers are stored with CometChat. 7. Save the credentials. #### How does it work? The Custom provider is triggered once for an event in one-on-one conversation. In case of notifying users in a group, the custom provider is triggered once for each user present in that group. ```json { "trigger": "sms-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-1", "phno": "+919299334134", // Optional "name": "Andrew Joseph" }, "messages": [ { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "Are we meeting on this weekend?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "📷 Has shared an image", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "senderDetails": { "uid": "cometchat-uid-4", "name": "Susan Marie", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp" }, "smsContent": "You've received new messages from Susan Marie! Read them at https://your-website.com/chat." }, "appId": "app123", "region": "us/eu/in", "webhook": "custom" } ``` ```json { "trigger": "sms-notification-payload-generated", "data": { "to": { "uid": "cometchat-uid-1", "phno": "+919299334134", // Optional "name": "Andrew Joseph" }, "messages": [ { "sender": { "uid": "cometchat-uid-5", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-5.webp", "name": "John Paul" }, "message": "Hello all! What's up?", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited }, { "sender": { "uid": "cometchat-uid-4", "avatar": "https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-4.webp", "name": "Susan Marie" }, "message": "This is the place I was thinking about", "messageObject": {CometChat Message Object}, // Present if "Include message object" is enabled. The message object is present for new messages or in case a message was edited } ], "groupDetails": { "guid": "cometchat-guid-1", "name": "Hiking Group", "icon": "https://assets.cometchat.io/sampleapp/v2/groups/cometchat-guid-1.webp" }, "smsContent": "You've received new messages in Hiking Group! Read them at https://your-website.com." }, "appId": "app123", "region": "us/eu/in", "webhook": "custom" } ``` #### Sample server-side code ```javascript const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000; app.use(express.json()); // Optional: Basic authentication middleware const basicAuth = (req, res, next) => { const authHeader = req.headers['authorization']; if (!authHeader || !authHeader.startsWith('Basic ')) { return res.status(401).json({ message: 'Unauthorized' }); } next(); }; const triggerSMSNotification = async (to, data) => { let { name, uid, phno } = to; let { groupDetails, senderDetails, smsContent } = data; if (groupDetails) { console.log('Received webhook for group SMS notification'); } if (senderDetails) { console.log('Received webhook for one-on-one SMS notification'); } if (phno == null) { // Your implementation to fetch Phone number phno = await fetchPhoneNumberFor(uid); } // Your implementation for sending the SMS notification await sendSMS(phno, smsContent); }; app.post('/webhook', basicAuth, (req, res) => { const { trigger, data, appId, region, webhook } = req.body; if ( trigger !== 'sms-notification-payload-generated' || webhook !== 'custom' ) { return res.status(400).json({ message: 'Invalid trigger or webhook type' }); } console.log('Received Webhook:', JSON.stringify(req.body, null, 2)); triggerSMSNotification(to, data) .then((result) => { console.log( 'Successfully triggered SMS notification for', appId, to.uid, result ); }) .catch((error) => { console.error( 'Something went wrong while triggering SMS notification for', appId, to.uid, error.message ); }); res.status(200).json({ message: 'Webhook received successfully' }); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); ``` ## Next steps Have a look at the available [preferences](/notifications/preferences-templates-sounds#sms-notification-preferences) and [templates](/notifications/preferences-templates-sounds#sms-notification-templates) for SMS notifications. # SMS Notification Extension (Legacy) Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/sms-notification-extension **Legacy Notice**: This extension is already included as part of the core messaging experience and is scheduled for deprecation in the near future. Please note: Legacy extensions are no longer actively maintained and will not receive feature updates or enhancements. ## About the extension The SMS Notification extension helps you to notify offline users via SMS, when they have unread text messages. After you've configured the extension, your users will receive SMS for unread messages in one-on-one conversations. Required: Read Receipts Make sure to implement read receipts so that your users receive SMS notifications for only unread messages. ## Create a new App on Twilio We have partnered with Twilio for sending SMS Notifications so need to set up an account on [Twilio](https://www.twilio.com) before you start using the extension. 1. Once you log in to Twilio, create a new app. 2. Note down the Account SID, Auth Token. 3. Click on "Get a Trial number" to get the Sender number. (Use the paid number if you already have one) 4. Note down the above details as these will be required in the next steps. ## Extension settings 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and enable the SMS Notification extension. 3. Open the Settings for this extension and save the below details. ## Configure your backend to store phone number You can use our [Update user](https://api-explorer.cometchat.com/reference/update-user) API to set private metadata for a user. We recommend adding this code when you call our [Create user](https://api-explorer.cometchat.com/reference/creates-user) API. Alternatively, just for the sake of testing purposes, you can add this from the CometChat Dashboard as well. 1. Login to the [CometChat](https://app.cometchat.com/login). 2. Select your app and go to the "Users" section. 3. Click on the Edit option available under the three dots for the user under consideration. 4. Click on the Edit button on the Details section. 5. Paste the below JSON in the Metadata input box and hit Save. The Metadata is a JSON that should have the `@private` key present and should have the value `contactNumber` specified for the user. The format for the private metadata must be as follows: ```json { "@private": { "contactNumber":"+12345678910" } } ``` Country code is required It is important to store the contact number with the correct country code to receive SMS notifications. ## Receive SMS Notification Send a message to an offline user and watch them receive an SMS! # Overview Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/sms-overview ## Introduction SMS notifications are useful as a re-engagement tool, prompting users to return to the app after an extended absence. These are useful for providing updates on messages that are unread while the user was away. The SMS alerts or notifications are dispatched at predetermined intervals and not in real time. ## Key features 1. **Notify users at intervals**: Users who have unread messages can be notified at the specified intervals. The SMS includes a message prompting users to return to the app and are triggered for every such conversation. 2. **Contacts management** Once the Phone numbers are verified and vetted on your end, they can be shared with the notifications system using APIs. 3. **Preferences management**: Through CometChat's Notification Preferences, users and admins have the ability to customize the notification settings, that help provide pertinent alerts while avoiding notification fatigue. 4. **Ability to set up a schedule**: CometChat's notifications service ensures that the notifications are delivered based on the specified daily timetable, adhering to the user's local time zone. 5. **Ability to mute notifications**: Users have the option to completely mute notifications for the app (DND mode), or selectively mute them for specific users and groups, for a designated duration. 6. **Ability to set up Templates**: CometChat offers developers a set of pre-defined templates that define the content shown in SMS. # Token Management Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/token-management ## Register tokens Token registration can now be done using the callExtension method provided by the CometChat SDK. The token can be FCM token or APNs token and VoIP token. This can be achieved using the code snippet below: **For FCM token:** ```js // For FCM Token CometChat.callExtension('push-notification', 'POST', 'v2/tokens', { fcmToken: "fcm_token" }) .then(response => { // Success response }) .catch(error => { // Error occured }) ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("fcmToken", "fcm_token"); CometChat.callExtension("push-notification", "POST", "/v2/tokens", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .post, endPoint: "v2/tokens", body: ["fcmToken": "fcm_token"] as [String : Any], onSuccess: { (response) in // success response }) { (error) in // Error occured } ``` **For APNs tokens:** ```js // For APNs tokens CometChat.callExtension('push-notification', 'POST', 'v2/tokens', { apnsToken: "apns_token", voipToken: "voip_token" }) .then(response => { // Success response }) .catch(error => { // Error occured }) ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("apnsToken", "apns_token"); body.put("voipToken", "voip_token"); CometChat.callExtension("push-notification", "POST", "/v2/tokens", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .post, endPoint: "v2/tokens", body: ["apnsToken": "apns_token", "voipToken": "voip_token"] as [String : Any], onSuccess: { (response) in // Success response }) { (error) in // Error occured } ``` ## Get tokens This provides a list of all the Push Notifications tokens that have been registered for the current user. The tokens are segregated based on the platform. ```js CometChat.callExtension('push-notification', 'GET', 'v2/tokens', null) .then(response => { // Success response }) .catch(error => { // Error occured }) ``` ```java CometChat.callExtension("push-notification", "GET", "/v2/tokens", null, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .get, endPoint: "v2/tokens", body: nil, onSuccess: { (response) in // Success response }) { (error) in // Error occured } ``` The response will be as follows: ```json { "ios": [ "cLztQGbuPA91bG3rkRcgcQYvlKuTlWGmHC1RnCwrTrbyT0VF" ], "web": [ "cLztQGbuPA91bG3rkRcgcQYvlKuTlWGmHC1RnxyzTrbyT0VF" ], "android": [ "dLztQGbuPA91bG3rkRckcQYvlKuTlWGmHC1RnxyzTrbyT0VF" ] } ``` ## Delete tokens Token deletion is handled implicitly by the `CometChat.logout()` method. That is, once the user is logged out of the current CometChat session, his/her registered Push Notification token automatically gets deleted. The same can be achieved explicitly by making a call to the extension using `callExtension` method as shown below. However, the token that is deleted belongs to the current session of the end-user by passing `all=false` as a parameter. ```js CometChat.callExtension('push-notification', 'DELETE', 'v2/tokens', { all: false, // true when ALL the registered tokens for the logged-in user need to be deleted }) .then((response) => { // Success response }) .catch((error) => { // Error occured }); ``` ```java import org.json.simple.JSONObject; JSONObject body=new JSONObject(); body.put("all", false); // true when ALL the registered tokens for the logged-in user need to be deleted CometChat.callExtension("push-notification", "DELETE", "/v2/tokens", body, new CometChat.CallbackListener < JSONObject > () { @Override public void onSuccess(JSONObject jsonObject) { //On Success } @Override public void onError(CometChatException e) { //On Failure } }); ``` ```swift CometChat.callExtension(slug: "push-notification", type: .delete, endPoint: "v2/tokens", body: ["all": false] as [String : Any], onSuccess: { (response) in // true when ALL the registered tokens for the logged-in user need to be deleted // Details about the created poll }) { (error) in // Error occured } ``` All the tokens for the current user will be deleted if you pass `all=true`. This needs to be used with care as the other logins of the current user will stop receiving Push Notifications. # Web Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/notifications/web-push-notifications The Push Notification extension allows you to send push notifications to mobile apps and desktop browsers. Push notifications will work in all desktop browsers which support [Push API](https://caniuse.com/#feat=push-api). These include: 1. Chrome 50+ 2. Firefox 44+ 3. Edge 17+ 4. Opera 42+ Push notifications sample app for Web (React) View on Github ## Firebase Project Setup Visit [Firebase Console](https://console.firebase.google.com) and login/signup using your Gmail ID. ### Step 1: Create a new Firebase Project This is a simple 3 step process where: 1. You give a name to your project 2. Add Google Analytics to your project (Optional) 3. Configure Google Analytics account (Optional) Click on Create and you are ready to go. ### Step 2: Add Firebase to your Web App 1. Click on the Web icon on the below screen and Register your app with a nickname. 2. Once done, click on Continue to Console. ### Step 3: Download the service account file ## Extension settings ### Step 1: Enable the extension 1. Login to [CometChat](https://app.cometchat.com/login) and select your app. 2. Go to the Extensions section and Enable the Push Notifications extension. 3. Open the settings for the extension and add all the mentioned settings and hit save. ### Step 2: Save your settings On the Settings page you need to enter the following: 1. **Set extension version** * If you are setting it for the first time, Select `V2` to start using the token-based version of the Push Notification extension. * If you already have an app using `V1` and want to migrate your app to use `V2`, then Select `V1 & V2` option. This ensures that the users viewing the older version of your app also receive Push Notifications. * Eventually, when all your users are on the latest version of your app, you can change this option to `V2`, thus turning off `V1` (Topic-based) Push Notifications completely. 2. **Select the platforms that you want to support** * Select from Web, Android, Ionic, React Native, Flutter & iOS. 3. **Notification payload settings** * You can control if the notification key should be in the Payload or not. Learn more about the FCM Messages [here](https://firebase.google.com/docs/cloud-messaging/concept-options). 4. **Push payload message options** * The maximum payload size supported by FCM and APNs for push notifications is approximately 4 KB. Due to the inclusion of CometChat's message object, the payload size may exceed this limit, potentially leading to non-delivery of push notifications for certain messages. The options provided allow you to remove the sender's metadata, receiver's metadata, message metadata and trim the content of the text field. * The message metadata includes the outputs of the Thumbnail Generation, Image Moderation, and Smart Replies extensions. You may want to retain this metadata if you need to customize the notification displayed to the end user based on these outputs. 5. **Notification Triggers** * Select the triggers for sending Push Notifications. These triggers can be classified into 3 main categories: 1. Message Notifications 2. Call Notifications 3. Group Notifications * These are pretty self-explanatory and you can toggle them as per your requirement. ## Web App Setup ### Step 1: Folder and files setup Create a folder with the following three files: | Files | Description | | ------------------------- | ------------------------------------------------------------------------------------------- | | index.html | Displays a simple User Login Form. | | PushNotification.js | File with the logic to initialize CometChat and Firebase. | | firebase-messaging-sw\.js | Service worker shows Push Notifications when the tab is either in the background or closed. | ### Step 2: Add the Firebase Config to the HTML File 1. Go to the Firebase Console and click on the Web app and open up the Settings page. 2. Go to the "General" tab on the Settings page. 3. Scroll down and copy the Firebase SDK snippet and paste in the \ tag of your index.html file. ### Step 3: Setup index.html file 1. Include the latest CometChat library using CDN. 2. Register the service worker file. 3. Also, include the `PushNotification.js`. 4. The \ has a simple form: 1. Text input for UID. 2. Login button. 3. Logout button. Once done, your `index.html` file should look like this: ```html Push Notification Sample Push Notifications (Legacy)

```
### Step 4: Setup the service worker file 1. Use `importScripts` to include the `firebase-app.js` and `firebase-messaging.js` files in the service worker. 2. Also paste in the `FIREBASE_CONFIG` object again in this file. 3. Initialize the Firebase object using the config. 4. Call the messaging() on the Firebase object. Once done, your `firebase-messaging-sw.js` file should look like this: ```js importScripts('https://www.gstatic.com/firebasejs/7.21.0/firebase-app.js'); importScripts( 'https://www.gstatic.com/firebasejs/7.21.0/firebase-messaging.js' ); const FIREBASE_CONFIG = { // Your Config }; // Initialize firebase in the service worker. firebase.initializeApp(FIREBASE_CONFIG); // Start Receiving Push Notifications when // the browser tab is in the background or closed. firebase.messaging(); ``` ### Step 5: Setup the PushNotification.js file Now our simple web app has the following: 1. Setup required to start using Firebase SDK. 2. Service worker registration when the index.html loads for the first time. Next, we can focus on the flow to setup CometChat login process along with the steps required to setup Push Notifications using Firebase Cloud Messaging (or FCM). During login: 1. Initialize CometChat. 2. Login using CometChat user. 3. Ask for the User's permission to show Push Notifications. 4. If permission is granted, obtain the `FCM_TOKEN`. 5. Register the obtained `FCM_TOKEN` with the extension. During logout: 1. First delete the token using the firebase object. 2. Logout CometChat user. The above steps have been implemented in the `login` and `logout` functions in the `PushNotifications.js` file. You can copy paste the below code. Do not forget to replace the `APP_ID`, `REGION`, `AUTH_KEY` of your app in the code below. ```js const APP_ID = 'APP_ID'; const REGION = 'REGION'; const AUTH_KEY = 'AUTH_KEY'; const APP_SETTING = new CometChat.AppSettingsBuilder() .subscribePresenceForAllUsers() .setRegion(REGION) .build(); let FCM_TOKEN = ''; let loginButton; let logoutButton; const login = async () => { const UID = document.getElementById('uid').value; if (!UID) { document.getElementById('uid').focus(); return; } loginButton.disabled = true; console.log('Initiating login... '); try { // CC init await CometChat.init(APP_ID, APP_SETTING); // User login const loginResponse = await CometChat.login(UID, AUTH_KEY); console.log('1. User login complete', loginResponse); CometChat.getLoggedinUser().then((user) => console.log(user.name)); // Change the page title document.title = UID + ' logged in'; // Fetch the FCM Token const messaging = firebase.messaging(); FCM_TOKEN = await messaging.getToken(); console.log('2. Received FCM Token', FCM_TOKEN); // Register the FCM Token await CometChat.registerTokenForPushNotification(FCM_TOKEN); console.log('3. Registered FCM Token'); logoutButton.disabled = false; } catch (error) { console.error(error); } }; const logout = async () => { console.log('Initiating logout...'); loginButton.disabled = true; logoutButton.disabled = true; try { // Delete the token const messaging = firebase.messaging(); await messaging.deleteToken(); // Logout the user await CometChat.logout(); console.log('5. Logged out'); // Refresh the page. init(); window.location.reload(); } catch (error) { console.error(error); } }; const init = () => { // Basic initialization loginButton = document.getElementById('loginButton'); logoutButton = document.getElementById('logoutButton'); loginButton.addEventListener('click', login); logoutButton.addEventListener('click', logout); logoutButton.disabled = true; }; window.onload = () => { // Call the initialization function on load. setTimeout(init, 300); }; ``` ## Start receiving Push Notifications 1. You can now host the project folder using Nginx, Apache web server, or even VSCode Live server extension. 2. Launch the web app in a browser and open the browser console to see the logs. 3. Enter the UID of the user and click on login. 4. When asked for permission to show notifications, click on Allow. 5. Once you see logs saying that the FCM Token has been registered, either send the browser tab to the background or close it completely. 6. Send a message to this logged-in user from another device (using our Sample Apps) and you should be able to see the Push Notifications. ## Stop receiving Push Notifications 1. Reopen the previous closed browser tab and click on logout. 2. The `FCM_TOKEN` will be deleted on the extension's end on the `CometChat.logout()` call. 3. As a good practice, the `FCM_TOKEN` should also be deleted using the `firebase.messaging().deleteToken()`. ## Custom body for notifications To send custom body for notifications or to receive notification of `CustomMessage`, you need to set metadata while sending the `CustomMessage`. ```js var receiverID = 'UID'; var customData = { latitude: '50.6192171633316', longitude: '-72.68182268750002', }; var customType = 'location'; var receiverType = CometChat.RECEIVER_TYPE.USER; var metadata = { pushNotification: 'Your Notification Message', }; var customMessage = new CometChat.CustomMessage( receiverID, receiverType, customType, customData ); customMessage.setMetadata(metadata); CometChat.sendCustomMessage(customMessage).then( (message) => { // Message sent successfully. console.log('custom message sent successfully', message); }, (error) => { console.log('custom message sending failed with error', error); // Handle exception. } ); ``` # AI Agents Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents Build and ship AI agents in chat: pick a provider, connect your agent, and export UI or embed widgets. {/* Hero */}

AI Agents

Plug in your provider, wire actions, and ship chat UI — in minutes, not sprints.

AI Agents
{/* Overview */}

Overview

Easily create, customize, and deploy intelligent AI chatbots, agents, and copilots right into your app with CometChat AI Agents.

CometChat AI Agents connect your app’s logic, state, and user context to AI-powered assistants that deliver engaging, interactive experiences — whether through embedded UIs or fully headless interfaces. You get everything you need to build, deploy, and monitor AI-assisted features that feel seamless, helpful, and deeply integrated.

With model-agnostic flexibility, CometChat AI Agents let you upgrade your AI stack anytime - without disrupting your user experience.

Integrate AI Agents

Three core steps to get an AI Agent into your product.

Start by linking your AI builders. Choose from popular platforms (OpenAI, Mastra, LangGraph and many more..)

} href="/ai-agents/mastra" horizontal /> } horizontal>Coming Soon } horizontal>Coming Soon } horizontal>Coming Soon

More providers coming…

Create and manage frontend actions and tools to enhance your agent’s capabilities.

Actions: trigger UI & workflows. Tools: structured capabilities the agent can call.

Customize the agent’s appearance and copy the embed code to integrate it into your app.

} description="No‑code" href="/ai-agents/chat-widget" horizontal /> } href="https://www.cometchat.com/docs/ui-kit/react/ai-assistant-chat" horizontal>Pre Built UI Components } horizontal>Coming Soon } horizontal>Coming Soon } horizontal>Coming Soon } horizontal>Coming Soon } horizontal>Coming Soon
{/* Footer */} # AI Agent Actions Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/actions Explore the various actions you can perform with your AI agent in CometChat. ## Overview Actions allow your AI agent to perform specific, predefined tasks during a conversation.\ Each action includes a **name**, **display name**, **execution text**, and optional **parameters** to make the execution dynamic. You can create actions to: * Trigger workflows or automations. * Call external APIs. * Send structured responses to users. * Execute commands with dynamic inputs. *** ## Creating an Action 1. **Navigate to AI Agent → Actions** in the CometChat dashboard. 2. Click **Create Action**. You will see the following fields: ### **Display Name** A human-friendly name shown in the UI.\ *Example*: `Create Support Ticket` ### **Execution Text** The text prompt shown to the AI when this action is triggered.\ *Example*: `Create a Zendesk ticket with the following details.` ### **Name** A unique identifier for the action. This is used programmatically and should not contain spaces.\ *Example*: `create_support_ticket` ### **Description** A short explanation of what the action does.\ *Example*: `Creates a support ticket in Zendesk based on user query details.` ### **Parameters** A JSON schema that defines what input values the action requires. **Important:** The `""` must exactly match the **Tool Name** you created in **AI Agent → Tools**.\ This ensures that the Action can send correctly formatted data to the intended Tool. Example: ```json { "type": "object", "properties": { "": { "type": "string", "description": "Description of the parameter, defining the input the tool expects." } } } ``` **Parameter Types:** Use standard JSON Schema types like `string`, `number`, `boolean`, `object`, or `array`. **Parameter Descriptions:** Clearly explain the purpose and expected format of each parameter. *** ## Example Action: Create Zendesk Ticket | Field | Value | | -------------- | ---------------------------------------------------- | | Display Name | Create Support Ticket | | Execution Text | Create a Zendesk ticket with the provided details. | | Name | create\_support\_ticket | | Description | Creates a support ticket in Zendesk for user issues. | | Parameters | See JSON example above | *** ## Best Practices * **Keep display names short and clear** – instantly understandable to end users. * **Use consistent naming** – for the `Name` field, use lowercase with underscores. * **Match parameter names to tool names** – ensures correct tool invocation. * **Validate parameters** – always define parameter types and descriptions to prevent AI misinterpretation. * **Document purpose** – add clear descriptions for developers integrating the action. # Integrate an AI Agent into the Chat Widget Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/chat-widget Add an AI Agent (Mastra) to the CometChat Chat Widget using the no‑code builder and a simple embed. ## Prerequisites * CometChat app (App ID, Region, Auth Key). * Chat Widget variant (will produce a Widget / Variant ID). * A running Mastra agent endpoint (public or tunneled URL). * Mastra Agent ID (e.g. `chef`) and any required API key(s). * (Optional) Frontend Action definitions if you want UI‑bound behaviors. *** ## Step 1 - Create / Verify Your Mastra Agent Have a Mastra project ready (example using the “Chef” agent): ```ts // tools/suggest-substitute.ts & tools/recipe-from-pantry.ts (omitted for brevity) // agents/chef-agent.ts (export chefAgent) // mastra/index.ts import { Mastra } from '@mastra/core/mastra'; import { chefAgent } from './agents/chef-agent'; export const mastra = new Mastra({ agents: { chef: chefAgent } // 'chef' becomes /api/agents/chef/* }); ``` ```bash npx mastra dev curl -X POST http://localhost:4111/api/agents/chef/generate \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"Hello chef"}]}' ``` You now have: * Agent ID (e.g. `chef`) * Base URL (e.g. `http://localhost:4111/api` or public tunnel) *** ## Step 2 - Deploy / Expose Your Agent Choose one path so the Dashboard & Widget can reach your Mastra endpoint. Install a tunnel & expose port 4111 (pick one): ```bash # ngrok ngrok http 4111 # cloudflared cloudflared tunnel --url http://localhost:4111 # loca.lt ssh -R 80:localhost:4111 nokey@localhost.run ``` Copy the public HTTPS URL (e.g. `https://abc123.ngrok.io`) – this becomes your **Deployment URL**. Project structure (excerpt): ```txt mastra/ (project root) api/agents/[agent]/generate.ts (Vercel function) ``` Example handler: ```ts // api/agents/[agent]/generate.ts import { mastra } from '../../mastra/index'; export default async function handler(req, res) { if (req.method !== 'POST') return res.status(405).end(); const { agent } = req.query; const body = req.body; try { const response = await mastra.agents[agent].generate(body); res.json(response); } catch (e) { res.status(500).json({ error: e.message }); } } ``` Deploy: ```bash vercel deploy --prod ``` Use the deployed base URL (e.g. `https://your-app.vercel.app/api`). Add a simple Express server & Dockerfile: ```ts // server.ts import express from 'express'; import bodyParser from 'body-parser'; import { mastra } from './mastra'; const app = express(); app.use(bodyParser.json()); app.post('/api/agents/:agent/generate', async (req, res) => { const agent = req.params.agent; try { const out = await mastra.agents[agent].generate(req.body); res.json(out); } catch (e) { res.status(500).json({ error: e.message }); } }); app.listen(4111, () => console.log('Mastra listening on 4111')); ``` ```dockerfile FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY . . EXPOSE 4111 CMD ["node","dist/server.js"] ``` Build & run: ```bash docker build -t mastra-agent . docker run -p 4111:4111 mastra-agent ```
  • Add an auth layer (Bearer token) that the Dashboard/Widget includes.
  • Enable basic rate limiting (e.g. 60 req/min per IP).
  • Log tool invocations (duration + errors) for observability.
For fastest iteration start with a tunnel, then move to serverless or container for staging/production. You now have a **public base URL** to use in the Dashboard. *** ## Step 3 - Configure in CometChat Open the CometChat Dashboard. Go to your App → AI Agents. Set Provider=Mastra, Agent ID=chef, Deployment URL=public base URL from Step 2. Add greeting, starter prompts, or map frontend actions/tools for richer UI. Save and ensure the agent toggle shows Enabled. *** ## Step 4 - Attach Agent in Chat Builder (No‑Code) Launch Chat Builder from the Dashboard. Choose an existing Widget Variant or create a new one. In the AI / Agents panel toggle on your Mastra agent. Set display name & avatar so users recognize the agent. Save to persist the agent attachment. *** ## Step 5 - Frontend Actions & Tools (Optional) In Dashboard add actions (name + optional schema) that represent UI behaviors. Ensure Mastra tool id matches the action name for invocation context. Implement handlers in custom UI or rely on widget defaults when available. *** ## Step 6 - Customize in Chat Builder From AI Agents click the variant (or Get Started) to enter Chat Builder. Select Customize and Deploy. Theme, layout, features; ensure the Mastra agent is attached. Use live preview to validate responses and appearance, then save. *** ## Step 7 - Export & Embed In Chat Builder click **Get Embedded Code** → copy credentials: * App ID * Auth Key * Region * Variant ID Example embed (HTML): Add script tag in document head (see snippet below). Add mount div + init script before closing body. ```html ``` ```html
``` > Replace placeholders (``, etc.) with real values. *** ## Step 8 - Verify | Check | How | | :--------------- | :------------------------------------------------------ | | Agent appears | Open widget → new conversation / agent entry available | | Basic reply | Send a prompt → response under a few seconds | | Tool logic works | Ask for ingredient substitution / recipe (Chef example) | | Error free | Browser console + Mastra logs have no unhandled errors | If responses fail, confirm the endpoint is publicly reachable and the Agent ID matches the Dashboard configuration. *** ## Troubleshooting | Issue | Fix | | :--------------- | :----------------------------------------------------- | | Agent not listed | Confirm it’s enabled in Dashboard + variant saved | | 404 from Mastra | Endpoint path or agent key mismatch | | Timeout | Expose via a tunnel or deploy to a public host | | Tool not invoked | Ensure tool ID referenced in agent instructions & code | | Auth error | Re-check Auth Key / App credentials in embed snippet | *** ## Next Steps * Add more tools (search, summarization, domain knowledge). * Introduce Frontend Actions for richer UI control. * Move from tunnel to production deployment. * Add analytics / observability (latency, error tracking). Need code export (React UI Kit) instead of Widget? See the “Export & Integrate” guide in AI Agents # Create an AI Agent with Mastra Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/mastra Connect a Mastra agent to CometChat, customize it with Chat Builder, and ship it as React UI Kit code or a Chat Widget. **Developer Preview**: AI Agents currently support **Mastra**. OpenAI, Agno, and other providers are coming soon. ## What you’ll build * A **Mastra** agent with tools/actions * The same agent **connected to CometChat** (Agent ID + Deployment URL) * A **customized chat experience** using **Chat Builder** * An export to **React UI Kit code** *or* **Chat Widget** for integration *** ## Prerequisites * A CometChat account and an app: **[Create App](https://app.cometchat.com/apps)** * A Mastra agent (ID + public Deployment URL) — follow Mastra’s quickstart:\ **[Mastra Quickstart](https://mastra.ai/agents)** *** {/*

Step 1

*/} ## Step 1 - Create your CometChat app Sign in at app.cometchat.com. Create a new app or open an existing one. Note your App ID, Region, and Auth Key (needed if you export the Chat Widget later). *** {/*

Step 2

*/} ## Step 2 - Connect your Mastra Agent Navigate to **AI Agent → Get Started** and then **AI Agents → Add Agent**. Select **Mastra**. Provide: * **Name** and optional **Icon** * (Optional) **Greeting** and **Introductory Message** * (Optional) **Suggested messages** Paste the following from your Mastra deployment: * **Mastra Agent ID** * **Deployment URL** (public URL that CometChat can reach) Click **Save**, then ensure the agent’s toggle is **ON** in **AI Agents** list. > **Tip:** If you update your Mastra agent later (prompts, tools, routing), you won’t need to re-connect it in CometChat—just keep the **Agent ID** and **Deployment URL** the same. *** {/*

Step 3 (Optional)

*/} ## Step 3 - Define Frontend Actions (Optional) Go to AI Agent → Actions and click Add to create a frontend action your agent can call (e.g., “Open Product,” “Start Demo,” “Book Slot”). Include:
  • Display Name — Shown to users (e.g., “Open Product Page”).
  • Execution Text — How the agent describes running it (e.g., “Opening product details for the user.”).
  • Name — A unique, code‑friendly key (e.g., open\_product).
  • Description — What the tool does and when to use it.
  • Parameters — JSON Schema describing inputs (the agent will fill these).
Example parameters JSON: ```json { "type": "object", "required": ["productId"], "properties": { "productId": { "type": "string", "description": "The internal product ID to open" }, "utm": { "type": "string", "description": "Optional tracking code" } } } ``` At runtime, listen for tool calls and execute them client‑side (e.g., route changes, modals, highlights).
*** {/*

Step 4

*/} ## Step 4 - Customize in Chat Builder From AI Agents click the variant (or Get Started) to enter Chat Builder. Select Customize and Deploy. Theme, layout, features; ensure the Mastra agent is attached. Use live preview to validate responses & any tool triggers. *** {/*

Step 5

*/} ## Step 5 - Export & Integrate Choose how you’ll ship the experience (Widget or React UI Kit export). } description="Embed / script" href="/widget/ai-agents" horizontal /> } href="https://www.cometchat.com/docs/ui-kit/react/ai-assistant-chat" horizontal>Pre Built UI Components > The Mastra agent from Step 2 is included automatically in exported variants—no extra code needed for basic conversations. Pick Chat Widget (fastest) or export React UI Kit for code-level customization. Open Chat Builder → Get Embedded Code → copy script + credentials. Export the variant as code (UI Kit) if you need deep theming or custom logic. Preview: the Mastra agent should appear without extra config. *** {/*

Step 6

*/} ## Step 6 - Deploy & Secure (Reference) Don’t have a public Mastra agent yet? Use these reference blocks to define, expose, and deploy one securely. Minimal agent definition. (Adjust imports per current Mastra release.) ```ts // mastra/agent.ts import { defineAgent } from "mastra"; export const supportAgent = defineAgent({ name: "My Agent 1", instructions: `You are a helpful support agent for Acme. Use tools when appropriate.`, tools: [ { name: "open_product", description: "Open a product by ID in the UI", parameters: { type: "object", required: ["productId"], properties: { productId: { type: "string" } } } } ] }); ``` ```ts // server.ts import express from "express"; import { supportAgent } from "./mastra/agent"; const app = express(); app.use(express.json()); app.post("/mastra/agent", async (req, res) => { const { messages } = req.body; const result = await supportAgent.respond({ messages }); res.json(result); }); app.listen(process.env.PORT || 3000, () => { console.log("Mastra agent running"); }); ``` ```js // server.js const express = require("express"); const { supportAgent } = require("./mastra/agent"); const app = express(); app.use(express.json()); app.post("/mastra/agent", async (req, res) => { const { messages } = req.body; const result = await supportAgent.respond({ messages }); res.json(result); }); app.listen(process.env.PORT || 3000, () => { console.log("Mastra agent running"); }); ```

Local Development

  1. npx mastra dev starts local API (commonly [http://localhost:4111/api](http://localhost:4111/api)).
  2. Custom Express route? Keep path consistent in production.

Quick test (replace AGENT\_ID):

```bash curl -X POST http://localhost:4111/api/agents/AGENT_ID/generate \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"ping"}]}' ```

Temporary Public Tunnel

```bash ngrok http 4111 cloudflared tunnel --url http://localhost:4111 loca.lt --port 4111 ```

Append route (e.g. /api/agents/chef/generate) to the forwarded HTTPS URL.

Production Patterns

  • Serverless: Single API route invoking the agent.
  • Container: Long‑lived Express/CLI process; add health checks.
  • Edge: Keep tools stateless; externalize persistence.

Vercel Example

```ts // api/agents/chef/generate.ts import type { VercelRequest, VercelResponse } from '@vercel/node' import { chefAgent } from '../../mastra/agents/chef-agent' export default async function handler(req: VercelRequest, res: VercelResponse) { if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' }) try { const { messages } = req.body || {} const result = await chefAgent.respond({ messages }) return res.status(200).json(result) } catch (e:any) { return res.status(500).json({ error: e.message || 'Agent error' }) } } ```

Security

  • Rate limit by IP + user.
  • Add auth (Bearer / JWT) for non-public agents.
  • Log tool calls (id, latency) for observability.

CometChat Mapping

Use the final HTTPS URL + path for Deployment URL and the agent key (e.g. chef) for Mastra Agent ID.

Deploy (Vercel, Render, Fly, etc.) then copy the public URL as your Deployment URL and the Mastra Agent ID from config.

Docs: [https://mastra.ai/agents](https://mastra.ai/agents)
*** ## Test your setup In AI Agents, ensure your Mastra agent shows Enabled. Open Chat Builder and start a preview session. Send a message; confirm the agent responds. Trigger a Frontend Action and verify your UI handles the tool call. *** ## Troubleshooting
  • Verify your Deployment URL is publicly reachable (no VPN/firewall).
  • Check server logs for 4xx/5xx errors.
  • Confirm the Action’s Name in CometChat exactly matches the tool name your UI listens for.
  • Validate the Parameters JSON Schema; the agent uses this to fill inputs.
  • Use authKey only for development. For production, implement a secure token flow for user login.
# Build Your Backend Tools Agent with Mastra Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/mastra-backend-tools-agent Create a Mastra agent that performs secure backend actions (e.g., fetch deals) via server-side tools, then connect it to CometChat. Let an agent take real actions on the server: call APIs, query services, and return results—safely and without exposing secrets to the browser. *** ## What You’ll Build * A **Mastra agent** that can perform backend actions using server-side tools. * A tool (e.g., `get-deals`) that calls an external service/DB and returns structured data. * An API endpoint to chat with the agent and receive results grounded in tool output. * Integration into **CometChat** chats. *** ## Prerequisites * A Mastra project (`npx create-mastra@latest my-mastra-app`). * Node.js installed. * OpenAI API key in `.env` as `OPENAI_API_KEY`. * A CometChat app. *** ## Quick links * Repo: [mastra-backend-tools-agent](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/mastra-backend-tools-agent) * README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/README.md) * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/package.json) *** ## How it works This example demonstrates a “backend actions” pattern: * The agent (e.g., `deals`) decides to use a server-side tool like **get-deals** when it needs live data. * The tool runs securely on the server (with keys/env), calls your service, and returns structured results. * The agent composes a concise answer grounded in tool output; sensitive details never leave the server. * Your UI just renders responses—no secrets or privileged calls in the browser. Key components (source-linked below): the agent, the `get-deals` tool, server entry, and workflows. *** ## Project Structure Core files and folders for the Backend Tools Agent (browse source on GitHub): * Environment * [.env.example](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/.env.example) * Runtime & config * [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/package.json) * [tsconfig.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/tsconfig.json) * [README.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/README.md) * Agent * [src/mastra/agents/deals-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/agents/deals-agent.ts) * Tools * [src/mastra/tools/get-deals-tool.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/tools/get-deals-tool.ts) * [src/mastra/tools/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/tools/index.ts) * Server * [src/mastra/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/index.ts) * Workflows * [src/mastra/workflows/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/workflows/index.ts) *** ## Step 1 - Create the Agent **`src/mastra/agents/deals-agent.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/agents/deals-agent.ts)): Checklist for the agent: * Set `name` to something like **"deals"** so the API path is `/api/agents/deals/*`. * Describe when to use the `get-deals` tool (e.g., when user asks about deals, pricing, or promos). * Keep responses short, cite the latest results, and avoid hallucinations. * Ensure tool results are summarized clearly for end-users. *** ## Step 2 - Register the Agent in Mastra **`src/mastra/index.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/src/mastra/index.ts)): * Register the agent with key **"deals"** → API path `/api/agents/deals/*`. * Keep config and logger settings as per the repo README. *** ## Step 3 - Run the Agent *Dev scripts & server details are in your repo:* * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/package.json) * README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-backend-tools-agent/README.md) Expected local API base: `http://localhost:4111/api` Use the repo scripts to install dependencies. Run the local Mastra server as per the README. POST to /api/agents/deals/generate and verify the answer is backed by tool output. API endpoints exposed by this example: * POST `/api/agents/deals/generate` — chat with the agent and retrieve action-backed responses *** ## Step 4 - Deploy the API Ensure your public route: **`/api/agents/deals/generate`** is reachable. *** ## Step 5 - Configure in CometChat Open the CometChat Dashboard. Go to your App → AI Agents. Set Provider=Mastra, Agent ID=deals, Deployment URL=your public generate endpoint. Server-side tools require no client code, but you can display structured results nicely in your UI. Save and ensure the agent toggle shows Enabled. > For more on CometChat AI Agents, see the docs: [Overview](/ai-agents/overview) · [Instructions](/ai-agents/instructions) · [Custom agents](/ai-agents/custom-agents) *** ## Step 6 - Customize in Chat Builder From AI Agents click the variant (or Get Started) to enter Chat Builder. Select Customize and Deploy. Theme, layout, features; ensure the Backend Tools agent is attached. Use live preview to validate responses and scenarios that trigger backend actions. *** ## Step 7 - Integrate Once your Backend Tools Agent is configured, you can integrate it into your app using the CometChat No Code - Widget: } description="Embed / script" href="/widget/ai-agents" horizontal /> } href="https://www.cometchat.com/docs/ui-kit/react/ai-assistant-chat" horizontal>Pre Built UI Components > **Note:** The **Backend Tools agent** you connected in earlier steps is already part of the exported configuration, so your end-users will chat with that agent immediately. *** ## Step 8 - Test Your Setup POST to /api/agents/deals/generate returns a message backed by tool output. /api/agents includes "deals". Server logs show get-deals tool invoked when appropriate. ```bash curl -X POST http://localhost:4111/api/agents/deals/generate \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "role": "user", "content": "@agent what are the current deals?" } ] }' ``` *** ## Security & production checklist * Protect endpoints with auth (API key/JWT) and restrict CORS to trusted origins. * Add rate limiting and request size limits to the generate route. * Validate inputs, sanitize logs/responses, and handle upstream timeouts/retries. * Keep secrets in server-side env only; never expose them to the client. ## Troubleshooting * **No tool runs**: confirm the agent is configured to use `get-deals` and the tool is registered. * **Upstream errors**: inspect server logs and add retry/backoff to the tool. * **Agent not found**: confirm the server registers the agent with key `deals`. *** ## Next Steps * Add more backend tools (e.g., get-order, create-ticket) and guard with RBAC. * Stream responses or add partial updates for long-running actions. * Instrument and log tool invocations for tuning and observability. # Build Your Frontend Actions Agent with Mastra Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/mastra-frontend-actions-agent Create a Mastra agent that can trigger UI actions via frontend actions/tools (e.g., confetti), then connect it to CometChat. Give your chats superpowers: let an agent trigger visual effects and UI actions in the browser (like confetti) by returning safe, structured tool calls that your frontend handles. *** ## What You’ll Build * A **Mastra agent** that can request frontend UI actions (tools) like confetti. * A simple **tool registry** on the client that runs actions when the agent returns a tool call. * An API endpoint to chat with the agent and receive tool instructions. * Integration into **CometChat** chats. *** ## Prerequisites Repo: [mastra-frontend-actions-agent](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/mastra-frontend-actions-agent) README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/README.md) Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/package.json) * OpenAI API key in `.env` as `OPENAI_API_KEY`. * A CometChat app. *** ## Quick links Environment * [.env.example](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/.env.example) * Repo: [mastra-frontend-actions-agent](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/mastra-frontend-actions-agent) Runtime & config * [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/package.json) * README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/README.md) * [tsconfig.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/tsconfig.json) * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/package.json) * [README.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/README.md) *** Agent * [src/mastra/agents/celebration-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/agents/celebration-agent.ts) ## How it works Tools * [src/mastra/tools/confetti-tool.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/tools/confetti-tool.ts) * [src/mastra/tools/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/tools/index.ts) Server * [src/mastra/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/index.ts) * The server responds with a normal chat message and a machine-readable tool call describing what to run.\ Frontend sample * [widget/index.html](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/widget/index.html) * This keeps sensitive work on the server and visual effects on the client. Workflows * [src/mastra/workflows/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/workflows/index.ts) Key components (source-linked below): the agent, the `confetti` tool, server entry, and a sample widget page. *** Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/package.json)\ README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/README.md)\ See the sample: [widget/index.html](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/widget/index.html) * Environment * [.env.example](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/.env.example) * Runtime & config * [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/package.json) * [tsconfig.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/tsconfig.json) * [README.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/README.md) * Agent * [src/mastra/agents/celebration-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/agents/celebration-agent.ts) * Tools * [src/mastra/tools/confetti-tool.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/tools/confetti-tool.ts) * [src/mastra/tools/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/tools/index.ts) * Server * [src/mastra/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/index.ts) * Frontend sample * [widget/index.html](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/widget/index.html) * Workflows * [src/mastra/workflows/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/workflows/index.ts) *** ## Step 1 - Create the Agent **`src/mastra/agents/celebration-agent.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/agents/celebration-agent.ts)): Checklist for the agent: * Set `name` to something like **"celebration"** so the API path is `/api/agents/celebration/*`. * Describe when to use the `confetti` tool (e.g., celebratory moments). * Keep normal chat responses short and friendly. * Ensure tool return format is structured and safe. *** ## Step 2 - Register the Agent in Mastra **`src/mastra/index.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/src/mastra/index.ts)): * Register the agent with key **"celebration"** → API path `/api/agents/celebration/*`. * Keep config and logger settings as per the repo README. *** ## Step 3 - Run the Agent *Dev scripts & server details are in your repo:* * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/package.json) * README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/README.md) Expected local API base: `http://localhost:4111/api` Use the repo scripts to install dependencies. Run the local Mastra server as per the README. POST to /api/agents/celebration/generate and inspect tool calls in the response. API endpoints exposed by this example: * POST `/api/agents/celebration/generate` — chat with the agent and receive frontend tool instructions *** ## Step 4 - Handle frontend tools You’ll need a small client-side handler that: * Reads tool calls from the agent’s response (e.g., `{ id: "confetti", args: {...} }`). * Maps the tool ID to a function (e.g., `confetti()`), then runs it. * Handles unknown tools safely (ignore or log). See the sample: [widget/index.html](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-frontend-actions-agent/widget/index.html) *** ## Step 5 - Deploy the API Ensure your public route: **`/api/agents/celebration/generate`** is reachable. *** ## Step 6 - Configure in CometChat Open the CometChat Dashboard. Go to your App → AI Agents. Set Provider=Mastra, Agent ID=celebration, Deployment URL=your public generate endpoint. If your UI uses frontend tools, ensure your app handles tool invocations. Save and ensure the agent toggle shows Enabled. > For more on CometChat AI Agents, see the docs: [Overview](/ai-agents/overview) · [Instructions](/ai-agents/instructions) · [Custom agents](/ai-agents/custom-agents) *** ## Step 7 - Customize in Chat Builder From AI Agents click the variant (or Get Started) to enter Chat Builder. Select Customize and Deploy. Theme, layout, features; ensure the Frontend Actions agent is attached. Use live preview to validate messages and any tool triggers. *** ## Step 8 - Integrate Once your Frontend Actions Agent is configured, you can integrate it into your app using the CometChat No Code - Widget: } description="Embed / script" href="/widget/ai-agents" horizontal /> } href="https://www.cometchat.com/docs/ui-kit/react/ai-assistant-chat" horizontal>Pre Built UI Components > **Note:** The **Frontend Actions agent** you connected in earlier steps is already part of the exported configuration, so your end-users will chat with that agent immediately. *** ## Step 9 - Test Your Setup POST to /api/agents/celebration/generate returns a message, possibly with a tool call. /api/agents includes "celebration". Your UI runs the confetti tool when the agent requests it. ```bash curl -X POST http://localhost:4111/api/agents/celebration/generate \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "role": "user", "content": "@agent celebrate our product launch with confetti" } ] }' ``` *** ## Security & production checklist * Protect endpoints with auth (API key/JWT) and restrict CORS to trusted origins. * Add rate limiting and request size limits to the generate route. * Validate inputs and sanitize logs/responses server-side. * Keep your OpenAI key in server-side env only; never expose it to the client. ## Troubleshooting * **No tool runs**: ensure the frontend reads tool calls from the response and maps IDs to functions. * **Agent not found**: confirm the server registers the agent with key `celebration`. * **401/403**: verify auth headers and CORS for your deployment. *** ## Next Steps * Add more tools (e.g., toast, highlight, modal) and map them in your UI. * Gate tool usage by roles or contexts. * Log tool invocations for auditing and tuning. # Build Your Knowledge Agent with Mastra Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/mastra-knowledge-agent Create a Mastra Knowledge Agent that answers documentation questions when invoked, then connect it to CometChat. Imagine an agent that answers policy, product, and FAQ questions by looking them up in your docs—concise, cited, and available right inside chat without derailing the conversation. *** ## What You’ll Build * A **Mastra agent** that can participate in conversations as a documentation expert. * Triggered only when explicitly mentioned (e.g., `@agent`). * Can fetch knowledge from your docs and return short, sourced answers. * Integrated into **CometChat** chats. *** ## Prerequisites * A Mastra project (`npx create-mastra@latest my-mastra-app`). * Node.js installed. * OpenAI API key in `.env` as `OPENAI_API_KEY`. * A CometChat app. *** ## Quick links * Repo: [mastra-knowledge-agent](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/mastra-knowledge-agent) * Quickstart: [Knowledge Agent Quickstart](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/README.md#knowledge-agent-quickstart) * Swagger UI (local): [http://localhost:4111/swagger-ui](http://localhost:4111/swagger-ui) * Environment variables: [README#environment-variables](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/README.md#environment-variables) *** ## How it works This example implements a retrieval-augmented Knowledge Agent that: * Ingests sources (URLs, files, or raw text) into a local knowledge folder per namespace using the ingestSources tool. Parsed content is stored under knowledge/\ for repeatable retrieval. * Retrieves relevant snippets with the docsRetriever tool. It scans your knowledge/\ content, chunks and ranks results, and returns the best matches with source metadata. * Generates answers using only retrieved context. The agent replies when invoked (e.g., @agent), composes a concise answer, and appends a short “Sources” list with citations. * Handles errors defensively. Server utilities sanitize errors before returning responses. Key components (source-linked below): the agent, docs retriever tool, ingest endpoints, and server routes. *** ## Setup Create a Mastra app and add OPENAI\_API\_KEY in .env. See the repository README for exact steps. Add a knowledge agent that answers from retrieved docs only, and responds when explicitly mentioned (e.g., @agent). Register the agent and expose endpoints for /api/tools/ingestSources, /api/tools/searchDocs, and /api/agents/knowledge/generate (see server entry). Choose a namespace (e.g., docs) and POST sources to /api/tools/ingestSources. Use URLs, file paths, or raw text. Request shape is documented in the README Quickstart. Send chat turns to /api/agents/knowledge/generate with a messages array. Optionally pass toolParams.namespace to scope retrieval. In Dashboard → AI Agents, set Provider=Mastra, Agent ID=knowledge, and point Deployment URL to your public generate endpoint. Make the API public, verify via Swagger UI, and re-run ingestion when docs change. *** ## Project Structure Core files and folders for the Knowledge Agent (browse source on GitHub): * Environment * [.env.example](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/.env.example) * Runtime & config * [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/package.json) * [tsconfig.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/tsconfig.json) * [README.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/README.md) * Agent * [src/mastra/agents/knowledge-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/agents/knowledge-agent.ts) * [src/mastra/agents/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/agents/index.ts) * Tools * [src/mastra/tools/docs-retriever.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/tools/docs-retriever.ts) * [src/mastra/tools/ingest-sources.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/tools/ingest-sources.ts) * [src/mastra/tools/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/tools/index.ts) * Server * [src/mastra/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/index.ts) * [src/mastra/server/routes.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/server/routes.ts) * [src/mastra/server/routes/ingest.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/server/routes/ingest.ts) * [src/mastra/server/routes/searchDocs.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/server/routes/searchDocs.ts) * [src/mastra/server/util/safeErrorMessage.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/server/util/safeErrorMessage.ts) * Workflows * [src/mastra/workflows/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/workflows/index.ts) * Knowledge base (sample) * [knowledge/default/raw/Acme-Enterprises-FAQ.pdf](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/knowledge/default/raw/Acme-Enterprises-FAQ.pdf) * [knowledge/default/acme-enterprises-faq-pdf.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/knowledge/default/acme-enterprises-faq-pdf.md) *** ## Step 1 - Create the Agent **`src/mastra/agents/knowledge-agent.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/agents/knowledge-agent.ts)): * Agent file: [src/mastra/agents/knowledge-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/agents/knowledge-agent.ts) * Docs retriever tool: [src/mastra/tools/docs-retriever.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/tools/docs-retriever.ts) * Knowledge folder: [knowledge](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/mastra-knowledge-agent/knowledge) Checklist for the agent: * Set `name` to **"knowledge"** so the API path is `/api/agents/knowledge/*`. * Respond **only when mentioned** (e.g., `@agent`). * Answer **from retrieved docs** and include a short **“Sources:”** list. * Register `docsRetriever`. *** ## Step 2 - Register the Agent in Mastra **`src/mastra/index.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/index.ts)): * Server entry: [src/mastra/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/src/mastra/index.ts) * Ensure the agent is registered with key **"knowledge"** → API path `/api/agents/knowledge/*`. * Storage/logger configuration as per repo [README.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/README.md). *** ## Step 3 - Run the Agent *Dev script & local server details are tracked in your repo:* * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/package.json) * Quickstart: [Knowledge Agent Quickstart](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/README.md#knowledge-agent-quickstart) Expected local API base: `http://localhost:4111/api` Use the commands in the Quickstart (kept in the repository). Follow the Quickstart to run the local Mastra server. POST to /api/tools/ingestSources with a namespace. Example commands are in the README Quickstart. POST to /api/agents/knowledge/generate. See the README Quickstart for request bodies and examples. API endpoints exposed by this example (see [Swagger UI](http://localhost:4111/swagger-ui)): * POST `/api/tools/ingestSources` — ingest URLs/files/text into `knowledge/` * POST `/api/tools/searchDocs` — retrieve relevant snippets from `knowledge/` * POST `/api/agents/knowledge/generate` — chat with the agent *** ## Step 4 - Deploy the API * [Swagger UI (local)](http://localhost:4111/swagger-ui) * [Environment variables](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-knowledge-agent/README.md#environment-variables) Ensure the public route: **`/api/agents/knowledge/generate`** is reachable. *** ## Step 5 - Configure in CometChat Open the CometChat Dashboard. Go to your App → AI Agents. Set Provider=Mastra, Agent ID=knowledge, Deployment URL=your public generate endpoint. Add greeting, prompts, and configure actions/tools if you use frontend tools. Save and ensure the agent toggle shows Enabled. > For more on CometChat AI Agents, see the docs: [Overview](/ai-agents/overview) · [Instructions](/ai-agents/instructions) · [Custom agents](/ai-agents/custom-agents) *** ## Step 6 - Customize in Chat Builder From AI Agents click the variant (or Get Started) to enter Chat Builder. Select Customize and Deploy. Theme, layout, features; ensure the Mastra Knowledge agent is attached. Use live preview to validate responses & any tool triggers. *** ## Step 7 - Integrate Once your Knowledge Agent is configured, you can integrate it into your app using the CometChat No Code - Widget: } description="Embed / script" href="/widget/ai-agents" horizontal /> } href="https://www.cometchat.com/docs/ui-kit/react/ai-assistant-chat" horizontal>Pre Built UI Components > **Note:** The **Mastra Knowledge agent** you connected in earlier steps is already part of the exported configuration, so your end-users will chat with that agent immediately. *** ## Step 8 - Test Your Setup POST to /api/agents/knowledge/generate returns a doc-grounded answer. /api/agents includes "knowledge". UI handles docsRetriever tool invocation. See curl command below. ```bash curl -X POST http://localhost:4111/api/agents/knowledge/generate \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "role": "user", "content": "@agent where is the refund policy documented?" } ] }' ``` *** ## Security & production checklist * Protect endpoints with auth (API key/JWT) and restrict CORS to trusted origins. * Add basic rate limiting and request size limits to ingestion and generate routes. * Validate inputs: enforce allowed namespaces, URL/file whitelists, and payload schemas. * Monitor logs and errors; sanitize responses using server utilities. * For public deploys, keep your OpenAI key in server-side env only; never expose it to the client. ## Troubleshooting * **Agent talks too much**: tighten instructions to only respond when mentioned and to answer from docs. * **No results**: ensure `/knowledge` contains `.md/.mdx` files or your ingestion job populated the store. * **Not visible in chat**: verify the agent is added as a user in CometChat and enabled in the Dashboard. * **404 / Agent not found**: check that the server registers the agent with key `knowledge`. *** ## Next Steps * Add tools like `summarize-doc`, `fetch-policy`, or `link-to-source`. * Use embeddings + chunking for better retrieval. * Restrict answers to whitelisted folders or domains. * Inspect and try endpoints via Swagger UI (`/swagger-ui`). * Set up CI/CD in your own repo as needed. # Build Your Orchestrator Agent with Mastra Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/mastra-orchestrator-agent Create a Mastra orchestrator agent that routes queries to the right specialist (billing, support, tech, manager, human), then connect it to CometChat. Give users the right help fast: an orchestrator agent that triages each request and forwards it to the best-fit specialist (billing, support, tech support, manager, or a human rep). *** ## What You’ll Build * A **Mastra orchestrator agent** that classifies intent and routes to specialist agents. * Specialist agents (billing, support, tech-support, manager, human-rep). * A routing tool and workflow that coordinate handoffs. * Integration into **CometChat** chats. *** ## Prerequisites * A Mastra project (`npx create-mastra@latest my-mastra-app`). * Node.js installed. * OpenAI API key in `.env` as `OPENAI_API_KEY`. * A CometChat app. *** ## Quick links * Repo: [mastra-orchestrator-agent](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/mastra-orchestrator-agent) * README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/README.md) * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/package.json) *** ## How it works This example demonstrates a “multi-agent orchestration” pattern: * The primary agent (the orchestrator) understands the user request and decides which specialist should respond. * The routing tool and workflow handle the handoff, preserving context. * The selected specialist (billing/support/tech/manager/human-rep) answers, and the orchestrator returns the final response. * This keeps logic modular and makes it easy to add or refine specialist agents. Key components (source-linked below): the orchestrator agent, specialist agents, orchestrator tool, and orchestrator workflow. *** ## Setup Create a Mastra app and add OPENAI\_API\_KEY in .env. See the repository README for exact steps. Add an orchestrator agent and specialist agents (billing, support, tech, manager, human-rep). Implement a routing tool and workflow that determine the best specialist for a request. Register the agents and expose /api/agents/orchestratorAgent/generate (see server entry). POST to /api/agents/orchestratorAgent/generate with a messages array and verify routed answers. In Dashboard → AI Agents, set Provider=Mastra, Agent ID=orchestratorAgent, and point Deployment URL to your public generate endpoint. Make the API public and monitor which specialist is selected in logs. *** ## Project Structure Core files and folders for the Orchestrator Agent (browse source on GitHub): * Environment * Use .env with OPENAI\_API\_KEY * Runtime & config * [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/package.json) * [tsconfig.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/tsconfig.json) * [README.md](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/README.md) * Agents * [src/mastra/agents/orchestrator-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/orchestrator-agent.ts) * [src/mastra/agents/billing-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/billing-agent.ts) * [src/mastra/agents/support-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/support-agent.ts) * [src/mastra/agents/tech-support-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/tech-support-agent.ts) * [src/mastra/agents/manager-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/manager-agent.ts) * [src/mastra/agents/human-rep-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/human-rep-agent.ts) * Tools * [src/mastra/tools/orchestrator-tool.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/tools/orchestrator-tool.ts) * Workflows * [src/mastra/workflows/orchestrator-workflow.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/workflows/orchestrator-workflow.ts) * Server * [src/mastra/index.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/index.ts) *** ## Step 1 - Create the Orchestrator and Specialist Agents **`src/mastra/agents/orchestrator-agent.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/orchestrator-agent.ts)): Checklist for the orchestrator: * Register the agent with key **"orchestratorAgent"** so the API path is `/api/agents/orchestratorAgent/*`. * Detect intents (billing, support, tech, manager, human rep). * Use the routing tool/workflow to hand off. * Compose a concise final reply. Specialists (configure as needed): * Billing: [billing-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/billing-agent.ts) * Support: [support-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/support-agent.ts) * Tech Support: [tech-support-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/tech-support-agent.ts) * Manager: [manager-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/manager-agent.ts) * Human Rep: [human-rep-agent.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/agents/human-rep-agent.ts) *** ## Step 2 - Routing Tool and Workflow * Routing tool: [orchestrator-tool.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/tools/orchestrator-tool.ts) * Workflow: [orchestrator-workflow.ts](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/workflows/orchestrator-workflow.ts) Ensure the orchestrator agent calls the tool/workflow with the correct context, and specialists are discoverable by key. *** ## Step 3 - Register the Agents in Mastra **`src/mastra/index.ts`** ([view in repo](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/src/mastra/index.ts)): * Register the orchestrator with key **"orchestratorAgent"** → API path `/api/agents/orchestratorAgent/*`. * Register specialist agents and expose only the orchestrator externally. * Keep config and logger settings as per the repo README. *** ## Step 4 - Run the Orchestrator *Dev scripts & server details are in your repo:* * Scripts: [package.json](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/package.json) * README: [Project README](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/mastra-orchestrator-agent/README.md) Expected local API base: `http://localhost:4111/api` Run npm install. Run npx mastra dev (or npm run dev). POST to /api/agents/orchestratorAgent/generate and verify the routed specialist answers. Responses end with (\[routedTo] | escalated: yes/no); check logs for which specialist was chosen. API endpoints exposed by this example: * POST `/api/agents/orchestratorAgent/generate` — chat with the orchestrator and get routed responses *** ## Step 5 - Deploy the API Ensure your public route: **`/api/agents/orchestratorAgent/generate`** is reachable. *** ## Step 6 - Configure in CometChat Open the CometChat Dashboard. Go to your App → AI Agents. Set Provider=Mastra, Agent ID=orchestratorAgent, Deployment URL=your public generate endpoint. Adjust specialist prompts and routing rules as needed. Save and ensure the agent toggle shows Enabled. > For more on CometChat AI Agents, see the docs: [Overview](/ai-agents/overview) · [Instructions](/ai-agents/instructions) · [Custom agents](/ai-agents/custom-agents) *** ## Step 7 - Customize in Chat Builder From AI Agents click the variant (or Get Started) to enter Chat Builder. Select Customize and Deploy. Theme, layout, features; ensure the Orchestrator agent is attached. Use live preview to validate routing and responses. *** ## Step 8 - Integrate Once your Orchestrator Agent is configured, you can integrate it into your app using the CometChat No Code - Widget: } description="Embed / script" href="/widget/ai-agents" horizontal /> } href="https://www.cometchat.com/docs/ui-kit/react/ai-assistant-chat" horizontal>Pre Built UI Components > **Note:** The **Orchestrator agent** you connected in earlier steps is already part of the exported configuration, so your end-users will chat with that agent immediately. *** ## Step 9 - Test Your Setup POST to /api/agents/orchestratorAgent/generate returns an answer from the chosen specialist and ends with routing metadata. /api/agents includes "orchestratorAgent". Logs show which specialist handled the request. ```bash curl -X POST http://localhost:4111/api/agents/orchestratorAgent/generate \ -H "Content-Type: application/json" \ -d '{ "messages": [ { "role": "user", "content": "@agent I need help with my invoice charges" } ] }' ``` *** ## Security & production checklist * Protect endpoints with auth (API key/JWT) and restrict CORS to trusted origins. * Add rate limiting and request size limits to the generate route. * Validate inputs, sanitize logs/responses, and monitor routing distribution. * Keep secrets in server-side env only; never expose them to the client. ## Troubleshooting * **Wrong specialist**: refine orchestrator prompts, add explicit routing criteria, or fallbacks. * **No response**: verify orchestrator and specialists are registered and reachable. * **Agent not found**: confirm the server registers the agent with key `orchestratorAgent`. *** ## Next Steps * Add more specialists (sales, onboarding) or escalation rules. * Add audit logs for routed conversations. * Implement handoff to a human rep based on confidence thresholds. # Build a Product Hunt Agent with Mastra Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/mastra-product-hunt-agent Create a Mastra agent that can fetch Product Hunt posts, answer launch questions, and trigger frontend actions (confetti), then plug it into CometChat. Give your chats superpowers: let an agent call tools to retrieve Product Hunt data and return safe, structured UI actions that your frontend runs (like confetti). *** ## Quick links * Live demo: [cometchat.github.io/ai-agent-mastra-examples/product-hunt-agent/web](https://cometchat.github.io/ai-agent-mastra-examples/product-hunt-agent/web/) * Source code: [GitHub repository](https://github.com/cometchat/ai-agent-mastra-examples/tree/main/product-hunt-agent) *** ## What you’ll build * A Mastra agent that can: * Get top Product Hunt posts by timeframe or all‑time by votes * Search posts via Product Hunt’s public Algolia index * Answer practical “how to launch on Product Hunt” questions * Trigger a confetti animation in the user’s browser (frontend action) * A tiny HTTP API that exposes `/api/top*`, `/api/search`, and `/api/chat` * A static Product Hunt‑style page (with CometChat widget) that handles the confetti tool Repo layout in this example: * [`src/mastra/agents/producthunt-agent.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/mastra/agents/producthunt-agent.ts) — the agent definition * [`src/mastra/tools/producthunt-tools.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/mastra/tools/producthunt-tools.ts) — tools: top products, timeframe top, search, confetti * [`src/services/producthunt.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/services/producthunt.ts) — Product Hunt GraphQL + Algolia helpers and timeframe parsing * [`src/server.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/server.ts) — minimal API server returning JSON and agent chat * [`web/index.html`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/web/index.html) — static UI that mounts CometChat and maps the confetti tool *** ## Prerequisites * Node.js 20+ * OpenAI API key in your environment as `OPENAI_API_KEY` (agent Q\&A) * Product Hunt API token as `PRODUCTHUNT_API_TOKEN` (for top posts) * A CometChat app (for the widget on the static page) Optional quick links in this project: * Runtime & scripts: [`package.json`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/package.json) * Server TS build: [`tsconfig.server.json`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/tsconfig.server.json) * Static page: [`web/index.html`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/web/index.html) *** ## How it works * The agent (model: OpenAI via `@ai-sdk/openai`) can call tools: * `get-top-products` — top all‑time by votes (GraphQL) * `get-top-products-by-timeframe` — top posts for a day/week/month/date range with timezone * `search-products` — search via Algolia public index * `confetti-tool` — returns a structured payload the frontend uses to fire confetti * The API server exposes: * `GET /api/top`, `GET /api/top-week`, `GET /api/top-range` — fetch posts * `GET /api/search` — Algolia search * `POST /api/chat` — chat with the agent; server streams model text and returns `{ reply }` * The static page uses the CometChat Embed, and registers a client‑side tool handler map. When a chat message triggers `confetti-tool`, the page loads `canvas-confetti` and fires it with the provided options. Security note: model/provider keys are server‑side; frontend only receives tool payloads for UI. *** ## Step 1 — Define tools File: [`src/mastra/tools/producthunt-tools.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/mastra/tools/producthunt-tools.ts) * Top/all‑time: `get-top-products` * Timeframe: `get-top-products-by-timeframe` (supports today/yesterday/this‑week/last‑week/this‑month/last‑month, single date YYYY‑MM‑DD, or `from:YYYY-MM-DD to:YYYY-MM-DD` ranges; default tz `America/New_York`) * Search: `search-products` via Algolia public GET with fixed public headers * Frontend action: `confetti-tool` returns a payload with particleCount, colors, origin, etc. The agent will render compact Markdown tables from tool output for top lists. *** ## Step 2 — Create the agent File: [`src/mastra/agents/producthunt-agent.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/mastra/agents/producthunt-agent.ts) Checklist for the agent: * Name it clearly (e.g., “Product Hunt Agent”) * Explain when to use each tool, especially timeframe vs. all‑time * Keep launch‑advice answers concise and actionable * Include links when returned by tools; omit when missing * Be graceful when APIs are missing (empty arrays) *** ## Step 3 — Wire Mastra (optional) File: [`src/mastra/index.ts`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/src/mastra/index.ts) * Register your agent into Mastra if you prefer the Mastra dev server workflow * This demo uses a custom minimal `src/server.ts` for a simple `/api/*` shape *** ## Step 4 — Run locally 1. Install dependencies 2. Build server TypeScript 3. Start the server 4. Open the static page Default local API: `http://localhost:8787` Environment variables: * `OPENAI_API_KEY` — required for agent chat * `PRODUCTHUNT_API_TOKEN` — required for live top posts; without it `/api/top*` return empty arrays *** ## Step 5 — Frontend actions handler File: [`web/index.html`](https://github.com/cometchat/ai-agent-mastra-examples/blob/main/product-hunt-agent/web/index.html) * Registers tool handlers: * `confetti-tool` (and `confettiTool`) → loads `canvas-confetti` on demand, or uses a fallback renderer * CometChat Embed is initialized and launched; when the agent returns a tool call tied to the widget configuration, your handler runs it Tip: keep the handler resilient — accept both string and object args, set defaults, and no‑op on unknown tools. *** ## Step 6 — API overview * `GET /api/health` → `{ ok: true }` * `GET /api/top?limit=3` → top all‑time by votes * `GET /api/top-week?limit=3&days=7` → rolling week by ranking * `GET /api/top-range?timeframe=today&tz=America/New_York&limit=3` → timeframe window by ranking * `GET /api/search?q=term&limit=10` → Algolia search * `POST /api/chat` with `{ message }` → `{ reply }` from the agent CORS is open in this demo. *** ## Step 7 — Deploy the API * Deploy `src/server.ts` (Node 20+) to your hosting (Render, Fly, Vercel functions with Node runtime, etc.) * Set `OPENAI_API_KEY` and `PRODUCTHUNT_API_TOKEN` in the host environment * Point the static page to your public API by setting `window.PH_AGENT_API` *** ## Step 8 — Connect in CometChat * Open the CometChat Dashboard → your App → AI Agents * Add an agent with Provider=Mastra, Agent ID matching your integration, and the public generate/chat endpoint * Ensure your frontend (widget or custom UI) maps the `confetti-tool` ID to your handler function *** ## Step 9 — Test * Hit `/api/health` to confirm server is up * Try `/api/search?q=notion` to verify Algolia access * Call `/api/top-range?timeframe=today` with a valid token to get live posts * POST `/api/chat` with a prompt like “Celebrate our launch with confetti” and verify the frontend fires confetti when wired via CometChat *** ## Security & production checklist * Keep API tokens server‑side; never expose `OPENAI_API_KEY` or Product Hunt tokens to the client * Add auth (API key/JWT), restrict CORS, and rate‑limit endpoints * Validate and clamp user inputs (limits, timeframes) * Log server errors, not secrets *** ## Troubleshooting * No posts from `/api/top*`: missing or invalid `PRODUCTHUNT_API_TOKEN` * Empty `/api/search`: network block to Algolia; verify headers and URL * Chat has generic replies only: `OPENAI_API_KEY` missing * Confetti not firing: verify tool ID mapping (`confetti-tool` or `confettiTool`) and that the handler loads `canvas-confetti` # AI Agent Tools Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/ai-agents/tools Explore the various tools you can use with your AI agent in CometChat. ## Overview Tools allow your AI agent to perform specific operations or integrate with external systems.\ Once created, these tools can be invoked by **Actions** to execute tasks, fetch data, or interact with third-party APIs. You can use tools to: * Fetch data from external APIs. * Trigger workflows in other systems. * Perform backend logic before returning results to the chat. * Extend your AI agent’s capabilities beyond basic responses. *** ## Creating a Tool 1. **Navigate to AI Agent → Tools** in the CometChat dashboard. 2. Click **Create Tool**. You will see the following fields: ### **Display Name** A human-friendly name shown in the UI.\ *Example*: `Zendesk Ticket Creator` ### **Execution Text** A brief command or instruction for the AI to run when invoking this tool.\ *Example*: `Create a Zendesk support ticket using the provided details.` ### **Name** A unique identifier for the tool. This name is critical: * It must match exactly when used in an **Action’s Parameters** as the ``. * Use lowercase with underscores for consistency.\ *Example*: `zendesk_ticket_creator` *** ## Linking Tools with Actions When you define an **Action** that uses this tool, its `Parameters` JSON schema must include a key matching the tool’s **Name**. Example: ```json { "type": "object", "properties": { "zendesk_ticket_creator": { "type": "string", "description": "Details required to create the ticket" } } } ``` This ensures that the Action passes the correct input to the intended tool. *** ## Best Practices * **Name consistency is crucial** – mismatch between Tool Name and Action parameter key will break the link. * **Keep execution text concise** – so the AI can easily understand the intended operation. * **Use descriptive display names** – helpful for dashboard management. * **Document tool requirements** – specify what input format or authentication is needed. * **Test after creation** – trigger an Action that calls the tool to ensure it works end-to-end. # Getting Started With Chat Builder Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/android/integration Chat Builder streamlines integrating CometChat’s Android UI Kit into your app. Design the experience visually, export platform‑ready assets and settings, and wire them into your Android project with a few steps. ## Complete Integration Workflow 1. Design your chat experience in Chat Builder. 2. Export your code and settings package. 3. Enable extra features in the CometChat Dashboard if needed. 4. Optionally preview the experience in a sample app. 5. Integrate into your Android project. 6. Customize further with UI Kit styling and components. *** ## Launch the Chat Builder 1. Log in to your CometChat Dashboard: [https://app.cometchat.com](https://app.cometchat.com) 2. Select your application. 3. Go to Integrate → Android → Launch Chat Builder. *** ## Enable Features in CometChat Dashboard If your app needs any of these, enable them from your Dashboard: [https://app.cometchat.com](https://app.cometchat.com) * Stickers * Polls * Collaborative whiteboard * Collaborative document * Message translation * AI User Copilot: Conversation starter, Conversation summary, Smart reply How to enable: 1. Log in to the Dashboard. 2. Select your app. 3. Navigate to Chat → Features. 4. Toggle ON the required features and Save. *** ## Integration with CometChat Chat Builder (Android) Follow these steps in your existing Android app (from README): ### Step 1: Add CometChat Maven repository Add to `settings.gradle.kts` (dependencyResolutionManagement): ```kotlin maven("https://dl.cloudsmith.io/public/cometchat/cometchat/maven/") ``` ### Step 2: Add UI Kit dependencies In your app module `build.gradle`: ```gradle dependencies { // CometChat UIKit implementation 'com.cometchat:chat-uikit-android:5.1.0' // Optional: voice/video calling implementation 'com.cometchat:calls-sdk-android:4.1.2' } ``` ### Step 3: Apply the Builder Settings plugin In your app module `build.gradle` plugins block: ```gradle plugins { id("com.cometchat.builder.settings") version "5.0.0" } ``` Sync the project to download plugin dependencies. ### Step 4: Add Builder configuration JSON Place `cometchat-builder-settings.json` at your app module root (same level as `build.gradle`). ### Step 5: Build to generate settings and styles Run a build to generate `CometChatBuilderSettings.kt` and add required theme styles: ```bash ./gradlew build ``` ### Step 6: Copy the helper utility Copy `BuilderSettingsHelper.kt` from the sample app into your project package (adjust package name): * Source: `src/main/java/com/cometchat/sampleapp/kotlin/buildersetup/BuilderSettingsHelper.kt` * Destination: `src/main/java//BuilderSettingsHelper.kt` ### Step 7: Add font resources Copy the `font` folder from the sample app into your project under `src/main/res/font`. ### Step 8: Set the Builder theme In `AndroidManifest.xml`: ```xml ... ``` ### Step 9: Apply settings to UI components Use the helper to apply settings on CometChat UI components: ```kotlin BuilderSettingsHelper.applySettingsToMessageHeader(binding.messageHeader) BuilderSettingsHelper.applySettingsToMessageList(binding.messageList) BuilderSettingsHelper.applySettingsToMessageComposer(binding.messageComposer) // Other components BuilderSettingsHelper.applySettingsToUsers(binding.users) BuilderSettingsHelper.applySettingsToCallLogs(binding.callLog) BuilderSettingsHelper.applySettingToGroupMembers(binding.groupMembers) ``` ### Step 10: Access generated constants directly ```kotlin import com.cometchat.builder.CometChatBuilderSettings if (CometChatBuilderSettings.ChatFeatures.CoreMessagingExperience.PHOTOSSHARING) { // Enable photo sharing logic } val brandColor = CometChatBuilderSettings.Style.Color.BRANDCOLOR ``` *** ## Alternative: Import the Sample App as a Module Prefer plug‑and‑play? Import the preconfigured Builder sample app (from README): 1. Download the sample from your CometChat Dashboard. 2. In the imported module’s `AndroidManifest.xml`, keep only `android:name` under `` (or extend your `Application` from `BuilderApplication`). 3. In project Gradle, comment out any CometChat Builder plugin config in the sample. 4. In the sample’s `build.gradle`, remove `com.cometchat.builder.settings`, and change `id("com.android.application")` → `id("com.android.library")`. 5. Import module in Android Studio: File → New → Import Module. 6. Add dependency in your app module: `implementation(project(":builder-android"))`. 7. Add Jetifier in `gradle.properties`: `android.enableJetifier=true`. 8. Ensure CometChat Maven repository is present in `settings.gradle.kts`. 9. Launch activities: * Not initialized / not logged in → `SplashActivity` * Logged in → `HomeActivity` ### Launch Messages screen (examples) For a User: ```kotlin val UID: String = "UID" val intent = Intent(this, MessagesActivity::class.java) CometChat.getUser(UID, object : CometChat.CallbackListener() { override fun onSuccess(user: User?) { intent.putExtra("user", com.google.gson.Gson().toJson(user)) startActivity(intent) } override fun onError(e: CometChatException?) { Log.e("TAG", "Error fetching user: ${e?.message}") } }) ``` For a Group: ```kotlin val GUID: String = "GUID" val intent = Intent(this, MessagesActivity::class.java) CometChat.getGroup(GUID, object : CometChat.CallbackListener() { override fun onSuccess(group: Group?) { intent.putExtra("group", com.google.gson.Gson().toJson(group)) startActivity(intent) } override fun onError(e: CometChatException?) { Log.e("TAG", "Error fetching group: ${e?.message}") } }) ``` *** ## Run the App Build and run on a device/emulator from Android Studio. Ensure a CometChat user is created and logged in via your app logic. *** ## Additional Notes * Ensure features (translation, polls, stickers, whiteboard, document, AI copilot) are enabled in Dashboard → Chat → Features. * If Gradle sync fails to fetch the plugin, verify the plugin version and Maven repo are configured correctly. *** ## Understanding Your Generated Code * `CometChatBuilderSettings.kt`: Type‑safe flags and styling constants generated from your Builder config. * Theme updates: The plugin injects required styles for Builder themes. *** ## Troubleshooting * Plugin not found: Check internet connectivity and use `5.0.0`. * Settings not generated: Confirm JSON path and rebuild (Clean/Build). * Import errors: Verify package names and imports for `BuilderSettingsHelper` and `CometChatBuilderSettings`. *** ## Next Steps * UI Kit Theme: [Theme introduction](/ui-kit/android/theme-introduction) * Components Overview: [UI Kit overview](/ui-kit/android/overview) * Methods & APIs: [Methods & APIs](/ui-kit/android/methods) # CometChat Builder For Android Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/android/overview The CometChat Builder for Android is a powerful way to ship chat faster with native UI that’s modular, customizable, and production‑ready. Configure features visually, export code and styles, and drop them into your Android app with minimal wiring. *** ## Prerequisites * Android Studio (latest recommended) * Android device/emulator with API level 26+ (Android 8.0) * Java 11+ * Internet connectivity (for CometChat services) *** ## Why Choose CometChat Builder? * Rapid integration: Prebuilt native UI and generated settings. * Customizable: Theme, typography, features — all configurable. * Scalable: Built on CometChat’s reliable chat infrastructure. * Native UX: Components designed for Kotlin/Android. *** ## Setup Options Choose one of the following paths to integrate: Get full customization with generated settings using the Gradle plugin. Start quickly with a plug-and-play approach by importing the sample module. *** ## User Interface Preview *** ## Try Live Demo Experience the CometChat Builder in action: *** ## Integration A ready‑to‑use chat experience configured via Chat Builder and powered by our Android UI Kit. **How It Works** * Toggle features like mentions, reactions, media uploads, polls, and more. * Export code, styles, and settings for your app. * Keep iterating — update configs without deep refactors. **Why It’s Great** * Fastest setup with minimal boilerplate. * Continuous customization with a visual configuration. * Fewer moving parts — reliable, pre‑assembled UI. *** ## Next Steps for Developers 1. Learn the basics — Key Concepts: [Key Concepts](/fundamentals/key-concepts) 2. Follow the setup guide — Chat Builder (Android): [Integration](/chat-builder/android/integration) 3. Customize UI — Theme and components: [Theme introduction](/ui-kit/android/theme-introduction), [UI Kit overview](/ui-kit/android/overview) 4. Test & ship — Run on device/emulator and deploy. *** ## Helpful Resources Explore these resources to go deeper with CometChat on Android. Experience the power of CometChat UI Kit with this interactive app Access the complete Android UI Kit source code. UI design resources for customization and prototyping. View on Figma *** ## Need Help? If you need assistance, check out: * Developer Community: [http://community.cometchat.com/](http://community.cometchat.com/) * Support Portal: [https://help.cometchat.com/hc/en-us/requests/new](https://help.cometchat.com/hc/en-us/requests/new) # Getting Started With Chat Builder Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/ios/integration Chat Builder simplifies integrating CometChat’s iOS UI Kit using Visual Chat Builder (VCB) configuration. Design your experience, export settings, and wire them into your app via JSON or QR‑based live sync. ## Complete Integration Workflow 1. Design your chat experience in Chat Builder. 2. Export your code/settings or connect via QR. 3. Enable extra features in the CometChat Dashboard if needed. 4. Optionally preview on device/simulator. 5. Integrate into your Xcode project. 6. Customize further with UI Kit styling and components. *** ## Launch the Chat Builder 1. Log in to your CometChat Dashboard: [https://app.cometchat.com](https://app.cometchat.com) 2. Select your application. 3. Go to Integrate → iOS → Launch Chat Builder. *** ## Enable Features in CometChat Dashboard If your app needs any of these, enable them from your Dashboard: [https://app.cometchat.com](https://app.cometchat.com) * Stickers * Polls * Collaborative whiteboard * Collaborative document * Message translation * AI User Copilot: Conversation starter, Conversation summary, Smart reply How to enable: 1. Log in to the Dashboard. 2. Select your app. 3. Navigate to Chat → Features. 4. Toggle ON the required features and Save. *** ## Integration with CometChat Chat Builder (iOS) Installation and configuration options from README‑iOS: ### Install the Builder package ```ruby pod 'CometChatBuilder' ``` ```bash pod install ``` 1. In Xcode: File → Add Packages. 2. Enter your repository URL (or local path) for `CometChatBuilder`. 3. Add the package to your app target. ### Option 1: Load from JSON (no‑code) 1. Add `cometchat-builder-settings.json` to your app target (ensure it’s in Target Membership). 2. Load settings at launch: ```swift import CometChatBuilder func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { CometChatBuilderSettings.loadFromJSON() return true } ``` ### Option 2: Load via QR Code (live Builder sync) 1. Start scanning from a view controller to sync settings for the current device build: ```swift import CometChatBuilder CometChatBuilder.startScanning(from: self) { appliedStyle in // Apply theme or reload UI if needed print("Chat Builder Style Applied:", appliedStyle.theme) } ``` The SDK will open a QR scanner, fetch settings, and apply them. It handles loading UI and error fallbacks. *** ## Run the App Build and run on simulator or device from Xcode. Ensure your CometChat initialization and user login logic are in place in your app. *** ## Understanding Your Builder Settings VCB configuration spans: * Core messaging experience (typing, media sharing, replies) * Deeper user engagement (reactions, mentions, translation, polls) * AI User Copilot (smart replies, summaries, starters) * Group management * Moderator controls * Voice & video calling * Layout & styling (theme, typography, layout) *** ## Troubleshooting * For JSON: ensure the file is included in your app bundle’s Target Membership. * For QR: confirm a valid code from the Builder and active network. * For SPM: confirm package resources are available to your target. If you need a reference app to compare against, see the iOS UI Kit Sample App: [https://github.com/cometchat/cometchat-uikit-ios/tree/v5/SampleApp](https://github.com/cometchat/cometchat-uikit-ios/tree/v5/SampleApp) *** ## Next Steps * UI Kit Theme: [Theme introduction](/ui-kit/ios/theme-introduction) * Components Overview: [Components overview](/ui-kit/ios/overview) * Methods & APIs: [Methods & APIs](/ui-kit/ios/methods) # CometChat Builder For iOS Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/ios/overview The CometChat Builder for iOS helps you deliver a complete chat experience quickly with prebuilt, customizable native UI. Configure features visually, export platform‑ready settings, and integrate them into your iOS app. *** ## Prerequisites * Xcode (latest recommended) * iOS 14+ target (or your project’s minimum supported iOS) * Swift 5.7+ (or compatible Swift toolchain) * CocoaPods or Swift Package Manager * Internet connectivity (for CometChat services) *** ## Why Choose CometChat Builder? * Rapid integration: Prebuilt native UI and generated settings. * Customizable: Theme, typography, and features via configuration. * Scalable: Backed by CometChat’s reliable chat infrastructure. * Native UX: Components built for iOS. *** ## Setup Options Choose one of the following paths to integrate: * **Load settings via Builder (recommended)**: Use the CometChatBuilder package and load settings via JSON or live QR sync. See: [Install the Builder package](/chat-builder/ios/integration#integration-with-cometchat-chat-builder-ios), Configure settings quickly by importing a JSON file, no coding required. Sync settings directly from the Builder using a live QR code. * **Start from the iOS Sample App**: Use the UI Kit sample to explore structure and patterns, then add the Builder package. See: [iOS Sample App](https://github.com/cometchat/cometchat-uikit-ios/tree/v5/SampleApp) *** ## User Interface Preview *** ## Try Live Demo Experience the CometChat Builder in action: *** ## Integration Ship a ready‑to‑use chat experience configured in the Builder and powered by our iOS UI Kit. **How It Works** * Toggle features like mentions, reactions, media uploads, polls, and more. * Export settings/styles and wire them into your iOS app. * Iterate quickly without large refactors. **Why It’s Great** * Fastest setup with minimal wiring. * Visual configuration for continuous customization. * Reliable, pre‑assembled UI. *** ## Next Steps for Developers 1. Learn the basics — Key Concepts: [Key Concepts](/fundamentals/key-concepts) 2. Follow the setup guide — Chat Builder (iOS): [Chat Builder (iOS)](/chat-builder/ios/integration) 3. Customize UI — Theme and components: [Theme introduction](/ui-kit/ios/theme-introduction), [Components overview](/ui-kit/ios/overview) 4. Test & ship — Run on device/simulator and deploy. *** ## Helpful Resources Experience the power of CometChat UI Kit with this interactive app. Explore the complete iOS UI Kit source code. View on GitHub UI design resources for customization and prototyping. View on Figma *** ## Need Help? * Developer Community: [http://community.cometchat.com/](http://community.cometchat.com/) * Support Portal: [https://help.cometchat.com/hc/en-us/requests/new](https://help.cometchat.com/hc/en-us/requests/new) # Customizing Your Chat Builder Integration Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/nextjs/builder-customisations While the `CometChatSettings.ts` file allows basic toggling of features in the Chat Builder, **deeper customizations** require a more hands-on approach. Follow the steps below to tailor the UI Kit to your exact needs. *** ## **How to Customize Components** 1. **Refer to the UI Kit Documentation**\ Browse the [**UI Kit components overview**](/ui-kit/react/components-overview) to find the component you'd like to customize.\ *Example*: [**Message List**](/ui-kit/react/message-list) 2. **Locate Customization Options**\ Once you've identified the component, explore its props and features within the documentation.\ *Example*: [**Sticky DateTime Format**](/ui-kit/react/message-list#sticky-datetime-format) 3. **Update Props or Modify Code**\ Use supported props to tweak behavior or look. For advanced changes, navigate through the folder structure and directly edit component logic or styling. *** Applying Customizations Changes made to the Chat Builder settings or components **will not reflect automatically** in your app.\ If you make additional modifications in the Chat Builder after initial setup: * Re-download the updated code package * Reintegrate it into your application This ensures all customizations are applied correctly. *** ## **Example: Customizing Date & Time Format in Message List** ### Goal Update how the sticky date headers appear in the chat message list. ### Step-by-Step 1. **Component to Customize**:\ [Message List](/ui-kit/react/message-list) 2. **Customization Option**:\ [`stickyDateTimeFormat`](/ui-kit/react/message-list#sticky-datetime-format) 3. **Apply the Prop**: ```javascript import { CometChatMessageList, CalendarObject } from "@cometchat/chat-uikit-react"; function getDateFormat() { return new CalendarObject({ today: `hh:mm A`, // e.g., "10:30 AM" yesterday: `[Yesterday]`, // Displays literally as "Yesterday" otherDays: `DD/MM/YYYY`, // e.g., "25/05/2025" }); } ``` *** ### Default Format Used ```javascript new CalendarObject({ today: "today", yesterday: "yesterday", otherDays: "DD MMM, YYYY", // e.g., "25 Jan, 2025" }); ``` *** Why Customize This? Sticky date headers enhance the chat experience by improving message navigation and giving users better temporal context. Adjust the format based on your target locale, tone of voice, or branding needs. *** # CometChat Chat Builder Directory Structure Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/nextjs/builder-dir-structure This document provides an overview of the CometChat Chat Builder directory structure, helping you understand the organization of the project and where to find specific files when you need to customize or extend functionality. ## Overview The CometChat Chat Builder follows a modular structure organized by feature and functionality. All Chat Builder files are contained within the `src/CometChat/` directory. ``` src/ ├── CometChat/ │ ├── assets/ │ ├── components/ │ ├── context/ │ ├── locales/ │ ├── styles/ │ ├── utils/ │ ├── CometChatApp.tsx │ ├── CometChatSettings.ts │ ├── customHooks.ts │ ├── decl.d.ts │ └── styleConfig.ts ├── App.css ├── App.tsx └── index.tsx ``` ## Directory Details ### Root Files | File | Description | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `CometChatApp.tsx` | The main entry point for the Chat Builder application. This is the component you import in your project to render the chat experience. | | `CometChatSettings.ts` | Contains configuration settings for the Chat Builder, including UI elements, features, and theming options. | | `customHooks.ts` | Custom React hooks used throughout the application. | | `decl.d.ts` | TypeScript declaration file for type definitions. | | `styleConfig.ts` | Configuration file for styling across the application. | ### Key Directories #### `assets/` Contains UI resources like icons, images, and audio files used throughout the application. ``` assets/ │ ├── chats.svg │ ├── calls.svg │ ├── users.svg │ ├── groups.svg │ └── (Other UI icons and images) ``` #### `components/` Contains all React components that make up the UI of the Chat Builder. ``` components/ ├── CometChatAddMembers/ │ ├── CometChatAddMembers.tsx │ └── useCometChatAddMembers.ts ├── CometChatAlertPopup/ │ └── CometChatAlertPopup.tsx ├── CometChatBannedMembers/ │ └── CometChatBannedMembers.tsx ├── CometChatCallLog/ │ ├── CometChatCallLogDetails.tsx │ ├── CometChatCallLogHistory.tsx │ ├── CometChatCallLogInfo.tsx │ ├── CometChatCallLogParticipants.tsx │ └── CometChatCallLogRecordings.tsx ├── CometChatCreateGroup/ │ └── CometChatCreateGroup.tsx ├── CometChatDetails/ │ ├── CometChatThreadedMessages.tsx │ └── CometChatUserDetails.tsx ├── CometChatHome/ │ └── CometChatHome.tsx ├── CometChatJoinGroup/ │ └── CometChatJoinGroup.tsx ├── CometChatLogin/ │ ├── CometChatAppCredentials.tsx │ ├── CometChatLogin.tsx │ └── sampledata.ts ├── CometChatMessages/ │ ├── CometChatEmptyStateView.tsx │ └── CometChatMessages.tsx ├── CometChatSelector/ │ ├── CometChatSelector.tsx │ └── CometChatTabs.tsx └── CometChatTransferOwnership/ ├── CometChatTransferOwnership.tsx └── useCometChatTransferOwnership.ts ``` Each component folder typically contains: * The main component file (`.tsx`) * Associated hook files (`use*.ts`) for component logic * Subcomponents specific to that feature area #### `context/` Contains React Context providers used for state management across the application. ```python context/ ├── AppContext.tsx # Main application context ├── CometChatContext.tsx # Context for builder settings └── appReducer.ts # Reducer functions for AppContext ``` #### `locales/` Contains translations for different languages, enabling localization of the UI. ```bash locales/ (Contains translations for different languages) ├── en/en.json ├── fr/fr.json ├── de/de.json └── (Other language JSON files) ``` #### `styles/` Contains CSS files for styling components, organized to mirror the components directory structure. ``` styles/ ├── CometChatAddMembers/ │ └── CometChatAddMembers.css ├── CometChatAlertPopup/ │ └── CometChatAlertPopup.css ├── CometChatBannedMembers/ │ └── CometChatBannedMembers.css ├── CometChatCallLog/ │ ├── CometChatCallLogDetails.css │ ├── CometChatCallLogHistory.css │ ├── CometChatCallLogInfo.css │ ├── CometChatCallLogParticipants.css │ └── CometChatCallLogRecordings.css ├── CometChatCreateGroup/ │ └── CometChatCreateGroup.css ├── CometChatDetails/ │ ├── CometChatDetails.css │ ├── CometChatThreadedMessages.css │ └── CometChatUserDetails.css ├── CometChatLogin/ │ ├── CometChatAppCredentials.css │ └── CometChatLogin.css ├── CometChatMessages/ │ ├── CometChatEmptyStateView.css │ └── CometChatMessages.css ├── CometChatNewChat/ │ └── CometChatNewChatView.css ├── CometChatSelector/ │ ├── CometChatSelector.css │ └── CometChatTabs.css ├── CometChatTransferOwnership/ │ └── CometChatTransferOwnership.css └── CometChatApp.css ``` #### `utils/` Contains utility functions and helpers used across the application. ```python utils/ └── utils.ts # General utility functions ``` ## Key Components Overview * **CometChatHome**: Main dashboard component that serves as the entry point for the chat experience * **CometChatMessages**: Core component for displaying and managing chat messages * **CometChatCallLog**: Components for call history and details * **CometChatDetails**: User and group details and settings * **CometChatLogin**: Authentication-related components * **CometChatSelector/CometChatTabs**: Navigation and tab-based interface components ## Customization Points When customizing the Chat Builder, you'll typically work with: 1. **`CometChatSettings.ts`**: To modify high-level configuration 2. **`styleConfig.ts`**: To change theme colors, fonts, and other styling variables 3. **Component styles**: To make specific UI adjustments to individual components 4. **Locale files**: To modify text strings or add new language support ## Recommendations for Modifications * Avoid direct modification of core components when possible * Use the settings files for configuration changes * Use CSS overrides for styling customizations * For extensive customizations, consider creating wrapper components that use the Chat Builder components as children *** ## **Conclusion** This structured breakdown of the **CometChat Chat Builder directory** helps developers understand the project layout, making it easier to navigate, extend, and customize as needed. For further customization and integration details, refer to: * **[Builder Configuration File](/ui-kit/react/builder-settings)** – Learn how to customize your integration. * **[Advanced Theming](/ui-kit/react/theme)** – Modify themes and UI elements to match your brand. # CometChat Settings Guide Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/nextjs/builder-settings The `CometChatSettings.ts` file defines configuration options for **[CometChat Builder](https://preview.cometchat.com/)**, giving developers full control over messaging capabilities, AI enhancements, UI layout, styling, and moderation tools. *** ## **1. Chat Features** ### Core Messaging Experience These options enable essential messaging functionalities: ```json "coreMessagingExperience": { "typingIndicator": true, "threadConversationAndReplies": true, "photosSharing": true, "videoSharing": true, "audioSharing": true, "fileSharing": true, "editMessage": true, "deleteMessage": true, "messageDeliveryAndReadReceipts": true, "userAndFriendsPresence": true } ``` * **`typingIndicator`** → Displays when a user is typing. * **`threadConversationAndReplies`** → Enables threaded replies. * **Media Sharing**: `photosSharing`, `videoSharing`, `audioSharing`, `fileSharing` * **Editing**: `editMessage`, `deleteMessage` * **Status**: `messageDeliveryAndReadReceipts`, `userAndFriendsPresence` *** ### Deeper User Engagement Enhance user interaction with richer messaging options: ```json "deeperUserEngagement": { "mentions": true, "reactions": true, "messageTranslation": true, "polls": true, "collaborativeWhiteboard": false, "collaborativeDocument": false, "voiceNotes": false, "emojis": true, "stickers": true, "userInfo": true, "groupInfo": true } ``` * **`mentions`** → Tag users using @mention. * **`reactions`** → Emoji reactions to messages. * **`messageTranslation`** → Instant translation of messages. * **`polls`** → Create and vote on polls. * **`collaborativeWhiteboard`**, **`collaborativeDocument`** → Real-time co-creation (currently disabled). * **`voiceNotes`** → Send recorded voice messages (currently disabled). * **`emojis`, `stickers`** → Express with visual elements. * **`userInfo`, `groupInfo`** → Enable viewing detailed user and group profiles. *** ### AI User Copilot AI-powered tools to boost communication efficiency: ```json "aiUserCopilot": { "conversationStarter": true, "conversationSummary": true, "smartReply": true } ``` * **`conversationStarter`** → AI-suggested chat openers. * **`conversationSummary`** → Summarize long threads automatically. * **`smartReply`** → AI-generated quick replies. *** ### Group Management Enable users to manage groups and members: ```json "groupManagement": { "createGroup": true, "addMembersToGroups": true, "joinLeaveGroup": true, "deleteGroup": true, "viewGroupMembers": true } ``` * Create, join, leave, or delete groups. * View members and add new ones. *** ### Moderator Controls Give moderators the tools to manage group integrity: ```json "moderatorControls": { "kickUsers": true, "banUsers": true, "promoteDemoteMembers": true } ``` * Kick or ban misbehaving users. * Change user roles (admin/member). *** ### Private Messaging within Groups One-on-one messaging inside group chats: ```json "privateMessagingWithinGroups": { "sendPrivateMessageToGroupMembers": true } ``` * Allows sending private DMs to group participants directly from the group context. *** ## **2. Call Features** Control real-time voice and video communication: ```json "callFeatures": { "voiceAndVideoCalling": { "oneOnOneVoiceCalling": true, "oneOnOneVideoCalling": true, "groupVideoConference": true, "groupVoiceConference": true } } ``` * **One-on-One**: Voice and video calling. * **Group**: Video conferencing and voice-only calls. *** ## **3. Layout Customization** Customize how the chat UI looks and navigates: ```json "layout": { "withSideBar": true, "tabs": ["chats", "groups", "users", "calls"], "chatType": "user" } ``` * **`withSideBar`** → Show/hide the sidebar. * **`tabs`** → Define which sections (and order) are present in navigation. * **`chatType`** → Default view: `"user"` or `"group"` chat. *** ## **4. Styling & Theme Customization** Manage the look & feel of the chat experience. ```json "style": { "theme": "system", "color": { "brandColor": "#df4343", "primaryTextLight": "#df4343", "primaryTextDark": "#FFFFFF", "secondaryTextLight": "#727272", "secondaryTextDark": "#989898" }, "typography": { "font": "Sans-serif", "size": "Default" } } ``` ### Theme * **`theme`**: `"system"` (inherits from OS), `"light"`, or `"dark"`. ### Colors * **`brandColor`** → Accent color used throughout UI. * **Text Colors**: Separate values for light and dark mode (`primaryText*`, `secondaryText*`). ### Typography * **`font`** → Global font family. * **`size`** → `"Default"`, `"Compact"`, or `"Comfortable"`. *** ## **Summary** The `CometChatSettings.ts` file gives you **end-to-end configuration** of your CometChat-powered app—from feature toggles to layout and theming. Use this guide as your go-to reference when: * Customizing chat or call functionality * Enabling AI features * Managing group or user interactions * Personalizing the UI for your brand *** ## **Related Links** * [Directory Structure](/ui-kit/react/builder-dir-structure) * [Advanced Theming](/ui-kit/react/theme) # Getting Started With Chat Builder Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/nextjs/integration **Chat Builder** is a powerful tool designed to simplify the integration of CometChat's UI Kit into your existing React application. With the **Chat Builder**, you can quickly set up chat functionalities, customize UI elements, and integrate essential features without extensive coding. ## **Complete Integration Workflow** 1. **Design Your Chat Experience** - Use the Chat Builder to customize layouts, features, and styling. 2. **Export Your Code** - Once satisfied, download the generated code package. 3. **Enable Features** - Enable additional features in the CometChat Dashboard if required. 4. **Preview Customizations** - Optionally, preview the chat experience before integrating it into your project. 5. **Integration** - Integrate into your existing application. 6. **Customize Further** - Explore advanced customization options to tailor the chat experience. *** ## **Launch the Chat Builder** 1. Log in to your [**CometChat Dashboard**](https://app.cometchat.com). 2. Select your application from the list. 3. Navigate to **Integrate** > **React** > **Launch Chat Builder**. *** ## **Enable Features in CometChat Dashboard** If your app requires any of the following features, make sure to enable them from the **[CometChat Dashboard](https://app.cometchat.com/)** * **Stickers** – Allow users to send expressive stickers. * **Polls** – Enable in-chat polls for user engagement. * **Collaborative Whiteboard** – Let users draw and collaborate in real time. * **Collaborative Document** – Allow multiple users to edit documents together. * **Message Translation** – Translate messages between different languages. * **AI User Copilot** * Conversation Starter – Suggests conversation openers. * Conversation Summary – Generates AI-powered chat summaries. * Smart Reply – Provides quick reply suggestions. ### **How to Enable These Features?** 1. Log in to your **[CometChat Dashboard](https://app.cometchat.com)** 2. Select your application. 3. Navigate to **Chat > Features**. 4. Toggle **ON** the required features. 5. Click **Save Changes**. *** ## **Preview Customizations (Optional)** Before integrating the Chat Builder into your project, you can preview the chat experience by following these steps. This step is completely optional and can be skipped if you want to directly integrate the Chat Builder into your project. > You can preview the experience: > > 1. Open the `cometchat-app-react` folder. > 2. Add credentials for your app in `src/index.tsx`: > > ```javascript > export const COMETCHAT_CONSTANTS = { > APP_ID: "", // Replace with your App ID > REGION: "", // Replace with your App Region > AUTH_KEY: "", // Replace with your Auth Key or leave blank if you are authenticating using Auth Token > }; > ``` > > 3. Install dependencies: > > ``` > npm i > ``` > > 4. Run the app: > > ```powershell > npm start > ``` *** ## **Integration with CometChat Chat Builder (Next.js)** ### **Step 1: Install Dependencies** ```ruby npm install @cometchat/chat-uikit-react@6.2.3 @cometchat/calls-sdk-javascript ``` ### **Step 2: Copy CometChat Folder** Copy the `cometchat-app-react/src/CometChat` folder inside your `src/app` directory. *** ### **Step 3: Create & Initialize `CometChatNoSSR.tsx`** Directory Structure: ```swift src/app/ ├── CometChat/ └── CometChatNoSSR/ └── CometChatNoSSR.tsx ``` src/app/CometChatNoSSR/CometChatNoSSR.tsx ```javascript import React, { useEffect } from "react"; import { CometChatUIKit, UIKitSettingsBuilder, } from "@cometchat/chat-uikit-react"; import CometChatApp from "../CometChat/CometChatApp"; import { CometChatProvider } from "../CometChat/context/CometChatContext"; import { setupLocalization } from "../CometChat/utils/utils"; export const COMETCHAT_CONSTANTS = { APP_ID: "", // Replace with your App ID REGION: "", // Replace with your App Region AUTH_KEY: "", // Replace with your Auth Key or leave blank if you are authenticating using Auth Token }; const CometChatNoSSR: React.FC = () => { useEffect(() => { const UIKitSettings = new UIKitSettingsBuilder() .setAppId(COMETCHAT_CONSTANTS.APP_ID) .setRegion(COMETCHAT_CONSTANTS.REGION) .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) .subscribePresenceForAllUsers() .build(); CometChatUIKit.init(UIKitSettings) ?.then(() => { setupLocalization(); console.log("Initialization completed successfully"); }) .catch((error) => console.error("Initialization failed", error)); }, []); return (
); }; export default CometChatNoSSR; ``` *** ### **Step 4: User Login** To authenticate a user, you need a **`UID`**. You can either: 1. **Create new users** on the **[CometChat Dashboard](https://app.cometchat.com)**, **[CometChat SDK Method](/ui-kit/react/methods#create-user)** or **[via the API](https://api-explorer.cometchat.com/reference/creates-user)**. 2. **Use pre-generated test users**: * `cometchat-uid-1` * `cometchat-uid-2` * `cometchat-uid-3` * `cometchat-uid-4` * `cometchat-uid-5` The **Login** method returns a **User object** containing all relevant details of the logged-in user. *** **Security Best Practices** * The **Auth Key** method is recommended for **proof-of-concept (POC) development** and early-stage testing. * For **production environments**, it is strongly advised to use an **[Auth Token](/ui-kit/react/methods#login-using-auth-token)** instead of an **Auth Key** to enhance security and prevent unauthorized access. **User Login After Initialization** Once the CometChat UI Kit is initialized, you can log in the user **whenever it fits your app’s workflow.** ```ts import { CometChatUIKit } from "@cometchat/chat-uikit-react"; const UID = "UID"; // Replace with your actual UID CometChatUIKit.getLoggedinUser().then((user: CometChat.User | null) => { if (!user) { // If no user is logged in, proceed with login CometChatUIKit.login(UID) .then((user: CometChat.User) => { console.log("Login Successful:", { user }); // Mount your app }) .catch(console.log); } else { // If user is already logged in, mount your app } }); ``` However, **if you prefer to log in the user immediately after initialization,** you can do so within the then block of CometChatUIKit.init(). ```ts import React, { useEffect } from "react"; import { CometChatUIKit, UIKitSettingsBuilder, } from "@cometchat/chat-uikit-react"; import CometChatApp from "../CometChat/CometChatApp"; import { CometChatProvider } from "../CometChat/context/CometChatContext"; import { setupLocalization } from "../CometChat/utils/utils"; export const COMETCHAT_CONSTANTS = { APP_ID: "", // Replace with your App ID REGION: "", // Replace with your App Region AUTH_KEY: "", // Replace with your Auth Key or leave blank if you are authenticating using Auth Token }; const CometChatNoSSR: React.FC = () => { useEffect(() => { const UIKitSettings = new UIKitSettingsBuilder() .setAppId(COMETCHAT_CONSTANTS.APP_ID) .setRegion(COMETCHAT_CONSTANTS.REGION) .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) .subscribePresenceForAllUsers() .build(); CometChatUIKit.init(UIKitSettings) ?.then(() => { setupLocalization(); console.log("Initialization completed successfully"); const UID = "UID"; // Replace with your actual UID CometChatUIKit.getLoggedinUser().then((user: CometChat.User | null) => { if (!user) { // If no user is logged in, proceed with login CometChatUIKit.login(UID) .then((loggedInUser: CometChat.User) => { console.log("Login Successful:", loggedInUser); // Mount your app or perform post-login actions if needed }) .catch((error) => { console.error("Login failed:", error); }); } else { console.log("User already logged in:", user); } }); }) .catch((error) => console.error("Initialization failed", error)); }, []); return (
); }; export default CometChatNoSSR; ```
*** ### **Step 5: Disable SSR & Render CometChat Component** In this step, we’ll render the `CometChatApp` component and specifically disable **Server-Side Rendering (SSR)** for `CometChatNoSSR.tsx`. This targeted approach ensures the CometChat Chat Builder components load only on the client side, while the rest of your application remains fully compatible with SSR. 1. **Create a Wrapper File**: Add a new file that houses the `CometChatApp` component. 2. **Dynamically Import `CometChatNoSSR.tsx`**: In this file, use dynamic imports with `{ ssr: false }` to disable SSR only for the CometChat component, preventing SSR-related issues but preserving SSR for the rest of your code. ```javascript "use client"; import dynamic from "next/dynamic"; // Dynamically import CometChat component with SSR disabled const CometChatComponent = dynamic( () => import("../app/CometChatNoSSR/CometChatNoSSR"), { ssr: false, } ); export default function CometChatAppWrapper() { return (
); } ``` Now, import and use the wrapper component in your project’s main entry file. ```javascript import CometChatAppWrapper from "./CometChatAppWrapper"; export default function Home() { return ( <> {/* Other components or content */} ); } ``` Why disable SSR? CometChat Chat Builder relies on browser APIs like `window`, `document`, and WebSockets. Since Next.js renders on the server by default, we disable SSR for this component to avoid runtime errors. #### **Render with Default User and Group** You can also render the component with default user and group selection: ```javascript import React, { useEffect, useState } from "react"; import { CometChatUIKit, UIKitSettingsBuilder, } from "@cometchat/chat-uikit-react"; import CometChatApp from "../CometChat/CometChatApp"; import { CometChatProvider } from "../CometChat/context/CometChatContext"; import { setupLocalization } from "../CometChat/utils/utils"; import { CometChat } from "@cometchat/chat-sdk-javascript"; export const COMETCHAT_CONSTANTS = { APP_ID: "", // Replace with your App ID REGION: "", // Replace with your App Region AUTH_KEY: "", // Replace with your Auth Key or leave blank if you are authenticating using Auth Token }; // Functional Component const CometChatNoSSR: React.FC = () => { const [user, setUser] = useState(undefined); const [selectedUser, setSelectedUser] = useState( undefined ); const [selectedGroup, setSelectedGroup] = useState< CometChat.Group | undefined >(undefined); useEffect(() => { const UIKitSettings = new UIKitSettingsBuilder() .setAppId(COMETCHAT_CONSTANTS.APP_ID) .setRegion(COMETCHAT_CONSTANTS.REGION) .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) .subscribePresenceForAllUsers() .build(); // Initialize CometChat UIKit CometChatUIKit.init(UIKitSettings) ?.then(() => { setupLocalization(); console.log("Initialization completed successfully"); CometChatUIKit.getLoggedinUser().then((loggedInUser) => { if (!loggedInUser) { CometChatUIKit.login("cometchat-uid-1") // Replace with your logged in user UID .then((user) => { console.log("Login Successful", { user }); setUser(user); }) .catch((error) => console.error("Login failed", error)); } else { console.log("Already logged-in", { loggedInUser }); setUser(loggedInUser); } }); }) .catch((error) => console.error("Initialization failed", error)); }, []); useEffect(() => { if (user) { // Fetch user or group from CometChat SDK whose chat you want to load. /** Fetching User */ const UID = "cometchat-uid-2"; // Replace with your actual UID CometChat.getUser(UID).then( (user) => { setSelectedUser(user); }, (error) => { console.log("User fetching failed with error:", error); } ); /** Fetching Group */ // const GUID = "cometchat-guid-1"; // Replace with your actual GUID // CometChat.getGroup(GUID).then( // (group) => { // setSelectedGroup(group); // }, // (error) => { // console.log("User fetching failed with error:", error); // } // ); } }, [user]); return ( /* The CometChatApp component requires a parent element with an explicit height and width to render properly. Ensure the container has defined dimensions, and adjust them as needed based on your layout requirements. */
{(selectedUser || selectedGroup) && ( )}
); }; export default CometChatNoSSR; ``` When you enable the **Without Sidebar** option for the Sidebar, the following behavior applies: * **User Chats (`chatType = "user"`)**: Displays one-on-one chats only, either for a currently selected user or the default user. * **Group Chats (`chatType = "group"`)**: Displays group chats exclusively, either for a currently selected group or the default group. *** ### **Step 6: Run Your App** Start your development server: ``` npm run dev ``` *** ## **Additional Configuration Notes** Ensure the following features are also turned on in your app > Chat > Features for full functionality: * Message translation * Polls * Stickers * Collaborative whiteboard * Collaborative document * Conversation starter * Conversation summary * Smart reply If you face any issues while integrating the builder in your app project, please check if you have the following configurations added to your `tsConfig.json`: ```json { "compilerOptions": { "jsx": "react-jsx", "resolveJsonModule": true } } ``` If your development server is running, restart it to ensure the new TypeScript configuration is picked up. *** ## **Understanding Your Generated Code** The exported package includes several important elements to help you further customize your chat experience: ### **Directory Structure** The `CometChat` folder contains: * **Components** - Individual UI elements (message bubbles, input fields, etc.) * **Layouts** - Pre-configured arrangement of components * **Context** - State management for your chat application * **Hooks** - Custom React hooks for chat functionality * **Utils** - Helper functions and configuration ### **Configuration Files** * **CometChat Settings File** - Controls the appearance and behavior of your chat UI * **Theme Configuration** - Customize colors, typography, and spacing * **Localization Files** - Add support for different languages *** ## **Next Steps** Now that you've set up your **chat experience**, explore further configuration options: * **[Builder Configuration File](/ui-kit/react/builder-settings)** – Learn how to customize your integration. * **[Builder Directory Structure](/ui-kit/react/builder-dir-structure)** – Understand the organization of the builder components. * **[Advanced Theming](/ui-kit/react/theme)** – Modify themes and UI elements to match your brand. * **[Additional Customizations](/ui-kit/react/builder-customisations)** – Customise the UI the way you want. *** # CometChat Chat Builder For Next.js Source: https://cometchat-22654f5b-docs-restapi-chatapi-quotedmessages.mintlify.app/chat-builder/nextjs/overview The **CometChat Chat Builder** for Next.js is a powerful solution designed to seamlessly integrate chat functionality into applications. It provides a robust set of **prebuilt UI components** that are **modular, customizable, and highly scalable**, allowing developers to accelerate their development process with minimal effort. *** ## **Why Choose CometChat Chat Builder?** * **Rapid Integration** – Prebuilt UI components for faster deployment. * **Customizable & Flexible** – Modify the UI to align with your brand’s identity. * **Cross-Platform Compatibility** – Works seamlessly across various React-based frameworks. * **Scalable & Reliable** – Built on CometChat's **robust chat infrastructure** for enterprise-grade performance. *** ## **User Interface Preview** *** ## **Try Live Demo** **Experience the CometChat Chat Builder in action:** *** ## **Integration Options** A ready-to-use chat interface—configured via a Chat Builder—built on top of our UI Kits. **How It Works** * Toggle features like @mentions, reactions, media uploads, and more in a visual interface. * Drag-and-drop or point-and-click to enable or disable components. * Customize layouts and styles—no deep coding required. **Why It’s Great** * **Fastest Setup** – Minimal component wiring. * **Continuous Customization** – Only turn on the features you want. * **Fewer Moving Parts** – Reliable, pre-assembled UI that’s easy to maintain. } href="/ui-kit/react/builder-integration" horizontal /> } href="/ui-kit/react/builder-integration-nextjs" horizontal /> } href="/ui-kit/react/builder-integration-react-router" horizontal /> *** ### **Option 2: UI Components (Assemble It Yourself)** */} A collection of individual components—like conversation lists, message lists, message composer, etc.—each with built-in chat logic so you can customize every element.