A Microsoft Flow for sending appointment reminders to customers via text for appointments created in Dynamics 365


Many companies provide the option for customers to receive appointment reminders whether that’s through email or text message. Not only does Microsoft support a wholistic approach to customer relationship management with Dynamics 365, it also provides the ability to manage these appointment reminders through Flow and its connection to Dynamics, which is an incredible asset to a business.

The following example details how create a Flow to send text appointment reminders to customers the day before as well as the hour before the appointment. The flow will execute once for every appointment created and will continue to run until the appointment has started.

Applies to: Dynamics 365 for Customer Engagement, apps version 9.1.0 

In this blog, you’ll find the following:



  1. A Flow subscription
  2. A Dynamics 365 subscription with administrative authority
  3. A third-party telecommunications subscription. This example specifically uses Telesign, however any third-party SMS provider can be used.

Build the Flow


Step 1: Select the trigger

Create a blank flow and use the Dynamics 365 trigger for when a record is created. The Organization Name field will be your organization name. The Entity Name field will be Appointments. An example of what this looks like is shown below:

As you can see, the title for this step is When a record is created. This name can be changed if you right-click the ellipsis button next to the title and select Rename. Any trigger or action can be renamed. Just be sure to do all renaming before you reference the trigger/action in a following trigger/action.


Step 2: Gather all necessary case and customer information

To gather customer contact information, you need to first get the case associated with the appointment. Obtain the case by adding a new step. Choose the action Get record for Dynamics 365.

Start by selecting the same organization from the previous step. For entity name, select Cases. The item identifier will be the case related to the Appointment from the first step. Since you are looking for content relating to a previous step, select the Add dynamic content button. In the Dynamic content tab, search for Regarding and select it. This option you just selected is the case regarding the appointment. The image below shows an example of what to put in the required fields:

As you can see in the image above, the Regarding field appears under a section titled Get record. This section titles in the dynamic content tab are the same as the titles given to the steps. Be sure to pay attention to this as you add dynamic content; most records have similar fields and you may select one that you did not intend if you are not careful.

Now that you have the case information, you’ll be able to get the customer information associated with that case. Add a new step and get another record as you did before.

When filling out the required fields, the organization name is the same. However, the entity name is now Contacts.  For the Item Identifier, add dynamic content and select the Customer related to the case record grabbed previously.


Step 3: Sending an SMS text message

You probably want to notify the customer that the appointment has been created. This can be accomplished by sending them a text message. Add a new step and choose the Send SMS Message action under TeleSign SMS. It will ask you to connect to your TeleSign account. Enter the appropriate credentials to login and proceed.

Once connected to your TeleSign account, fill in all the required fields. For the Phone number field, go to dynamic content and use the   associated with the customer record grabbed previously.

The Message Text field is customizable for your needs. Fill this section with whatever you would like. As example, I’ll demonstrate how to get the following:

Hello [CUSTOMER_FIRST_NAME]. Your appointment is scheduled on [START_TIME]. Thanks!

To get the customers first name, add dynamic content and add the First Name associated with the customer record grabbed previously.

Getting the start time is just as easy as getting the customer’s name, however it is a little trickier to format it in a simple, readable way. All times saved in Dynamics 365 are stored in Universal Time Coordinated (UTC). Storing times in this time zone makes life a lot easier when comparing values or making a product location invariant, but it does provide a small challenge when displaying these times.

To change the time zone, select the Expression tab when adding dynamic content. Scrolling down, you should see a section for date and time.

You should find an option titled ConvertFromUTC(). ConvertFromUTC() takes three inputs in the following order: timestamp, target time zone, and format (which is optional), all of which need to be separated by a comma. To get the timestamp, navigate back to dynamic content and scroll until you find Start Time associated with the appointment.

For time zone, select the time zone you are based in. Time zones should be encapsulated by single quotes like so: ‘Pacific Standard Time’

Format is optional, though in the interest of learning more about generating your own Flow, I will demonstrate how to set this input value. The input needs to look exactly as you want the date to appear when written out. However, instead of the actual date/time with numbers, you will use letter fillers. For example:

