How To Use the Microsoft Exchange Calendar API with EWS

How To Use the Microsoft Exchange Calendar API with EWS

Learn how to use the Microsoft Exchange Calendar API with EWS.

Ben Lloyd Pearson | May 13, 2020

Microsoft’s Exchange Web Services (EWS) provides an Exchange calendar API that allows you to add full Exchange data and functionality into your app. EWS offers a direct SOAP implementation and C# client library that provides access to full data and functionality for user accounts in Exchange Online, Exchange Online as part of Office 365,  Exchange server calendar. 

If you’re looking to build an integration with Exchange calendars directly into your app, this post will detail the major aspects of the Exchange Calendar API and explain what it takes to integrate Exchange calendars smoothly

It will also demonstrate how the Nylas Communications Platform abstracts away much of the complexity of building a direct integration with the Exchange calendar API to enable you to build your calendar integration much more quickly and efficiently.

Connect Exchange Accounts to Your App.

Before you can access an Exchange calendar, you need to authenticate the account with the appropriate permissions. Take a look at our guide on How to Use the EWS API to Authenticate Accounts Into Your App to learn more. Confused by all the related products in the Microsoft Exchange ecosystem? Our Microsoft Exchange definitions guide will set you straight.

Alternatively, Nylas Hosted Auth auto-detects all Microsoft accounts, and prompts users to sign in and accept the permissions your app needs. Your user’s credentials are stored safely on our SOC 2 Certified infrastructure, and Nylas provides an access token your app can use for Exchange Calendar data and functionality. With Nylas, integrating with additional calendar providers beyond Exchange requires no additional work.

Illustration of the Nylas Hosted Auth service that integrates with 100% of email, calendar, and contacts providers, including Google

The Microsoft Exchange Calendar API

Exchange Calendars are a collection of related events that include relevant metadata like name, description time zone, and more. Exchange organizes all calendar objects inside CalendarFolder objects. These can contain additional CalendarFolders, Appointment objects or a CalendarItemType object. CalendarFolders also define things like:

  • ManagedFolderInformation – Info about folder storage quota, comments, and whether the folder can be deleted, moved, or renamed.
  • EffectiveRights – The permissions a user has over the calendars contained inside.
  • SharingEffectiveRights – The permissions a user has for calendars other users have shared with them

Exchange Meetings and Appointments

Exchange Calendars define two types of events: appointments and meetings; the only functional difference between the two is that meetings have attendees, rooms, and/or resources, while appointments don’t. Exchange provides two objects to represent meetings and appointments: CalendarItem and Appointment, respectively.

There are two key differences between the ClaendarItem and Appointment objects:

  • When new CalendarItems are created or existing CalendarItems are updated, an email must be sent to affected attendees, rooms, and resources for all changes to be properly represented. Since these don’t exist in appointments, notification messages are unnecessary.
  • CalenderItems must be scheduled when attendees are available, Appointments can be scheduled at any time.

Both types of events have start and end times, durations, and other time-related properties, such as the time at which related messages are created, sent, and received, and they can be single instances or part of a recurring series. Existing appointments and meetings can be retrieved from a Calendar folder based on a start and end time, which are represented in Coordinated Universal Time (UTC). Take a look at the EWS Calendar API docs to learn more about how to return or create appointments and meetings for an Exchange account.

Calendars and Events With Nylas

The Nylas Calendar API connects to 100% of calendar providers, including Exchange Calendars. Nylas standardizes data and functionality into a predictable, easy-to-use JSON format that allows you to enable full calendar functionality within your app, no matter the provider your users prefer. Similar to EWS, The Nylas Calendar API is organized into calendars and events.

With one simple request to the Nylas Calendar API, you can return the entire list of calendars the user has access to. This is an example of what this would look like for an Exchange calendar:

