Zapier’s Office 365 API Journey

Since we first heard about the new Office 365 product suite, we at Zapier have been eager to dig into the APIs that would accompany it. So earlier this year, when the Office 365 APIs preview launched at https://dev.office.com/, we jumped at it!

For those of you who aren't familiar with the Office 365 APIs, the preview has these goodies:

  • A REST API for Office 365 for Business (Home & Outlook.com currently excluded)
  • OAuth2 for authentication
  • Endpoints for Mail, Calendar, Contacts, and Files/Folders
  • OData formatting (which provide tons of powerful query string operators)
  • JSON serialization

Previously, much of the Microsoft development ecosystem focused on .NET code. While .NET SDKs still have superb support, this marks an exciting time where language-agnostic REST APIs are first class citizens. For example, Zapier is mostly written in Python and we found it a breeze to connect to the new REST/OAuth/OData Office 365 APIs. Here's how we did it.

Getting started

The first thing you'll need is an Office 365 subscription. They do offer free trials, so you can sign up and start experimenting right away at https://office.microsoft.com/en-us/business/, or get a developer site at https://msdn.microsoft.com/library/office/fp179924(v=office.15).

After you get all settled and are able to log on to https://outlook.office365.com/, you're ready to explore the API. Currently, Basic Authentication is enabled (for testing purposes only) in addition to OAuth2. That means there is a really simple way to explore the API directly from your browser. Just visit https://outlook.office365.com/api/v1.0/Me and enter in your normal Office 365 login credentials; you should see some JSON containing a bunch of handy links.

Let's tour a few of those more interesting links!

A quick tour

Explore the following links to get a list of calendars and events, contacts, and email messages:

I highly recommend keeping your browser session up and running, or using a tool like https://www.hurl.it/ to experiment with requests as you go.

It is also wise to read up on the MSDN REST API docs for more information about how to use the REST API. Additionally, read the OData URI conventions doc for more information about how to use OData query strings for filtering and performance tweaks.

Some real code

Ripped straight out of Zapier, here is some real production code that shows how to use some of the useful resource URLs listed above with Basic Auth (we'll talk about OAuth in a moment!). Remember, these are the same calls you were making in your browser, just scripted!

import requests # install https://docs.python-requests.org/

EMAIL = 'you@yourdomain.onmicrosoft.com' # or your custom domain
PASSWORD = 'yourpassword' # the same one you use to log in with

# Get a list of all calendars.
calendars_url = 'https://outlook.office365.com/api/v1.0/Me/Calendars'

print('Calendars:')
response = requests.get(calendars_url, auth=(EMAIL, PASSWORD))
for calendar in response.json()['value']:
  print(calendar['Name'])
print('')

# Get a list of all events.
events_url = 'https://outlook.office365.com/api/v1.0/Me/Events'

print('Events:')
response = requests.get(events_url, auth=(EMAIL, PASSWORD))
for event in response.json()['value']:
  print(event['Subject'])
print('')

# Get a list of all contacts.
contacts_url = 'https://outlook.office365.com/api/v1.0/Me/Contacts'

print('Contacts:')
response = requests.get(contacts_url, auth=(EMAIL, PASSWORD))
for contact in response.json()['value']:
  print(contact['EmailAddress1'])
print('')

# Get a list of the 10 most recently created contacts.
contacts_url = 'https://outlook.office365.com/api/v1.0/Me/Contacts'
params = {'$orderby': 'DateTimeCreated desc', '$top': '10'}

print('10 Most Recent Contacts:')
response = requests.get(contacts_url, params=params, auth=(EMAIL, PASSWORD))
for contact in response.json()['value']:
  print(contact['EmailAddress1'])
print('')  

# Get a list of the 25 most recently received messages.
messages_url = 'https://outlook.office365.com/api/v1.0/Me/Inbox/Messages'
params = {'$orderby': 'DateTimeReceived desc', '$top': '25', '$select': 'Subject,From'}

print('25 Most Recent Messages:')
response = requests.get(messages_url, params=params, auth=(EMAIL, PASSWORD))
for message in response.json()['value']:
  print(message['Subject'])
print('')

If you are creating a prototype script, you can use Basic Auth to quickly try out the APIs, because it is really simple and easy. However, if you are performing these calls in production, or on behalf of others, don't collect their passwords, just use OAuth (which is much more pleasant for everyone). Let's cover that now.

Connecting OAuth

Now that you have the API landscape under your belt, we can upgrade from Basic Auth to OAuth2. To do that, you'll need to connect your Office 365 Subscription to an Azure account (which contains all the Active Directory apps). Just visit https://manage.windowsazure.com/ to get started.

After you have an Azure account created and connected to your Office 365 app, you'll need to create a new Active Directory application. You might need to create a new directory under your Active Directory tab, but right alongside your Active Directory users, groups, domains, and so on you should see applications. You want to create one of those.

A screenshot of the Microsoft Azure Active Directory portal.

As you create and edit your app, you'll be able to set up your logo, secret keys, redirect/reply URI, and all the other good bits you are familiar with around OAuth. The only difference is that you'll need to select your scopes at application creation time, not in the redirect URI like most apps. You can do that in the "permissions to other applications" section:

A screenshot of the Microsoft Azure permissions to other applications section of the app registration page.

Then you'll want to set these values in the code powering your OAuth app:

It is worth reiterating that you don't need to provide scopes, as those are encoded in the "permissions to other applications" section.

After you finish the flow, just use the access_token and refresh_token in the same way that most OAuth services do. You can learn more about OAuth 2.0 in Azure AD, which should cover much of the basics outlined above.

Putting it into production

Thanks to the adoption of standard web API patterns like OAuth and REST, our company Zapier was able launch its very own Office 365 Integration in just a few days using the same developer platform optimized for the most common web API patterns.

A quick checklist to run down before you go into production:

  • Make sure your refresh tokens swap for a new access token properly.
  • Use filter query strings like $filter=Price+lt+20 to reduce the number of records you request instead of requesting all records and doing it in memory.
  • Add a sanity limit query string like $top=100 to protect your performance.
  • Along with $top=100, consider using something like $orderby=DateTimeReceived+desc to get new records.
  • Use $select=DisplayName,EmailAddress1 to reduce the amount of data to only the bits you need. This is especially useful for email messages (which can be very large).

If you follow these tips, you can be sure that your API calls are quick, efficient and robust. Don't forget to keep your eyes on the Office 365 documentation as they are often updated with new endpoints and features. Likewise, the Office 365 Dev Blog is indispensable!

Bryan Helmig

This post brought to you by Bryan Helmig. Bryan is a co-founder and engineer at Zapier. In addition to being a blues/jazz guitarist and whiskey connoisseur, he's hacked on just about every API available today and has helped design and build the Zapier platform which makes 10s of millions of API calls a day.