Input Output
MM/dd/yyyy 05/29/2019
dd/MM/yyyy 29/05/2019
dddd, dd MMMM yyyy Monday, 29 May 2019
ddd, dd MMM yyy HH:mm:ss GMT Fri, 29 May 2015 13:45:09 GMT
hh:mm tt 03:45 PM

The following detail all the possible filler letters and what they represent:

  1. dRepresents the day of the month as a number from 1 through 31.
  2. dd Represents the day of the month as a number from 01 through 31.
  3. ddd Represents the abbreviated name of the day (Mon, Tues, Wed, and so on.)
  4. dddd Represents the full name of the day (Monday, Tuesday, and so on.)
  5. h12-hour clock hour (for example, 4).
  6. hh12-hour clock, with a leading 0 (for example, 06)
  7. H24-hour clock hour (for example, 15)
  8. HH24-hour clock hour, with a leading 0 (for example, 22)
  9. mMinutes
  10. mmMinutes with a leading zero
  11. MMonth number (for example, 3)
  12. MMMonth number with leading zero (for example, 04)
  13. MMMAbbreviated Month Name (for example, Dec)
  14. MMMMFull month name (for example, December)
  15. sSeconds
  16. ssSeconds with leading zero
  17. tAbbreviated AM / PM (for example, A or P)
  18. ttAM / PM (for example, AM or PM)
  19. yYear with no leading zero (for example, 2015 would be 15)
  20. yyYear with leading zero (for example, 2015 would be 015)
  21. yyyYear (for example, 2015)
  22. yyyyYear (for example, 2015)
  23. KRepresents the time zone information of a date and time value (for example, +05:00)
  24. zWith DateTime values, represents the signed offset of the local operating system’s time zone from

The result should look something like this:

convertFromUtc(triggerBody()?[‘scheduledstart’],’Pacific Standard Time’,’ddd, dd MMM yyy HH:mm’)


Step 4: Delay until the day of the appointment

It is inefficient to continually probe the system asking, “Hey is it the day of the appointment? Can I send out a text?” Additionally, Flow actions, such as checking to see if it a specific time or sending a text, are not instantaneous and need a small amount of time to execute. Therefore, it is better to delay the Flow until just before the first appointment reminder will be sent. To do this, select the Delay until action.

The required timestamp will equal the time just before you want to send out an appointment reminder. For example, if a customer has an appointment on the 25th at 3pm and you want to send out a reminder one day before, you will delay the Flow until the 24th at 2:59pm. The timestamp will equal the start time minus 24 hours and 1 minutes.

To get this timestamp, go to the Expression tab. You will need both addHours() and addMinutes(). These expressions take in three parameters: timestamp, amount of time to add (unit based on which expression you selected), and format (which is optional). Format in this case is unnecessary, so it is okay to ignore that parameter.

To subtract 24 hours and 1 minutes, you will need to use addMinutes, then addHours. The timestamp input for addHours will be a result of the addMinutes expression. The result will look like this:

addHours(addMinutes(triggerBody()?[‘scheduledstart’], -1),-24)

You can also subtract 1441 minutes if that’s easier to conceptualize. If you are subtracting 1441 minutes, the result will look like this:

addMinutes(triggerBody()?[‘scheduledstart’], -1441)

Once you input the timestamp, the delay action is good to go. Now you need to send the appointment reminders.


Step 5: Create a looping action as to not miss the time to send an appointment reminder

To send a reminder at a given time before the appointment, you need to check if the current time is equal to the time the reminder needs to be send out. For example, if the appointment is at 5:30 and you want to notify the customer 1 hour before the appointment, you need to check and see if the current time is equal to the appointment start time minus 1 hour.

Seems simple enough. However, executing Flow operations is not instantaneous. It cannot be guaranteed that the check will trigger at exactly the time intended, down to the millisecond. Therefore, you need to allow for some buffer. This can be accomplished in two ways. The first way is by creating a loop to continue executing the check multiple times in case it was missed on the first iteration, as demonstrated in this step. The second way will be discussed in the next step.

To create a loop, add the Do until action. On the left-hand side of the Do until action, add dynamic content, switch to the expression tab, and add  to get the current time.

For the condition statement in the middle, select the is greater than option. On the right-hand side, add dynamic content and select the start time.