$ curl -X GET 'https://api.nylas.com/calendars' -H 'Authorization: Bearer ACCESS_TOKEN'
[
    {
        "id": "9a09r24v269qsijwl27nxv4t2",
        "account_id": "aaffnt*****",
        "name": "Calendar",
        "description": null,
        "read_only": false,
        "object": "calendar"
    },
    {
        "id": "5voxh7b7bg9fchti99lsrei5j",
        "account_id": "aaffnt*****",
        "name": "Emailed events",
        "description": "Emailed events",
        "read_only": true,
        "object": "calendar"
    },
    {
        "id": "9a09r24v269qsijwl27nxv4t2",
        "account_id": "aaffnt*****",
        "name": "Agricultural Conferences",
        "description": "Agriculture Industry Events",
        "read_only": true,
        "object": "calendar"
    }
]

In this example, we make a GET request to /calendars, passing the access token for the user account in the request header. The response is a JSON body that contains a list of the user’s three calendars. The first calendar is the primary Exchange calendar for the user, which has “Calendar” as the name. The second calendar is the Emailed Events calendar, which includes all events to which the user has been invited via email. 

The last calendar is a custom calendar used to track conferences that has been shared to our user by someone else. Notice that our user is only capable of editing the first calendar in this list, the other two have a value of true for the read_only attribute indicating the user only has read access. 

Now, let’s see what one of the events on the shared Agricultural Conferences looks like.

$ curl -X GET 'https://api.nylas.com/events/{id}' -H 'Authorization: Bearer ACCESS_TOKEN' 
[
    {
        "account_id": "bh1vu31mw9a***",
        "busy": true,
        "calendar_id": "h4rm1jjibrzd7***",
        "title": "Monthly Top Soil Sustainability Meetup",
        "description": "This is our normal monthly meetup to discuss progress being made on the topsoil sustainability.",
        "ical_uid": "040000008200B00073D5B71D31B3F9D2612722",
        "id": "c7n5vfdagsd7bdeq***",
        "location": "Alabama",
        "message_id": null,
        "object": "event",
        "owner": " Henry Ford <[email protected]om>",
        "participants": [
            {
                "comment": "So many exciting things are happening in my cotton field!",
                "email": "[email protected]",
                "name": "George Washington Carver",
                "status": "yes"
            },
            {
                "comment": "Apologies, but I have more pressing matters this month",
                "email": "[email protected]",
                "name": "Albert Einstein",
                "status": "no"
            }
        ],
        "read_only": true,
        "status": "confirmed",
        "when": {
            "end_time": 1478568600,
            "object": "timespan",
            "start_time": 1478565000
        }
    }
]

In this example, we make a GET request to the /events/{id} endpoint to return a JSON payload that represents a single event. As you can see, this payload has all of the elements you’d expect to see in a calendar event, including the title, description, list of participants with indicated status and comments, and date and time information. 

Free / Busy Detection

Free / Busy functionality is the easiest way to identify blocks of time that work for all attendees to a meeting. The ExchangeService.GetUserAvailability method allows you to query an Exchange server to get a list of times that a user is available. When you use an AvailabilityData enumeration value of FreeBusyAndSuggestions in your ExchangeService.GetUserAvailability method call, you can get both a list of suggested meeting times and all the scheduled event times for your attendees. Exchange servers also have the ability to provide a list of suggested meeting times.

Free / Busy With Nylas

Similarly, The Nylas Calendar API provides free/busy information via POST requests to the /free-busy endpoint. To check the free/busy status of a users calendar, pass a start and end time, and the user’s email to the /free-busy endpoint. It will return a list of time_slot objects that indicate timespans where the user is marked busy:

$ curl -X POST "https://api.nylas.com/calendars/free-busy" -H 'Authorization: Bearer ACCESS_TOKEN' \
-d "{
        \"start_time\":\"1409594400\",
        \"end_time\":\"1409598000\",
        \"emails\": [\"[email protected]\"]
} "
[ 
  {
   "object": "free_busy",
   "email": "[email protected]",
   "time_slots": [
      { 
        "object": "time_slot",
        "status": "busy",
        "start_time": 1409594400,
        "end_time": 1409598000
      },
      { 
        "object": "time_slot",
        "status": "busy",
        "start_time": 1409598000,
        "end_time": 1409599000
      }
    ]
  }
]

Recurring Events

Recurring appointments and meetings consist of three things: a recurring master, a number of occurrences that repeat according to a set pattern, and sets of occurrences that have been modified or deleted. Exchange Web Services makes it possible to identify if a calendar item is the master, an occurrence in a series, or an exception to a series. It also allows you to search user calendar folders for recurring meetings and appointments, and iterate through a series of recurring events, including exceptions and deletions.

Working with recurring events in the EWS API is fairly similar to the process of working with single instances of events. When creating recurring events, you need to specify the Recurrance object. If you want to get a recurring event, you need to  make a GetItem request, and specify the occurrence you want with OccurrenceItemId

Recurring appointments can be returned like any other appointment using ExchangeService.FindAppointments method to retrieve all appointments between a given start and end date. However, the master calendar item is not returned as a part of these requests, for this you need to use ExchangeService.FindItems and filter for a time span that includes the time of the master event. 

Recurring Events With Nylas

By default, Nylas only returns the master event, not all of the recurring events. However, it’s extremely easy to return all event recurrences by passing expand_query=’true’ to the as a query parameter to the /events endpoint. In the following example, notice the additional recurring event info embedded into the id field after the underscore and the reference to the original master event’s id in the master_event_id field for each event.

$ curl -X GET 'https://api.nylas.com/events?expand_recurring=true' -H 'Authorization: Bearer ACCESS_TOKEN'
[
    {
        'id': '5soti3r111c0f35dllc0iz2zb_20200317T170000Z', 
        'title': 'Weekly Machinery Sync', 
        'description': 'This is our weekly meeting to stay in sync on upcoming farming equipment!',
        'when': {
            'start_time': 1584464400,
            'end_time': 1584465900, 
            'object': 'timespan'
        }, 
        "participants": [
            {
                "comment": null,
                "email": "[email protected]",
                "name": "George Washington Carver",
                "status": "yes"
            },
            {
                "comment": null,
                "email": "[email protected]",
                "name": "Henry Ford",
                "status": "yes"
            }
        ],
        ], 
        'calendar_id': '5idi2a6***', 
        'status': 'confirmed', 
        'master_event_id': '5soti3r111c0f35dllc0iz2zb', 
        'owner': ' [email protected]', 
        ...
    },
    {
        'id': '8dg2y9scccgacw519fd5iz89h_20200317T170000Z',  
        'when': {
            'start_time': 1584550800,
            'end_time': 1584552600, 
            'object': 'timespan'
        },
        "participants": [
            {
                "comment": null,
                "email": "[email protected]",
                "name": "George Washington Carver",
                "status": "yes"
            },
            {
                "comment": null,
                "email": "[email protected]",
                "name": "Henry Ford",
                "status": "yes"
            }
        ],
        ], 
        'calendar_id': '5idi2a6***', 
        'status': 'confirmed', 
        'master_event_id': '5soti3r111c0f35dllc0iz2zb', 
        'owner': '[email protected]', 
        ...
 

    },
    {
        'id': 'bjds9az3wmaizmd5eaq5q33lr_20200317T170000Z',  
        'when': {
            'start_time': 1584637200,
            'end_time': 1584639000, 
            'object': 'timespan'
        },
        "participants": [
            {
                "comment": null,
                "email": "[email protected]",
                "name": "George Washington Carver",
                "status": "yes"
            },
            {
                "comment": null,
                "email": "[email protected]",
                "name": "Henry Ford",
                "status": "yes"
            }
        ],
        ], 
        'calendar_id': '5idi2a6***', 
        'status': 'confirmed', 
        'master_event_id': '5soti3r111c0f35dllc0iz2zb', 
        'owner': ' [email protected]', 
        ...

    }
]

