Skip to main content

Seamlessly Integrate Your CRM with Webhooks

· 4 min read
Vadim Ruban
Software Engineer

This guide will help you integrate a CRM with the Wildix platform using webhooks. The integration will ensure that when a call between a customer and an agent ends, an activity is automatically added to the specific customer in your CRM. We will use Pipedrive as an example CRM in this guide. The webhook will be triggered upon call completion. Additionally, we will configure Ngrok to provide a public HTTPS endpoint for local development and add a step to verify the webhook signature.

Prerequisites

  • Node.js installed on your server.
  • A CRM account (Pipedrive in this case).
  • API access and tokens for your CRM.
  • Ngrok installed for public HTTPS tunneling.
  • A server to run the integration script (we will use Express.js in Node.js).

Step-by-Step Guide

Step 1: Setting Up the Server

  1. Install Node.js and npm if not already installed. Follow the installation instructions from the official Node.js website: Node.js.

  2. Create a new project directory and navigate to it in your terminal:

    mkdir wildix-crm-integration
    cd wildix-crm-integration
  3. Initialize a new Node.js project:

    npm init -y
  4. Install necessary dependencies:

    npm install express @wildix/wda-stream-client pipedrive ngrok

Step 2: Creating the Integration Script

Create a file named index.js in your project directory and add the following code:

import { WebhookCallCompletedEvent, WebhookEventType } from '@wildix/wda-stream-client';
import express, { Request, Response } from 'express';
import { ActivitiesApi, ActivityPostObject, ApiClient } from 'pipedrive';
import crypto from 'crypto';
import ngrok from 'ngrok';

const app = express();
const port = 3100;

// Pipedrive API setup
const apiClient = new ApiClient();
const apiToken = apiClient.authentications.api_key;
apiToken.apiKey = 'YOUR_API_TOKEN_HERE'; // Replace with your Pipedrive API token
const activitiesApi = new ActivitiesApi(apiClient);

// Middleware to parse JSON
app.use(express.json());

// Verify the webhook signature
function verifySignature(req, secret) {
const signature = req.headers['x-signature'];
const hash = crypto.createHmac('sha256', secret).update(JSON.stringify(req.body)).digest('hex');
return signature === hash;
}

// Process call completed event and create activities in Pipedrive
async function processCallCompletedEvent(event) {
const promises = event.data.flows.map(async (flow) => {
const callerName = flow.caller?.name || flow.caller?.phone || 'unknown';
const calleeName = flow.callee?.name || flow.callee?.phone || 'unknown';
const endDate = new Date(flow.endTime);

const activityData = ActivityPostObject.constructFromObject({
subject: `Call with ${callerName} and ${calleeName}`,
type: 'call',
done: 1,
note: `Call completed between ${callerName} and ${calleeName}. Duration: ${flow.duration} seconds.`,
due_date: endDate.toISOString().split('T')[0],
due_time: endDate.toISOString().split('T')[1].split('.')[0],
// Fill other options that relate to your structure.
// person_id: '<person_id>',
// lead_id: '<lead_id>',
// project_id: '<project_id>',
// org_id: '<org_id>',
});

try {
const activity = await activitiesApi.addActivity(activityData);

if (activity) {
console.log('Activity created successfully in Pipedrive');
} else {
console.error('Failed to create activity in Pipedrive');
}
} catch (error) {
console.error('Error creating activity in Pipedrive:', error);
}
});

await Promise.all(promises);
}

// Handler for webhook events
app.post('/webhook', async (request, response) => {
const event = request.body;
const secret = 'YOUR_WEBHOOK_SECRET'; // Replace with your actual webhook secret

try {
if (!verifySignature(request, secret)) {
return response.status(401).json({ message: 'Invalid signature' });
}

if (event.type === WebhookEventType.CALL_COMPLETED) {
await processCallCompletedEvent(event);
}

response.json({ message: 'Webhook processed successfully' });
} catch (error) {
console.error('Error processing webhook:', error);
response.status(500).json({ message: 'Internal server error' });
}
});

// Start the server and Ngrok tunnel
app.listen(port, async () => {
const url = await ngrok.connect(port);
console.log(`Server is running at http://localhost:${port}`);
console.log(`Public URL: ${url}`);
});

Step 3: Configuring Webhook in Wildix

To configure the webhook in Wildix, follow these steps:

  1. Login to Wildix Administration Console.
  2. Navigate to WMS -> PBX -> Integrations -> Cloud integrations tab
  3. Click on Webhook integration -> Install.
  4. On the Connect integration screen, fill out the following fields:
  • Integration type: Select WebHook.
  • URL: Enter the public URL provided by Ngrok (<your_ngrok_url>/webhook).
  • Choose list of events: Select Analytics Events > call:completed.
  1. Click Add.

Step 4: Running the Server

Start your Node.js server by running:

node index.js

Step 5: Testing the Integration

Make a test call using the Wildix platform and ensure it completes. After the call ends, check your CRM (Pipedrive) to see if the activity has been logged correctly.

Additional Information

  • Ngrok Configuration: Ngrok provides a public HTTPS URL that you can use to expose your local server to the internet. This is useful for testing webhooks locally.
  • Webhook Signature Verification: It's important to verify the signature of incoming webhooks to ensure they are from a trusted source. The script includes a function to verify the signature using a secret.

Conclusion

This guide provided a step-by-step approach to integrating the Wildix platform with a CRM using webhooks. By following these steps, you can automate the process of logging call activities into your CRM, thereby improving efficiency and accuracy. Customize the script as per your requirements to make the most out of this integration.