Table of Content

Introduction – The Client Challenge

While Dynamics 365 Sales provides native calling capabilities and supports Microsoft Teams calling, it assumes a single outgoing number per user, and only supports Teams-based telephony not Twilio or other programmable voice providers. Additionally, it does not support dynamic number routing based on Model-Driven App or Business Unit context.

Our client operates across multiple Business Units and Model-Driven Apps, each requiring calls to originate from a different Twilio number.

This created several limitations:

  • Calls were being logged against incorrect Business Units
  • Users had to manage numbers manually outside CRM
  • No support for multi-number routing in a single CRM instance
  • Teams’ integration does not support routing by app context

Why We Used Twilio and a Custom Dialer

To solve these gaps, we needed a solution that would:

  • Route calls dynamically based on the current App or Business Unit
  • Assign dedicated Twilio numbers per client / business unit
  • Embed a seamless dialer experience inside Dynamics 365
  • Handle both outgoing and incoming calls
  • Ensure secure, app-bound call sessions

Twilio was the ideal platform because it:

  • Allows provisioning of dedicated phone numbers
  • Enables programmable call logic via TwiML Functions
  • Supports secure token-based authentication
  • Integrates well via HTML, JavaScript, C#, and Dataverse APIs

Our Solution

We built a Custom Twilio Dialer embedded in Dynamics 365 using:

  • Web Resources (HTML/JavaScript/CSS)
  • C# Custom Actions for backend processing
  • Twilio Programmable Voice SDK
  • TwiML Functions for secure call routing
  • Token-based authentication (JWT)
  • Two Dataverse Configuration Tables

This allows us to support multi-client telephony within a single CRM system while delivering a seamless and secure user experience.

Project Overview

Our custom dialer supports:

  • Multiple Twilio phone numbers
  • Dynamic number selection based on Business Unit or App
  • Embedded custom UI with “Call From” and “Call To” fields
  • Real-time Twilio call handling
  • Automatic Phone Call Activity logging
  • Incoming call support with routing to correct App

Key Components

ComponentPurpose
Call Configuration TableMaps Twilio Numbers to specific Model-Driven Apps and Business Units. Dynamically controls which app can initiate calls.
Configuration TableStores Twilio credentials and other sensitive keys securely using key-value pairs.
Web Resources (HTML/JS/CSS)Implements the custom dialer UI & event handlers
C# Custom ActionsToken generation, Twilio call triggering, Activity creation
Power Automate FlowsCreate phone call activities for incoming / outgoing calls
TwiML FunctionsRoutes incoming/outgoing calls appropriately
Twilio Token AuthSecure temporary access for each user session

Custom Dialer UI & Workflow

1. Token-Based Authentication (Required)

This integration requires a JWT token for secure communication with Twilio. We generate a short-lived JWT token for each session using a secure server-side C# plugin and a Dataverse Custom Action.

Token Generation Flow:

  • User opens a record or clicks a call icon
  • JavaScript calls a Custom Action with App SID and number
  • Plugin generates a JWT with VoiceGrant
  • Token is returned and used to initialize Twilio.Device

C# Custom Action code

var grant = new VoiceGrant

{

    OutgoingApplicationSid = appSid,

    IncomingAllow = true

};

var token = new Token(accountSid, apiKey, apiSecret, identity, new HashSet<IGrant> { grant });

return token.ToJwt();

2. Initializing the Twilio Device

Include the required SDK in your HTML Web Resource:

Html [Twilio SDK]

<script src="https://media.twiliocdn.com/sdk/js/client/v1.13/twilio.min.js"></script>

JavaScript inside HTML to initiate Twilio Device

Twilio.Device.setup(token);

Twilio.Device.ready(() => updateStatus(“📞 Ready”));

Twilio.Device.error(error => showError(error.message));

Solving the Multi-Number Calling Challenge in Dynamics 365 with a Custom Twilio Dialer

3. Making Outgoing Calls

Calls can be initiated from:

  • The custom dialer UI
  • Clicking a custom phone icon next to number fields on any CRM form

javascript

Twilio.Device.connect({ To: phoneNumber });

Twilio.Device.on(“connect”, connection => {

    startCallTimer();

    updateStatus(“📞 Call Connected”);

    callButton.textContent = “End Call”;

});

screenshot showing Making Outgoing Calls using twelio in crm

Call Routing with TwiML Functions

TwiML Functions are a core part of our custom calling logic. These are serverless functions hosted by Twilio, written in JavaScript, that define how to handle incoming or outgoing calls using Twilio Markup Language (TwiML).

We configure and use two types of TwiML Functions per client:

Outgoing Call Function

Our custom dialer does not dial phone numbers directly. Instead, it invokes a TwiML Function, which:

  • Accepts the destination number as input
  • Builds a dynamic TwiML response that either:
    • Dials an external phone number, or
    • Connects to a Twilio Client (CRM browser user)

This TwiML Function’s public URL is attached to a TwiML Application, which we create and manage in Twilio.

Call Routing with TwiML Functions

We configure the TwiML Function URL in the associated TwiML Application.

Call Routing with TwiML Functions