Note: The returned JSON in this example has been abbreviated for easier reading.

The Nylas Calendar API Reduces Complexity

You might be asking yourself whether to build a direct integration with Exchange Web Services or with Nylas. The Nylas ROI calculator estimates that a direct integration with Exchange for Calendar data and functionality would take you 13,812 hours to build, but would only take 18 days for a single developer to implement the same thing with Nylas. Let’s take a look at some specific examples of how Nylas abstracts away the complexity of building your Exchange Calendar integration.

Events as First Class Objects

EWS requires you to know which calendar an event exists on before you can request it. This isn’t a problem if you only need to access events from a single calendar, but it quickly becomes problematic when you need to manage events across multiple user or shared calendars, and you might be forced to sync a large amount of information from EWS to get the data you need.

With the Nylas Calendar API, events are first class objects, meaning you can access them without prior knowledge of the calendar they are contained in. If you need to search for events on a specific calendar, you can pass calendar_id={id} as a query parameter to the /events endpoint. Here’s what this looks like with our Python SDK.

from nylas import APIClient
nylas = APIClient(
    CLIENT_ID,
    CLIENT_SECRET,
    ACCESS_TOKEN
)
# Return all of the events a user has across all of their calendars
all_events = nylas.events.all()
# Return events only for a specific calendar
my_calendar_events = nylas.events.where(calendar_id='{id}')

Additionally, if you build directly with EWS, you need to manage recurring events by making exceptions in the master event.  When you use Nylas to modify recurring events, you can treat each individual occurrence of the event like any other normal event; the Nylas Sync Engine handles the complex task of making modifications to the master event to ensure all changes are reflected in the user’s calendars.

One Event to Rule Them All

EWS has two representations of events, meetings and appointments, that each have their own methods and properties that need to be considered related to schedule availability and notifications.  Nylas abstracts away this complexity and presents all events in a single, predictable manner that makes it extremely easy to do things like create events and invite participants. Here’s an example of this using our Python SDK:

from nylas import APIClient
nylas = APIClient(
    CLIENT_ID,
    CLIENT_SECRET,
    ACCESS_TOKEN
)

event = nylas.events.create()
event.title = "Learn about our new filament improvements"
event.description = "Let's talk about the recent changes to our filament technology"
event.busy = True
# Provide the appropriate id for a calendar to add the event to a specific calendar
event.calendar_id='{id}'
# Participants are added as a list of dictionary objects
# email is required, name is optional
event.participants = [
    {
    "name": "Thomas Alva Edison", 
    'email': '[email protected]'
    },
    {
    "name": "Susan Seller", 
    'email': '[email protected]_company.com'
    }
]
event.when = {"start_time": 1577829600, "end_time": 1577840400}


# notify_participants='true' will send a notification email to
# all email addresses specified in the participant subobject
event.save(notify_participants='true')

Nylas Provides A Modern, RESTful Interface

Exchange Web Services is only available via a SOAP API or with their C# client library called the EWS Managed API. Nylas, on the other hand, provides a REST API that returns data in a predictable JSON format that makes it much easier to manage calendar data and functionality. Additionally, Nylas provides SDKs for Java, Python, Node.js, and Ruby to suit your needs.

Take Your Calendar Integration Further With Nylas

Why Stop with Exchange Calendars? Nylas supports 100% of email, calendar, and contacts providers out of the box, enabling your users to keep using their calendar provider of choice. This post has only covered a fraction of the benefits the Nylas Communications Platform provides, let’s take a look at a few of the other reason why you should build your calendar integration with Nylas.

About the Author

Ben is the Developer Advocate for Nylas. He is a triathlete, musician, avid gamer, and loves to seek out the best breakfast tacos in Austin, Texas.

Ready to Start Building?