Skip to main content
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:
Authorization: Basic <Base64-encoded-credentials>

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. 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.
{
  "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"
}

Sample server-side code

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());

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 (!uid) throw new Error('Missing data.to.uid');
  if (!smsContent) throw new Error('Missing data.smsContent');

  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) {
    phno = await fetchPhoneNumberFor(uid);
  }

  if (!phno) throw new Error(`Phone number not available for uid=${uid}`);

  return await sendSMS(phno, smsContent);
};

app.post('/webhook', basicAuth, (req, res) => {
  const { trigger, data, appId, region, webhook } = req.body || {};
  const { to } = data || {};

  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}`);
});