Everything inside this Do until block will continue to execute until the current time is greater than the start time of the appointment. In other words, it will continue to execute until the appointment has started. The Do until action is now done and you’re ready for the next step.


Step 6: Send an appointment reminder to the customer at a specified time before the appointment

You only want to send an appointment reminder if the current time is equal to the time you want to send a reminder. To do this check, add a Condition action. This condition action should be inside the Do until block (shown below).

The current time and start time are both stored in the UTC time zone with day, month, year, hour (on a 24-hour clock), second, and millisecond. As stated in the previous step, it is not guaranteed that the check to see if the current time is equal to time you want to send a reminder will execute at the exact time required, down to the millisecond. The looping action is one way to ensure the check happens at the precise time intended. You should also truncate the current and reminder times to get rid of the milliseconds. This furthers the reliability and ensures that when the check happens, the values are the same and the Flow will send an appointment reminder.

To truncate the timestamps, you’ll need to format them. Luckily, there are many expressions provided by Flow that allow you to format time. If you refer to Step 3, there’s more detailed information about how to generate a format input. I used the following format:

‘ddd, dd MMM yyy HH:mm’


In addition to format, you also need to do some math to calculate the time you want to send out a reminder. When doing the check for 1 day before the appointment, you just need to see if the current time plus 1 day is equal to the start time of the appointment. To do this use the addDays expression.

On the left-hand side of the Condition action, use the expression addDays, which has three inputs: timestamp, number of days to add, and format. The timestamp will be the current time (utcNow()). The number of days to add will be 1, and the format will be the one I selected and show above. It will look like this.

addDays(utcNow(), 1, ‘ddd, dd MMM yyy HH:mm’)

In the middle of the Condition action, select is equal to. On the right-hand side of the Condition action, use the formatted date and time. Follow the same procedure that you did in Step 3 when formatting the time. The result will look like this:

formatDateTime(triggerBody()?[‘scheduledstart’], ‘ddd, dd MMM yyy HH:mm’)

After you’ve truncated the value, send an SMS message the same way as described in Step 3. This message is the appointment reminder. It will go inside the Yes block of the condition action only if yes, the current time is equal to the time you want to send a reminder. Your reminder message is customizable to your needs. Refer to  on how to add dynamic content to your message.

Now that the first reminder is sent, you may want to send another reminder slightly closer to the day of the appointment. As stated before, constantly having the Flow probe the system checking to see if it’s time to send the next reminder is not efficient and could cause a lot of issues if there are a lot of appointment reminders going out around the same time. To address this issue, you should follow the same procedure as before when sending the one-day reminder and delay the Flow until just before the next appointment reminder should be sent out.

The result of sending appointment reminders for one day and one hour before the appointment should look something like this with the following inputs:

Send reminder for 1 day before appointment statement:

addDays(utcNow(), 1, ‘ddd, dd MMM yyy HH:mm’)

is equal to

formatDateTime(triggerBody()?[‘scheduledstart’], ‘ddd, dd MMM yyy HH:mm’)

Delay until about 1 hour before:



Send reminder for 1 hour before appointment statement:

addHours(utcNow(),1,’ddd, dd MMM yyy HH:mm’)

is equal to

formatDateTime(triggerBody()?[‘scheduledstart’],’ddd, dd MMM yyy HH:mm’)

Delay until start:


Now you’re set! The customers will receive an appointment reminder the day before and the hour before the appointment!

Taking it further

This is a great start to sending appointment reminders to a customer. In this blog we looked at a method of sending appointment reminders when an appointment is created. One can also extend this Flow by handling the cases of when an appointment is updated, rescheduled, or cancelled.

Perhaps instead of starting a Flow only when an appointment is created, you could start a Flow when an appointment is created or updated. You could do a check to see if the status of the appointment is updated or cancelled and based on the result you will notify the customer the status. Or you could have a separate flow for when an appointment has been updated and cancel the Flow currently executing because it no longer has valid information. Accomplishing these actions and handling these cases requires a more in-depth knowledge of Microsoft Flow. Look at the Microsoft Flow  .

Thanks for sticking with me and reading this blog post. Cheers!

– Hannah Olliges