When generating the JWT token for secure communication via the Twilio Client SDK, we pass the TwiML App SID to bind that token to the correct app and routing logic.

This approach ensures:

  • Centralized and secure routing for all outbound calls
  • Proper enforcement of app-specific call behavior
  • Seamless integration between JWT auth and TwiML execution

TwiML Function for Outgoing Call

exports.handler = function (context, event, callback) {

  const twiml = new Twilio.twiml.VoiceResponse();

  const to = event.To;

  const callerId = ‘+12343’; // Replace with Twilio number

  if (!to) return callback(“Missing ‘To’ parameter”);

  const dial = twiml.dial({ callerId });

  if (to.startsWith(‘+’)) {

    dial.number(to); // External number

  } else {

    dial.client(to); // Browser-to-browser

  }

  return callback(null, twiml);

};

4. Handling Incoming Calls

Each Twilio number is configured to point to a TwiML Function responsible for managing incoming call routing. When a call is received, Twilio invokes the Function URL, defined in the Voice settings of the Twilio phone number.

This function executes a set of TwiML instructions to:

  • Greet the caller
  • Forward the call to a specific Twilio Client (browser-based CRM user)
screenshot of dashboard showing Handling Incoming Calls in twelio using CRM

TwiML Function for Incoming Call

exports.handler = function (context, event, callback) {

  const twiml = new Twilio.twiml.VoiceResponse();

  const callerId = ‘+122343’;

  const crmClientId = ‘+15464’; // CRM browser client ID

  const dial = twiml.dial({ callerId });

  dial.client(crmClientId); // Route to browser

  return callback(null, twiml);

};

The Function URL is set as the Voice Webhook on the Twilio number’s configuration.

TwiML Function for Incoming Call

The call is routed based on the client identity (clientId) specified in the dial.client() method. This identity must match the one used in the JWT token previously generated and used to initialize the Twilio Client SDK on the browser.

The incoming call reaches the correct authenticated CRM user within the right Model-Driven App.

Client-Side Behavior

On the client side, the Twilio Client SDK listens for incoming call events. When a call is detected:

  • The custom dialer UI automatically switches to the Incoming Call UI
  • The caller’s number is displayed
  • The user is prompted to accept or reject the call

javascript

Twilio.Device.on(“incoming”, connection => {

    showIncomingCallUI(connection.parameters.From);

    acceptButton.onclick = () => connection.accept();

    rejectButton.onclick = () => connection.reject();

});

Additional Features

  • Auto-reject if the user is already on a call
  • 30-second timeout if unanswered
  • UI dynamically updates based on call status

This end-to-end handling ensures a seamless and secure incoming call experience within Dynamics 365, fully embedded in the browser.

Call Logging in Dynamics 365

A Phone Call Activity is created automatically when a call ends, capturing:

  • From (calling user)
  • To (Lead/client engagement)
  • Duration & status
  • Regarding (linked record)
Call Logging in Dynamics 365

Usage Scenario

We did not embed the dialer on a form.

Instead:

  • We built a custom HTML Web Resource
  • Added custom phone icons on phone fields in forms like Lead or client engagement
  • When the user clicks the icon:
    • The Twilio token is generated
    • The dialer opens in the side pane
    • The call is automatically initiated
  • This works on any entity form — Lead, Contact, Opportunity, etc.
  • No navigation or switching required.

Error Handling

  • Validates phone numbers
  • Catches token/auth errors
  • Shows user-friendly messages (no raw errors)

Benefits Delivered

  • Seamless, embedded calling in CRM
  • Supports dynamic, per-App or per-BU number routing
  • Secure with short-lived JWT tokens
  • Real-time incoming and outgoing call management
  • Automatic logging and auditing
  • Centralized, maintainable TwiML call logic

Conclusion

By designing a flexible, secure, and scalable Twilio-based custom dialer, we solved the multi-number, multi-business unit challenge inside Dynamics 365 CRM. The result is a powerful, seamless telephony solution tailored for multi-tenant CRM environments improving efficiency, call tracking, and user experience.

Read more : merge twilio dll in dynamics crm plugin easily

FAQ’s

Can I use multiple Twilio numbers within a single Dynamics 365 instance?

Yes. Our custom Twilio dialer allows dynamic number selection based on Business Unit or Model-Driven App, all within a single CRM instance.

Does the solution support both outgoing and incoming calls?

Absolutely. The custom dialer handles secure outgoing and incoming calls, with routing and UI logic embedded directly in Dynamics 365.

How are calls logged in Dynamics 365?

All calls are automatically logged as Phone Call Activities, capturing caller info, duration, status, and linked CRM records.

is a software solution company that was established in 2016. Our quality services begin with experience and end with dedication. Our directors have more than 15 years of IT experience to handle various projects successfully. Our dedicated teams are available to help our clients streamline their business processes, enhance their customer support, automate their day-to-day tasks, and provide software solutions tailored to their specific needs. We are experts in Dynamics 365 and Power Platform services, whether you need Dynamics 365 implementation, customization, integration, data migration, training, or ongoing support.

Share This Story, Choose Your Platform!

How to Merge External DLLs (Like Twilio) for Dynamics CRM Plugin Deployment