Copy Outlook Calendar Events with Logic Apps or Power Automate

Automatically sync multiple Outlook Calendars to one ‘main’ Calendar

Arthur Steijn
5 min readJan 10, 2021
Photo by Estée Janssens on Unsplash

Working as a consultant sometimes means having multiple mail addresses and calendars to manage. Up until now, I added Calendar events from my client manually to my ‘main’ calendar, just to keep it up to date for my colleagues and avoid two meetings at the same time.

After multiple attempts of trying to fix this through the outlook client, I decided to try a different approach. Logic Apps and Power Automate have out of the box connectors for Office 365 Outlook.

What looked like a very simple solution at first, escalated pretty quickly. Besides adding a new event, I wanted to handle updates and deletes as well.

I’ll give a detailed description of the Logic App I created. All steps can be reproduced in Power Automate as well.

Logic App Setup

Trigger to start the process

To trigger the app, I used the Office 365 connector ‘When an event is added, updated, or deleted (V3)’. This connector makes use of the Microsoft Graph API. The trigger is authenticated with the credentials of the account from which you want to send the events (source calendar). This new version of the connector is triggered almost instantly when an event gets added, updated, or deleted in the connected Calendar. The type of event is displayed in the ‘Action Type’ field.

Trigger Settings

After the trigger we initialize a variable, we need this in a later stadium for updated events.

Initialize Variable Settings

Switch on Action Type

Depending on the ‘Action Type’ we define different actions. For this, I use a ‘Switch’ action. Let’s start with the simple one, ‘added’.

Switch on Action Type

Added logic

If the ‘Action Type’ equals ‘added’ I want to add a new event to my ‘main’ outlook account. The connector used is ‘Create event (V4)’. This one is authenticated with the ‘target’ account. The information I use to create the event is derived from the trigger. There are two adjustments I made compared to the original appointment.

1. The subject; I added something to recognize the source calendar. In this case, a short name to recognize the client: ‘ABC:’.

2. The body; I am not interested in the original body of the appointment. The only thing I add here is the ‘Id’ field. I need this later on when updating existing appointments.

Create Event and Set Parameters

If you like you can set additional parameters, like reminders and how it is displayed in the Calendar.


If the ‘Action Type’ is ‘updated’ I want to change the existing event in the target calendar, when it is not there, I want to add it. This is where it gets a little more complicated, but not undoable.

Get Events

The first thing to do is to check the target calendar if we can find the event that needs to be updated. We do this with the ‘Get events (V4)’ action. The action uses an OData protocol to get the events from your account.

My intuition was to filter the results on the ‘Id’-field we added to the body of the event. But I kept getting errors, probably because the body is Html. To solve this we need two steps:

  1. Get a list of events by Subject
  2. Loop through the list to find the right event

To filter the results of the ‘Get events’ we can use the following expression:

contains(Subject, '@{triggerBody()?['subject']}')

Get Events and Filter on Subject

Loop through all Events

Now we will try to find the right event by looking for the ‘Id’ field in the body of the event.

Loop the Result Set for the Id

If we find the right event, we delete it and create it again with the new information. After that, we set the variable to ‘true’.

Delete the Event, Recreate it and Set the Variable

In the delete action, it is important to use the ‘Id’ that we get from the ‘Get Events’ action because this corresponds with the previously created event.

Add if Event wasn’t found

If for any reason the event is not found, I want to add those too. For this, we initialized the variable at the top level of the Logic App. If the event was not found in the previous step, the variable will still be ‘false’. Meaning that we are missing this event in our target calendar. Thus we create it in the same way we did in the first added action

If Variable ‘UpdatedEventExists’ is ‘false’ add the Event to the Calendar


When an event is deleted in the source calendar, I want to remove it from the target calendar as well. Basically, I do the same steps as when the ‘Action Type’ is ‘updated’. There is one downside, the trigger returns very little information about the event. There is only the ‘Id’ of the event we can search for in the body of the appointments. This means I can only filter on the short name I added in the subject to filter the results.

Get Events with filter on Subject, Look for the ‘Id’ and Delete Event

Not filtering the query in the ‘Get Events’ action can take significantly more time and therefore is more expensive in the end.

Wrap Up

That’s it! We can now add appointments from one calendar to another, update them if they change, and delete them when needed!

I admit it is not a perfect solution. Recurring appointments from the source calendar are not handled in the best way.

And I would really like to add a category to the created events. The Graph API docs tell me that it should be possible, but I didn’t manage to get it working with these Office 365 Connectors.

Let me know if you see any improvements!


Office 365 Outlook — Connectors | Microsoft Docs



Arthur Steijn

Microsoft-oriented Data/DevOps/Cloud Engineer, always looking for new and exciting techniques to improve processes and deliver fast and reliable data pipelines