# NodeJS -------------------------------------------------------------------------------- title: "Introduction" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.675Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/introduction/" service: "All Services" related: - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) - Node.js SDK (/en/sdk/nodejs/v2/overview/) - Twilio (https://www.twilio.com/) -------------------------------------------------------------------------------- # Dialer App ### Introduction In this tutorial, we will build a simple Dialer application on Catalyst by integrating with **Twilio**. The Dialer application allows you to initiate an outbound audio call connection between your sales team and customers. Twilio is a cloud communication platform that provides a rich set of REST APIs to establish meaningful and quick connections through voice, video, messaging, live-streaming, emails, and more. Twilio platform provides a variety of functionalities such as personalized customization of text-to-speech dial messages, call recordings, conference calling, call forwarding, and tracking. We will use the {{%link href="https://www.twilio.com/voice" %}}Programmable Voice API{{%/link%}} of Twilio for setting up an outbound call between two phone numbers through a virtual phone number. {{%note%}}{{%bold%}}Note{{%/bold%}}: You will need a paid Twilio account for this application, because integration with Twilio's APIs is not available in its free version. A Twilio phone number (virtual number) can be purchased from the Twilio console based on your country preference when you sign up for a Twilio account. {{%/note%}} The client application will look like this : The Dialer application contains the following fundamental Catalyst components : 1. {{%link href="/en/serverless/getting-started/introduction/" %}}**Catalyst Serverless**{{%/link%}}: - {{%bold%}}{{%link href="/en/serverless/help/functions/advanced-io" %}}Advanced I/O Function{{%/link%}}{{%/bold%}}: The Advanced I/O function is coded in {{%bold%}}Node.js{{%/bold%}} programming environment. It contains backend logic that integrates with Twilio's Programmable Voice API to initiate outbound calls and also keep track of the call logs. 2. {{%link href="/en/cloud-scale/getting-started/introduction/" %}}**Catalyst Cloud Scale**{{%/link%}}: - {{%bold%}}{{%link href="/en/cloud-scale/help/data-store/introduction" %}}Data Store:{{%/link%}}{{%/bold%}} To store information related to the calls you make, such as the phone numbers, countries from which the calls are initiated, timestamp of the calls and the call statuses. - {{%bold%}}{{%link href="/en/cloud-scale/help/zcql/introduction" %}}ZCQL:{{%/link%}}{{%/bold%}} To query the Data Store and fetch the call logs after a call is completed, to be rendered in the web client. - {{%bold%}}{{%link href="/en/cli/v1/project-directory-structure/client-directory/" %}}Client{{%/link%}}{{%/bold%}}: The front end of the application that is hosted on Catalyst through {{%link href="/en/cloud-scale/help/web-client-hosting/introduction" %}}web client hosting{{%/link%}}. We will use the Catalyst web console and the Catalyst Command Line Interface (CLI) to build this application. In this tutorial, we have provided the code for the files to be included in the Advanced I/O function and client components. You will just need to copy the provided code and paste it into the appropriate files as directed. ### Application Architecture The Dialer application architecture is depicted below: 1. The application accepts user input, such as the sales team's contact number and the customer’s phone number. 2. The phone numbers entered by the user are validated. Upon successful validation, the numbers will be stored in CallLogs table of Catalyst's Data Store and a request will be sent to the Twilio's Voice API. 3. On calling the Twilio API, an outbound call is initiated and routed from your Twilio number to the sales team's contact number. 4. At this point, the dialer application sends TwilML instructions to the Voice API in order to dictate the actions to be presented to the user once the call is on-going. In our application, we have configured an url that returns voice instructions back to the REST API. 5. Twilio's Voice Response function has pre-configured verbs that allow you to customize the call actions according to your preference. Here, we will use the {{%link href="https://www.twilio.com/docs/voice/twiml/dial" %}}dial(){{%/link%}} and {{%link href="https://www.twilio.com/docs/voice/twiml/say" %}}say(){{%/link%}} verbs to dial the sales number from your account's Twilio number and present a message to the caller once the respective call is being forwarded. 6. On successful completion of the call, the call details such as call duration, call status, called country and timestamp of the call are updated in the table. The call will be terminated when either of the parties hang up or if Twilio’s signal is busy. 7. The user can also view the call logs in the Dialer application. The logs will be fetched by querying the DataStore. The Dialer application serves as a quick solution to initiate outbound audio call communications to your customers. -------------------------------------------------------------------------------- title: "Prerequisites" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.675Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/prerequisites/" service: "All Services" related: - CLI Command Reference (/en/cli/v1/cli-command-reference/) - Install CLI (/en/getting-started/installing-catalyst-cli/) - Login CLI (/en/cli/v1/login/login-from-cli/) -------------------------------------------------------------------------------- # Prerequisites Before you begin building the application, you must have the following prerequisites installed on your system: 1. {{%bold%}}Catalyst CLI{{%/bold%}} : Catalyst CLI contains a host of tools that enable you to initialize, develop, test, and deploy the components of your application from your local machine. We will be working with Catalyst CLI in this tutorial. You must perform these actions: 1. {{%bold%}}Install Catalyst CLI{{%/bold%}}: Catalyst CLI is installed through NPM. You must therefore have NPM and Node.js installed on your system before you install the CLI. Refer to the {{%link href="/en/getting-started/installing-catalyst-cli" %}}**Install Catalyst CLI help page**{{%/link%}} for details on the pre-requisites and the steps to install it. 2. {{%bold%}}Login Catalyst CLI{{%/bold%}}: After you install Catalyst CLI, you must authenticate the CLI with your Catalyst account before using it. Refer to the {{%link href="/en/cli/v1/login/login-from-cli/" %}}**CLI Login help page**{{%/link%}} for the steps to log in from Catalyst CLI and the various options available for it. 2. {{%bold%}}Any IDE tool for Java, Node.js, and client code development{{%/bold%}} : Download and install an IDE of your choice in your system. You can use any IDE to work with the function and the client code. Some popular choices include Visual Studio Code, IntelliJ IDEA, Eclipse, and Sublime Text. {{%info image="/images/tutorials/todo-list/vscode.png"%}}If you are a Visual Studio Code IDE user, you can install the {{%bold%}}Catalyst Tools{{%/bold%}} extension, and use your IDE itself in place of the CLI. You can find more details about the Catalyst VS Code extension from this {{%link href="/en/catalyst-extensions/vs-code-extension/introduction/" %}}help section{{%/link%}}.{{%/info%}} 3. {{%bold%}} Twilio account and credentials{{%/bold%}} : As discussed earlier, you will need to purchase a paid Twilio account in order to integrate with Twilio's Voice API. Make sure you obtain the below credentials in prior from your Twilio account: 1. {{%bold%}}Twilio phone number{{%/bold%}} 2. {{%bold%}}Twilio SID{{%/bold%}} 3. {{%bold%}}AuthToken{{%/bold%}} You can navigate to the Twilio console to obtain your account’s SID and AuthToken. These are auto-generated by Twilio upon account creation. {{%bold%}}SID{{%/bold%}} is a unique string value provided by Twilio to identify your account's call resource and AuthToken is generated to authenticate your API requests. Make sure to get a voice capable Twilio number. Again, this can be purchased for free from the Twilio console itself. As discussed earlier, the primary purpose of this number is to route calls in your application. We will use these credentials in our code section while calling Twilio's Voice API. -------------------------------------------------------------------------------- title: "Create a project" description: "Build a dialer application using Catalyst Advanced I/O Functions, Catalyst CloudScale DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.675Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/create-project/" service: "All Services" related: - Project Directory (/en/cli/v1/project-directory-structure/introduction) - Setup Catalyst Projects (/en/getting-started/catalyst-projects) -------------------------------------------------------------------------------- # Create a Project Let's {{%link href="/en/getting-started/catalyst-projects" %}}create a Catalyst project{{%/link%}} from the Catalyst console. 1. Log in to the {{%link href="https://console.catalyst.zoho.com/baas/index" %}}Catalyst console{{%/link%}} and click {{%bold%}}Create a new Project{{%/bold%}}. <br/> 2. Enter the project's name as {{%badge%}}CatalystDialerApp{{%/badge%}} in the pop-up window. <br/> 3. Click {{%bold%}}Create{{%/bold%}}. Your project will be created. -------------------------------------------------------------------------------- title: "Create a table" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.675Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/create-table/" service: "All Services" related: - Data Store (/en/cloud-scale/help/data-store/introduction) -------------------------------------------------------------------------------- # Create a Table in the Data Store Next, let's create a table in the Data Store in the {{%bold%}}CatalystDialerApp{{%/bold%}} project. As discussed earlier, this table is used to store to-do list items created by the user. To create a table: 1. Navigate to the {{%bold%}}Catalyst CloudScale Data Store{{%/bold%}} component in the console. Click {{%bold%}}Start Exploring{{%/bold%}}. <br/> 2. Click {{%bold%}}Create a new Table{{%/bold%}}. <br/> 3. Enter the table's name as "{{%bold%}}CallLog{{%/bold%}}", then click {{%bold%}}Create{{%/bold%}}. <br/> {{%note%}}{{%bold%}}Note : {{%/bold%}} Ensure that you enter the name exactly as instructed, because the application's code contains the same name.{{%/note%}} The table is now created and displayed in the Data Store page. ### Create Columns Next, let's create a column to store the details of the call. 1. Click {{%bold%}}New Column{{%/bold%}} in the Schema View section of the table. <br/> 2. Enter the column's name as "{{%bold%}}callDuration{{%/bold%}}". Select the data type as {{%bold%}}'int'{{%/bold%}} and click **Create**. <br/> You can learn about the various data types supported by Catalyst and the other properties of a column from the {{%link href="/en/cloud-scale/help/data-store/introduction" %}}Data Store help page{{%/link%}}. {{%note%}}{{%bold%}}Note:{{%/bold%}} Ensure that you enter the name exactly as instructed, because the application's code contains the same name.{{%/note%}} The column is now created and listed in the _Schema View_ section. You must now create five other columns in the same way. The table must contain six columns in total with the following mandatory properties : <table class="content-table"> <thead> <tr> <th>Column Name</th> <th>Data Type</th> <th>Max Length</th> </tr> </thead> <tbody> <tr> <td>callStatus</td> <td>varchar</td> <td>255</td> </tr> <tr> <td>calledCountry</td> <td>varchar</td> <td>255</td> </tr> <tr> <td>timeOfCall</td> <td>varchar</td> <td>255</td> </tr> <tr> <td>fromNumber</td> <td>varchar</td> <td>255</td> <td></td> </tr> <tr> <td>toNumber</td> <td>text</td> <td></td> </tr> </tbody> </table> You have now configured all the necessary components from the console. You will now be working on coding the application from your local system. -------------------------------------------------------------------------------- title: "Initialize the project" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.676Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/initialize-project/" service: "All Services" related: - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction) - Initialize Resources (/en/cli/v1/initialize-resources/introduction) -------------------------------------------------------------------------------- # Initialize the Project from the CLI You can now begin working on your Catalyst project from the CLI. The first step is to initialize the project in an empty directory. This will be the home directory of your project and all of the project files will be saved in it. You can learn more about this from the {{%link href="/en/cli/v1/project-directory-structure/introduction" %}}Project Directory Structure help page{{%/link%}}. You can learn about initializing a project in detail from the {{%link href="/en/cli/v1/initialize-resources/introduction/" %}}CLI help documentation{{%/link%}}. For the Dialer application, we will initialize the client and the Advanced I/O function components. 1. Create a folder for the project on your local machine and navigate to it from the terminal. 2. Initialize a project by executing the following command from that directory: {{%cli%}} catalyst init{{%/cli%}} 3. The CLI will now ask you to associate a Catalyst project with the directory. Associate it with the project that we created earlier from the console. Select {{%bold%}}CatalystDialerApp{{%/bold%}} from the list and press {{%bold%}}Enter{{%/bold%}}. <br /> 4. Select {{%bold%}}Functions{{%/bold%}} and {{%bold%}}Client{{%/bold%}} using the space bar. Press the {{%bold%}}Enter{{%/bold%}} key to initialize. <br /> 5. The CLI will initiate the function setup. Select {{%bold%}}AdvancedIO{{%/bold%}} as the function type. <br /> 6. Select the latest runtime version of **NodeJS** platform listed. <br /> 7. Enter {{%badge%}}dialer{{%/badge%}} as the package name, {{%badge%}}index.js{{%/badge%}} as the entry point, and your email address as the author and press {{%bold%}}Enter{{%/bold%}}. You can alternatively press {{%bold%}}Enter{{%/bold%}} without entering inputs to fill in the default values. The CLI will prompt the initialization of the Node dependencies. Press {{%bold%}}Y{{%/bold%}} to confirm the installation, and press {{%bold%}}Enter{{%/bold%}} to confirm your choice. The Node modules will be installed. <br /> The CLI will prompt the initialization of the Node dependencies. Press {{%bold%}}Y{{%/bold%}} to confirm the installation, and press {{%bold%}}Enter{{%/bold%}} to confirm your choice. The Node modules will be installed. {{%note%}}{{%bold%}}Note{{%/bold%}}: Ensure that you enter the function's package name or class name exactly as instructed, because the application's code contains the same name.{{%/note%}} 8. The CLI will now initiate the client set up next. Enter {{%bold%}}CatalystDialerApp{{%/bold%}} as the name for the client package and press {{%bold%}}Enter{{%/bold%}}. You can enter any name you need.<br /> Catalyst initialization is now complete. Your {{%link href="/en/cli/v1/project-directory-structure/introduction" %}}project directory{{%/link%}} (CATALYST_PROJECT_HOME), {{%link href="/en/cli/v1/project-directory-structure/client-directory" %}}client directory{{%/link%}} (CATALYST_CLIENT_HOME), {{%link href="/en/cli/v1/project-directory-structure/functions-directory" %}}functions directory{{%/link%}} (CATALYST\_FUNCTIONS\_HOME) along with the configuration files and dependencies, {{%link href="/en/cli/v1/project-directory-structure/catalyst-json" %}}catalyst.json{{%/link%}} and a hidden {{%badge%}}.catalystrc{{%/badge%}} file will be created in a standard structure. This is the structure of the CatalystDialerApp project's directory with both the function and client directories configured. -------------------------------------------------------------------------------- title: "Configure the Advanced I/O function" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.676Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/configure-advanced-function/" service: "All Services" related: - Advanced I/O Functions (/en/serverless/help/functions/advanced-io/) - Functions Directory Structure (/en/cli/v1/project-directory-structure/functions-directory) -------------------------------------------------------------------------------- # Configure the Advanced I/O Function Let's begin coding the Dialer app by configuring the function component. The function's directory,{{%badge%}}functions/dialer{{%/badge%}} contains: * The {{%badge%}}index.js{{%/badge%}} main function file * The {{%badge%}}catalyst-config.json{{%/badge%}} configuration file * Node modules * {{%badge%}}{{%link href="https://docs.npmjs.com/files/package.json" %}}package.json{{%/link%}}{{%/badge%}} and {{%badge%}}{{%link href="https://docs.npmjs.com/configuring-npm/package-lock-json.html" %}}package-lock.json{{%/link%}}{{%/badge%}} dependency files ### Install packages for Node.js You will need to install two additional packages in the functions directory of your application before proceeding further. #### {{%bold%}}Express{{%/bold%}} To import the {{%link href="https://expressjs.com/" %}}Express Node.js{{%/link%}} package in the code, you must install the Express dependencies in your system. The express framework is used to manage routes and also respond to HTTP requests. To install {{%badge%}}Express.js{{%/badge%}} in your local machine, navigate to the function's home directory ({{%badge%}}functions/dialer{{%/badge%}}) in your terminal and execute the following command: {{%cli%}} npm install express --save {{%/cli%}} This will install the Express module and save the dependencies. #### {{%bold%}}Twilio{{%/bold%}} You will also need to install the Twilio package for this tutorial. The Twilio library allows you to make HTTP requests to the Twilio API. Execute the below command to add the Twilio dependencies. {{%cli%}} npm install twilio {{%/cli%}} This information will also be updated in the {{%badge%}}package.json{{%/badge%}} file. Next, let's add the code in the function file. Copy the Node js code and paste it in {{%badge%}}index.js{{%/badge%}} in the {{%badge%}}functions/dialer{{%/badge%}} directory. You can use any IDE of your choice to work with the application's files. {{%note%}}{{%bold%}}Note{{%/bold%}}: Please go through the code given in this section to ensure you fully understand it. We will discuss the architecture of the function and the client in the next section.{{%/note%}} {{% panel_with_adjustment header="index.js" class="language-javascript line-numbers" %}}const express = require("express"); const app = express(); var twilio = require('twilio'); const VoiceResponse = require("twilio").twiml.VoiceResponse; var catalyst = require('zcatalyst-sdk-node'); var YOUR_TWILIO_NUMBER = '+15612993019'; //Replace with your Twilio Phone Number var accountSid = "xxxxxxxxxxxxxxx"; //Replace with your Twilio Account SID var authToken = "{{7xxxxxxxxxxxxxxxxx8}}"; //Replace with your Twilio Auth Token var twilioClient = twilio(accountSid, authToken); var bodyParser = require('body-parser'); app.use(bodyParser.json()); // support json encoded bodies app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies app.post("/makeCall", async (req, res) => { try { var salesNumber = req.body.salesNumber; console.log(req.body) const catalystApp = catalyst.initialize(req); let rowData = { fromNumber: req.body.phoneNumber, toNumber: req.body.salesNumber }; console.log(rowData) const catalystTable = catalystApp.datastore().table('CallLog'); const data = await catalystTable.insertRow(rowData); var url = 'https://' + req.headers.host + '/server/dialer/outbound/' + encodeURIComponent(salesNumber); var options = { to: req.body.phoneNumber, from: YOUR_TWILIO_NUMBER, url: url, method: 'post', statusCallbackEvent: ['answered', 'completed'], statusCallback: 'https://' + req.headers.host + '/server/dialer/statusCheck?ROWID=' + data.ROWID, statusCallbackMethod: 'POST' }; twilioClient.calls.create(options).then((call) => { res.status(200).send({ message: 'Call Initiated' }); }).catch((error) => { console.log(error); res.status(500).send({ "error": error }); }); } catch (e) { console.log("Exception while making a Call ::" + e); res.status(500).send({ "error": 'Internal Server Error Occured. Please Try again after sometime.' }); } }); app.post('/outbound/:salesNumber', function (req, res) { try { var salesNumber = req.params.salesNumber; var twimlResponse = new VoiceResponse(); twimlResponse.say('Thanks for trying out the Catalyst Dialer App. Please hold on so that we can connect with your Customer... ', { voice: 'alice' }); twimlResponse.dial(salesNumber); res.status(200).send(twimlResponse.toString()); } catch (e) { console.log("Exception while making Outbound Call ::" + e); res.status(500).send({ "error": 'Internal Server Error Occured. Please Try again after sometime.' }); } }); app.post('/statusCheck', async (req, res) => { try { const catalystApp = catalyst.initialize(req); if (req.body.CallStatus === "completed") { let updatedRowData = { callDuration: req.body.CallDuration, callStatus: req.body.CallStatus, calledCountry: req.body.CalledCountry, calledState: req.body.CalledState, timeOfCall: req.body.Timestamp, ROWID: req.body.ROWID }; console.log(updatedRowData) const catalystTable = catalystApp.datastore().table('CallLog'); await catalystTable.updateRow(updatedRowData); } res.status(200).send(' StatusCheck Completed'); } catch (e) { console.log("Exception while checking status :: " + e); res.status(500).send({ "error": 'Internal Server Error Occured. Please Try again after sometime.' }); } }); app.get('/getLogs', async function (req, res) { try { const catalystApp = catalyst.initialize(req); const query = 'SELECT callDuration,callStatus,calledCountry,timeOfCall,fromNumber,toNumber FROM CallLog'; const queryResult = await catalystApp.zcql().executeZCQLQuery(query); res.status(200).send(queryResult); } catch (e) { console.log("Exception while getting Call Logs ::" + e); res.status(500).send({ "error": 'Internal Server Error Occured. Please Try again after sometime.' }); } }); module.exports = app; {{% /panel_with_adjustment %}} {{%note%}}{{%bold%}}Note{{%/bold%}}: Please make sure you add your Twilio accountID, associated Twilio phone number, and auth token values in lines 6, 7, and 8.{{%/note%}} The functions directory is now configured. We will discuss the function and the client code in the next section. -------------------------------------------------------------------------------- title: "Configure the client" description: "Build a dialer application using Catalyst Advanced I/O Functions,Catalyst CloudScale DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.676Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/configure-client/" service: "All Services" related: - Client Directory Structure (/en/cli/v1/project-directory-structure/introduction) - Web Client Hosting (/en/cloud-scale/help/web-client-hosting/introduction) -------------------------------------------------------------------------------- # Configure the Client Next, let's configure the client component. The {{%link href="/en/cli/v1/project-directory-structure/client-directory/" %}}client directory{{%/link%}}contains: * The {{%badge%}}index.html{{%/badge%}} file that contains the HTML code for the front-end application. * The {{%badge%}}main.css{{%/badge%}} file that contains the CSS code for the front-end application. * The {{%badge%}}main.js{{%/badge%}} file that contains the JavaScript code. * The {{%badge%}}client-package.json{{%/badge%}} configuration file. We will be coding {{%badge%}}index.html{{%/badge%}}, {{%badge%}}main.css{{%/badge%}}, and {{%badge%}}main.js{{%/badge%}}. {{%note%}}{{%bold%}}Note : {{%/bold%}} Please go through the code given in this section to make sure you fully understand it.{{%/note%}} Copy the code snippets given below and paste it in {{%badge%}}index.html{{%/badge%}}, {{%badge%}}main.css{{%/badge%}}, and {{%badge%}}main.js{{%/badge%}} files respectively located in {{%badge%}}client{{%/badge%}} directory using an IDE, then save the file. {{% panel_with_adjustment header="index.html" class="language-xml line-numbers"%}} &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset="utf-8" /&gt; &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt; &lt;title&gt;Catalyst Dialer App&lt;/title&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt; &lt;link rel="stylesheet" type="text/css" media="screen" href="main.css" /&gt; &lt;script src="main.js"&gt;&lt;/script&gt; &lt;script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"&gt; &lt;/script&gt; &lt;script type="text/javascript" src="//media.twiliocdn.com/sdk/js/client/v1.3/twilio.min.js"&gt; &lt;/script&gt; &lt;meta charset="utf-8" /&gt; &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt; &lt;link rel="stylesheet" type="text/css" media="screen" href="main.css" /&gt; &lt;link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"&gt; &lt;link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"&gt; &lt;link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/css/mdb.min.css" rel="stylesheet"&gt; &lt;script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"&gt;&lt;/script&gt; &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"&gt; &lt;/script&gt; &lt;script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"&gt; &lt;/script&gt; &lt;script src="main.js"&gt;&lt;/script&gt; &lt;link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"&gt; &lt;/head&gt; &lt;body onload="logButton()"&gt; &lt;center&gt; &lt;h1 class="display-4"&gt;Catalyst Dialer App ☏&lt;/h1&gt;&lt;br&gt;&lt;br&gt; &lt;/center&gt; &lt;div style="width: 200px;float: right; margin-right: 50px;"&gt;&lt;label for="switchbutton" id="btntext" class="btn btn-primary btn-block btn-outlined"&gt;&lt;/label&gt; &lt;button id="switchbutton" style="display: none;"&gt;&lt;/button&gt; &lt;/div&gt; &lt;center&gt; &lt;div id="Dialer"&gt; &lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;br&gt;&lt;br&gt; &lt;div class="form-outline"&gt; &lt;label for="phoneNumber"&gt;Customer Phone Number   &lt;/label&gt; &lt;input type="text" placeholder="(+91/Country Code)&lt;112233445566&gt;" name="phoneNumber" size="35" id="phoneNumber"&gt; &lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;label for="salesNumber"&gt;Your Sales Phone Number   &lt;/label&gt; &lt;input type="text" placeholder="(+91/Country Code)&lt;8899773366&gt;" name="salesNumber" size="35" id="salesNumber"&gt; &lt;br&gt; &lt;/div&gt; &lt;br&gt;&lt;br&gt; &lt;button type="submit" id='call-customer-button' class="btn btn-success" onclick="getFormDetails();return false;"&gt;Initiate Call&lt;/button&gt; &lt;br&gt;&lt;br&gt; &lt;h2&gt; &lt;p class="info" id='call-status'&gt;&lt;/p&gt; &lt;/h2&gt; &lt;/div&gt; &lt;/center&gt; &lt;div id="CallLogs" style="display: none;"&gt; &lt;h1 class="display-6"&gt;Call Logs : &lt;/h1&gt;&lt;br&gt;&lt;br&gt; &lt;p id="featData"&gt;&lt;/p&gt; &lt;div id="loader" style="display: none;"&gt; &lt;div class="spinner-border" role="status"&gt; &lt;span class="sr-only"&gt;Loading...&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/body&gt; &lt;/html&gt; {{% /panel_with_adjustment %}} {{% panel_with_adjustment header="main.css" class="language-css line-numbers"%}}body { padding: 30px; } #loader { width: 100px; height: 100px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; } #dataTable { font-family: Arial, Helvetica, sans-serif; border-collapse: collapse; width: 100%; } #dataTable td, #dataTable th { border: 1px solid #ddd; padding: 8px; } #dataTable tr:nth-child(even) { background-color: #f2f2f2; } #dataTable tr:hover { background-color: #ddd; } #dataTable th { padding-top: 12px; padding-bottom: 12px; text-align: left; background-color: rgb(76, 175, 170); color: white; } {{% /panel_with_adjustment %}} {{% panel_with_adjustment header="main.js" class="language-javascript line-numbers"%}}//To fetch phone numbers from the client,validate and make an outbound call function getFormDetails() { let data = { phoneNumber: $('#phoneNumber').val(), salesNumber: $('#salesNumber').val() }; if (!validateData(data)) { return false; } $.ajax({ url: "/server/dialer/makeCall", method: "post", dataType: 'json', data: { phoneNumber: data.phoneNumber, salesNumber: data.salesNumber } }).done(function (data) { alert("Call Initiated. You can check the details in Call Logs once the Call is completed"); console.log(data); }).fail(function (error) { alert(JSON.stringify(error)); }); } //To render the call log webpage function logButton() { document.getElementById("btntext").innerHTML = "View Call Logs"; document.getElementById('switchbutton').setAttribute('onclick', 'showCallLogs()'); } //To show the call logs tab in the application function showCallLogs() { document.getElementById("btntext").innerHTML = "View Dialer"; $("#Dialer").hide(); $("#CallLogs").show(); document.getElementById('switchbutton').setAttribute('onclick', 'showDialer()'); loadLog(); } //To show the dialer tab in the application function showDialer() { document.getElementById("btntext").innerHTML = "View Call Logs"; $("#Dialer").show(); $("#CallLogs").hide(); document.getElementById('switchbutton').setAttribute('onclick', 'showCallLogs()'); } //To validate the sales contact number and customer mobile number entered by the user function validateData(data) { var regex = "[+][0-9]+$"; if (data.phoneNumber.length === 0) { alert('Customer Phone number cannot be empty'); return false; } if (!data.phoneNumber.startsWith('+')) { alert('Customer Phone number must start with country code'); return false; } if (data.salesNumber.length === 0) { alert('Sales Phone number cannot be empty'); return false; } if (!data.salesNumber.startsWith('+')) { alert('Sales Phone number must start with country code'); return false; } if (!data.phoneNumber.match(regex)) { alert('Enter a valid customer number'); return false; } if (!data.salesNumber.match(regex)) { alert('Enter a valid sales number'); return false; } return true; } //To render the table data in the client end function renderTable(respData) { console.log("respData"); console.log(respData); debugger; var col = []; for (var i = 0; i < respData.length; i++) { for (var key in respData[i]) { if (col.indexOf(key) === -1) { col.push(key); } } } var table = document.createElement("table"); table.classList.add("ca-table-view"); table.setAttribute('id', 'dataTable'); var tr = table.insertRow(-1); for (var i = 0; i < col.length; i++) { var th = document.createElement("th"); th.innerHTML = col[i]; tr.appendChild(th); } for (var i = 0; i < respData.length; i++) { tr = table.insertRow(-1); for (var j = 0; j < col.length; j++) { var tabCell = tr.insertCell(-1); tabCell.innerHTML = respData[i][col[j]]; } } debugger; var divContainer = document.getElementById("featData"); divContainer.innerHTML = ""; divContainer.appendChild(table); } //To store the call log data in appropriate columns function getRequiredData(data) { var i; var resp = []; for (i = 0; i < data.length; i++) { var gulp = { "From Number": data[i].fromNumber, "To Number": data[i].toNumber, "Call Duration": data[i].callDuration, "Call Status": data[i].callStatus, "Time Of Call": data[i].timeOfCall, "Called Country": data[i].calledCountry } resp.push(gulp); } console.log(resp); return resp; } //To fetch call logs by calling the /getLogs route and render the log data in the client function loadLog() { $("#loader").show(); $.ajax({ url: "/server/dialer/getLogs", method: "get" }).done(function (data) { $("#loader").hide(); var arr = []; for (i = 0; i < data.length; i++) { arr.push(data[i].CallLog); } var data = getRequiredData(arr); renderTable(data); }).fail(function (error) { alert(JSON.stringify(error)); }); } {{% /panel_with_adjustment %}} The client directory is now configured. Let us quickly go through the working of the Advanced I/O function of the application: 1. {{%bold%}}{{%badge%}}validateData(){{%/badge%}}{{%/bold%}} - Both the sales team's contact number and the customers number are validated in this function.The logic is defined to check whether the entered phone numbers are not an empty string, follows the standard phone number format that contains only numerals and is prefixed by a '+' symbol. 2. {{%bold%}}{{%badge%}}getFormdetails(){{%/badge%}}{{%/bold%}} - This function gets the input phone number details of the customer and the sales person's number entered by the user. The phone numbers are validated by calling the {{%bold%}}{{%badge%}}validateData(){{%/badge%}}{{%/bold%}} function. On successful validation of both the phone numbers, an ajax call is made to the {{%bold%}}{{%badge%}}/makeCall{{%/badge%}}{{%/bold%}} route. It initiates an outbound call from the sales team's contact number to the customer's mobile number, and renders a response back to the client once the call is initiated. 3. {{%bold%}}{{%badge%}}getRequiredData(){{%/badge%}}{{%/bold%}} - This function is used to set the columns of the call logs with respect to the call data retrieved by querying the DataStore in {{%bold%}}{{%badge%}}/getLogs{{%/badge%}}{{%/bold%}} route. 4. {{%bold%}}{{%badge%}}renderTable(){{%/badge%}}{{%/bold%}} - This function gets the data from the {{%bold%}}{{%badge%}}getRequiredData(){{%/badge%}}{{%/bold%}} function and renders it back in the client to display the call logs. 5. {{%bold%}}{{%badge%}}showDialer(){{%/badge%}}{{%/bold%}} - This function is executed on click of the {{%bold%}}'View Dialer'{{%/bold%}} button. 6. {{%bold%}}{{%badge%}}showCallLogs(){{%/badge%}}{{%/bold%}} - This function is executed on click of the {{%bold%}}'View Call Logs'{{%/bold%}} button and triggers the {{%bold%}}{{%badge%}}loadLog(){{%/badge%}}{{%/bold%}} function. 7. {{%bold%}}{{%badge%}}loadLog(){{%/badge%}}{{%/bold%}} - This function makes an ajax call to the {{%bold%}}{{%badge%}}/getLogs{{%/badge%}}{{%/bold%}} route defined in the Advanced I/O function to fetch the call log details and render them in the client. The Advanced I/O function defines the following APIs that perform various actions: 1. {{%bold%}}{{%badge%}}/makeCall{{%/badge%}}{{%/bold%}} Obtains the sales team's contact number and customer's phone number data from the {{%bold%}}{{%badge%}}getFormDetails(){{%/badge%}}{{%/bold%}} function. Inserts the phone number details in the {{%bold%}}{{%badge%}}CallLog(){{%/badge%}}{{%/bold%}} table in the DataStore. An outbound call is initiated by calling Twilio's Voice API and also sending the TwiML instructions defined in the {{%bold%}}{{%badge%}}/outbound{{%/badge%}}{{%/bold%}} route as a part of the API request. 2. {{%bold%}}{{%badge%}}/outbound/:salesNumber{{%/badge%}}{{%/bold%}} Defines the TwiML instructions sent to Twilio that will be executed when a call is initialized. In our Dialer application we have used the {{%bold%}}Dial(){{%/bold%}} verb of Twilio to route a call to the sales number from Twilio's phone number. And the {{%bold%}}Say(){{%/bold%}} verb to specify the message to be presented when the sales person is awaiting a response from the customer's end. 3. {{%bold%}}{{%badge%}}/statusCheck{{%/badge%}}{{%/bold%}} On completion of a call, this route sends relevant call information, such as call duration, call status, called country and timestamp, to the respective columns in the CallLogs table. 4. {{%bold%}}{{%badge%}}/getLogs{{%/badge%}}{{%/bold%}} Executes the ZCQL query to fetch the call data from the CallLogs table. The query result returns the sales team's contact number, customer mobile number, duration of the call, timestamp of the call, status of the call and the country from which the call was initiated. -------------------------------------------------------------------------------- title: "Test the application" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.677Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/test-application/" service: "All Services" related: - Serve CLI Resources (/en/cli/v1/serve-resources/introduction) -------------------------------------------------------------------------------- # Test the application Before you deploy the application to the remote console, you can test the application on a local server and check if everything works using the Catalyst CLI. For detailed information on {{%badge%}}catalyst serve{{%/badge%}}, refer to the {{%link href="/en/cli/v1/serve-resources/introduction" %}}Serve Resources help page{{%/link%}}. To serve the Catalyst project locally, execute the following command from your project directory (CATALYST_PROJECT_HOME): {{%cli%}} catalyst serve{{%/cli%}} The CatalystDialer application will now be served at default port 3000. The local endpoint URLs of the components are displayed. {{%note%}}{{%bold%}}Note : {{%/bold%}} Every time you access the home page or any of the sub-pages of your client, or the function, the CLI will display a live log of the URL accessed, along with the HTTP method that is used to access it.{{%/note%}} You can now open the client component's local URL in a browser to access the Dialer application. Once you input the customer and sales person's contact number and initiate the call, you will be notified that the call has been successfully initiated. After the call is done, you can click on {{%bold%}}View Call Logs{{%/bold%}} to see the call logs. You can click {{%bold%}}View Dialer{{%/bold%}} again to go back to the dialer screen.If this setup is working correctly, we can deploy the application to production. -------------------------------------------------------------------------------- title: "Deploy the project" description: "Build a dialer application using Catalyst Advanced I/O Functions,DataStore and integration with Twilio’s Voice API that establishes an outbound call connection between your sales team and customers." last_updated: "2026-03-18T07:41:08.677Z" source: "https://docs.catalyst.zoho.com/en/tutorials/dialer-app/nodejs/deploy-project/" service: "All Services" related: - Deploy CLI Resources (/en/cli/v1/deploy-resources/introduction) - Web Client Hosting (/en/cloud-scale/help/web-client-hosting/introduction) -------------------------------------------------------------------------------- # Deploy the Project To {{%link href="/en/cli/v1/deploy-resources/introduction" %}}deploy your Catalyst project{{%/link%}} from the CLI, run the following command in your terminal from your project directory: {{%cli%}} catalyst deploy{{%/cli%}} The function is deployed first, followed by the client component. The production URLs of the components are displayed. You can now open the client component's URL in a browser to access the deployed application. The CatalystDialer application can now be accessed from its {{%link href="/en/cloud-scale/help/web-client-hosting/implementation" %}}web app URL{{%/link%}}. Dialer application is now functional and will work without any errors.