Skip to main content
Custom providers let you route push payloads to your own webhook instead of FCM/APNs. Use this page to set up credentials, understand payload shapes, and wire a simple receiver.

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:
Authorization: Basic <Base64-encoded-credentials>
  1. 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.
  2. 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:
{
  "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"
}

Sample server-side code

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;
  const { to } = data || {};

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