---
title: "How to Integrate with Microsoft Outlook"
img: https://s3.us-east-2.amazonaws.com/unified-article-images/how_to_integrate_with_microsoft_outlook-icon.png
date: 2026-03-05T21:54:00.000Z
tag: Product
description: "If your product needs inbox access, email sending, scheduling, or calendar sync, a Microsoft Outlook API integration usually means building on Microsoft Graph...."
url: "https://unified.to/blog/how_to_integrate_with_microsoft_outlook"
---

# How to Integrate with Microsoft Outlook
------
_March 5, 2026_

If your product needs inbox access, email sending, scheduling, or calendar sync, a **Microsoft Outlook API integration** usually means building on **Microsoft Graph**. That gives you access to mail folders, messages, calendars, events, and change notifications across Microsoft 365 accounts. 


But a production-grade Outlook integration involves more than calling `/me/messages`. You need to register an app in Microsoft Entra ID, choose the right delegated permissions, implement [OAuth](/embeddedauth) correctly, decide between delta sync and change notifications, and handle throttling safely. 


This guide covers:

1. How to integrate directly with Microsoft Graph for Outlook email and calendar
2. The operational complexity you will own
3. How to integrate Outlook using Unified's Messaging and Calendar APIs
4. When to build direct vs use an integration layer

If you are comparing adjacent integrations, you may also want our guides on [Gmail API integration](https://unified.to/blog/gmail_api_integration_a_step_by_step_guide_for_b2b_saas_teams_2026) and [Salesforce API integration](https://unified.to/blog/how_to_integrate_with_the_salesforce_api_a_step_by_step_guide_for_b2b_saas_teams_2026).


## Direct Microsoft Graph setup


### Step 1: Register your app in Microsoft Entra ID


In the Microsoft Entra admin center, create a new app under **App registrations**. Registration gives you an **Application (client) ID** and lets you configure one or more **redirect URIs** under the app's **Authentication** section. Microsoft documents app registration and redirect URI setup in its Graph authentication guidance.


For a B2B SaaS integration, you will usually choose a multi-tenant app registration so customers in different Microsoft 365 tenants can authorize your app. That decision depends on your product and customer base, but the Entra registration flow is where you set it. 


### Step 2: Choose delegated vs application permissions


For inbox and calendar integrations in SaaS products, **delegated permissions** are usually the default. They let your app act on behalf of the signed-in user, and `/me/...` endpoints only work in delegated scenarios. **Application permissions** are app-only and are generally used for background services or tenant-wide access with admin consent.


That distinction matters immediately:

- Use **delegated** when each user connects their own mailbox and calendar
- Use **application** only when you truly need service-level access to mailboxes across a tenant and can support admin consent workflows

### Step 3: Configure the right Graph permissions


For Outlook email and calendar, the common delegated permissions include:

- `Mail.ReadBasic` or `Mail.Read` for reading mail
- `Mail.ReadWrite` for updating or deleting messages
- `Mail.Send` for sending mail
- `Calendars.ReadBasic` or `Calendars.Read` for reading calendars and events
- `Calendars.ReadWrite` for creating or editing events
- `offline_access` if you need refresh tokens for long-lived connections

As with every OAuth integration, request the least privilege you need.


### Step 4: Implement OAuth 2.0 authorization code flow


For user-connected Outlook integrations, the standard flow is the Microsoft identity platform's **authorization code flow**.


You send the user to the authorize endpoint with:

- `client_id`
- `response_type=code`
- `redirect_uri`
- `scope`
- `state`

Then you exchange the returned `code` at the token endpoint, typically including:

- `client_id`
- `client_secret` for confidential clients
- `code`
- `redirect_uri`
- `grant_type=authorization_code`

Request `offline_access` if you need a refresh token so the integration can continue working after the original access token expires. Microsoft's OAuth documentation explicitly calls this out. 


## Core Microsoft Graph endpoints for Outlook email and calendar


### List mail folders


To list Outlook folders, use:


```plain text
GET /me/mailFolders
GET /users/{id}/mailFolders
```


You can also include `includeHiddenFolders=true`, and Graph supports common OData parameters like `$top`, `$skip`, `$select`, `$filter`, and `$orderby` here. 


### List messages


To list all messages:


```plain text
GET /me/messages
GET /users/{id}/messages
```


To list messages in a specific folder:


```plain text
GET /me/mailFolders/{id}/messages
GET /users/{id}/mailFolders/{id}/messages
```


Graph supports `$select` and `$top`, and Microsoft documents some important rules when combining `$filter` and `$orderby`. 


### Get a message


To retrieve a single message:


```plain text
GET /me/messages/{id}
GET /users/{id}/messages/{id}
```


If you need MIME content, append `/$value`. You can also use the `Prefer: outlook.body-content-type` header to request text or HTML body formatting. 


### Send mail


To send an email:


```plain text
POST /me/sendMail
POST /users/{id}/sendMail
```


This requires `Mail.Send`. Microsoft Graph returns `202 Accepted` for successful send requests.


### List calendars


To list calendars:


```plain text
GET /me/calendars
GET /users/{id}/calendars
```


You can also list calendars within a calendar group. OData parameters are supported here as well. 


### List events


To list events from the default calendar:


```plain text
GET /me/calendar/events
GET /users/{id}/calendar/events
```


To list events from a specific calendar:


```plain text
GET /me/calendars/{id}/events
GET /users/{id}/calendars/{id}/events
```


You can set `Prefer: outlook.timezone` to control how start and end times are returned.


### Create and update events


To create an event:


```plain text
POST /me/events
POST /users/{id}/events
POST /me/calendars/{id}/events
```


To update an event:


```plain text
PATCH /me/events/{id}
PATCH /users/{id}/events/{id}
PATCH /me/calendars/{id}/events/{id}
```


Graph supports partial updates, and Microsoft recommends using `transactionId` on create requests for idempotency.


## Change sync options: delta queries vs change notifications


### Delta queries


Microsoft Graph supports **delta queries** for both messages and events.


For mail, you can use:


```plain text
GET /me/messages/delta
GET /me/mailFolders/{id}/messages/delta
```


For calendar sync, Graph supports delta on calendar views, for example:


```plain text
GET /me/calendarView/delta?startDateTime=...&endDateTime=...
```


The pattern is:

1. Make the initial delta request
2. Follow `@odata.nextLink` until exhausted
3. Persist the final `@odata.deltaLink`
4. Reuse that delta link later to retrieve only changes since the last checkpoint

This is the right pattern for efficient pull-based sync.


### Change notifications (webhooks)


Graph also supports **change notifications** for Outlook resources including messages and events. You create a subscription via `POST /subscriptions`, provide your `notificationUrl`, specify the monitored resource, and include `changeType`, `expirationDateTime`, and `clientState`.


Important operational details:

- Graph validates your webhook by sending a `validationToken`
- Your endpoint must return the plain-text token within 10 seconds
- Subscriptions expire and must be renewed
- Outlook resources have bounded subscription lifetimes, so renewal logic is mandatory

In practice, many robust integrations use **change notifications to trigger work** and **delta queries to fetch the actual changes**. That reduces missed updates and keeps sync logic simpler.


## Throttling and retry behavior


Microsoft Graph returns **429 Too Many Requests** when you hit throttling limits. When that happens, Graph usually includes a **Retry-After** header, and Microsoft's guidance is clear: wait the specified number of seconds, then retry. If no `Retry-After` header is present, implement exponential backoff. 


Microsoft also recommends avoiding aggressive polling and using delta queries and change notifications instead, which is especially relevant for inbox and calendar sync. 


## Where direct Outlook integrations become operationally expensive


A direct Microsoft Graph integration means you own:

- Entra app registration and tenant configuration
- Delegated vs application permission strategy
- OAuth flow implementation and refresh token handling
- Mail + calendar endpoint orchestration
- Delta checkpoint storage
- Webhook subscription creation, validation, and renewal
- Throttling management and backoff
- Multi-tenant mailbox isolation
- Admin-consent-heavy scenarios for broader directory access

For a single internal tool, this may be acceptable.


For a customer-facing SaaS product serving many Microsoft 365 tenants, this is real infrastructure work.


## Integrating Microsoft Outlook via Unified


Using the Unified Outlook configuration you shared, the flow is simpler.


### Step 1: Register Outlook OAuth for Unified


For Unified, the redirect URI is:


```plain text
https://api.unified.to/oauth/code
```


You also noted region-specific variants:

- `https://eu.api.unified.to/oauth/code`
- `https://au.api.unified.to/oauth/code`

On the Outlook side, Unified scopes map to Microsoft Graph scopes like:

- `messaging_channel_read` → `Mail.ReadBasic`
- `messaging_message_read` → `Mail.Read`
- `messaging_message_write` → `Mail.Read`, `Mail.Send`, `Mail.ReadWrite`
- `calendar_calendar_read` / `calendar_event_read` / `calendar_busy_read` → `Calendars.Read`
- `calendar_calendar_write` / `calendar_event_write` → `Calendars.ReadWrite`

Plus identity scopes such as `openid`, `email`, `profile`, and `offline_access`, based on the integration sheet you shared.


### Step 2: Authorize a connection


Unified's pattern is:

1. Activate the Outlook integration in your workspace
2. Redirect the user through Unified's authorization flow
3. Receive a `connection_id` after successful authorization

That gives you a stable identifier for future Messaging and [Calendar API](/calendar) calls.


### Step 3: Call Unified's Messaging API


Based on the integration details you shared, Outlook under Unified supports:

- **Channel**: list, get
- **Message**: list, get, create, update, remove

A first-call example to list folders/channels looks like:


```bash
curl -X GET "https://api.unified.to/messaging/CONNECTION_ID/channel?limit=50&offset=0" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```


And to list messages in a folder:


```bash
curl -X GET "https://api.unified.to/messaging/CONNECTION_ID/message?channel_id=CHANNEL_ID&limit=50" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```


To create or send a message:


```bash
curl -X POST "https://api.unified.to/messaging/CONNECTION_ID/message" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "channels": ["CHANNEL_ID"],
    "subject": "Hello",
    "message": "This is the body",
    "message_html": "<p>This is the <strong>HTML</strong> body</p>",
    "attachments": []
  }'
```


### Step 4: Call Unified's Calendar API


From the Outlook mapping you shared, Unified supports:

- **Calendar**: list, get
- **Event**: list, get, create, update, remove
- **Busy**: list

Examples:


List calendars:


```bash
curl -X GET "https://api.unified.to/calendar/CONNECTION_ID/calendar?limit=50&offset=0" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```


List events:


```bash
curl -X GET "https://api.unified.to/calendar/CONNECTION_ID/event?calendar_id=CALENDAR_ID&limit=50" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```


Create an event:


```bash
curl -X POST "https://api.unified.to/calendar/CONNECTION_ID/event" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "calendar_id": "CALENDAR_ID",
    "start": "2026-03-10T15:00:00Z",
    "end": "2026-03-10T16:00:00Z",
    "summary": "Planning meeting",
    "description": "Weekly planning meeting",
    "attendees": [{"email": "user@example.com", "name": "User Name"}]
  }'
```


List free/busy data:


```bash
curl -X GET "https://api.unified.to/calendar/CONNECTION_ID/busy?calendar_ids[]=CALENDAR_ID&start=2026-03-10T00:00:00Z&end=2026-03-10T23:59:59Z" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```


### Step 5: Use passthrough when needed


The Outlook integration details you shared also include passthrough methods (`get`, `post`, `put`, `patch`, `delete`). That gives you a fallback path for Graph features not covered by Unified's normalized Messaging and Calendar models.


## Unified webhooks for Outlook


Based on the Unified Outlook notes you shared:

- Outlook supports both **native** and **virtual** [webhooks](/blog/replacing_polling_with_unified_webhooks_and_virtual_streams) in Unified for messages and calendar events
- Native webhooks are used when Graph supports subscriptions for the resource
- Virtual webhooks are used when polling is needed or selected
- Unified recommends webhooks over polling and applies built-in retry/backoff behavior

That means you can get standardized change notifications without implementing Graph subscription validation and renewal yourself, depending on how you configure the integration.


## Direct vs Unified: when to choose each


### Build direct with Microsoft Graph if:

- Outlook is one of your core product surfaces
- You need full Graph flexibility for mail and calendar features
- You are comfortable owning delta sync, webhook subscriptions, renewal, and throttling logic
- You need app-only scenarios, tenant-wide access, or highly custom Microsoft 365 behavior

### Use Unified if:

- You want one integration surface across Outlook and other providers
- You prefer not to manage Graph-specific OAuth, webhook validation, and renewal logic
- Your product mainly needs common email + calendar behavior
- You want normalized channel, message, calendar, event, and busy abstractions
- You want passthrough available for edge cases

## Final thoughts


A Microsoft Outlook integration is straightforward at the endpoint level.


The engineering complexity shows up in:

- delegated vs application permission decisions
- long-lived OAuth handling
- mailbox and calendar sync design
- webhook validation and renewal
- delta checkpoint management
- throttling and retry behavior

If Outlook email and calendar are central to your product, building directly on Microsoft Graph can make sense.


If they are critical but not differentiating, using a normalized integration layer can reduce time-to-market and lower long-term maintenance.


[→ Start your 30-day free trial](https://app.unified.to/login)


[→ Book a demo](https://calendly.com/d/cph9-g8n-jzg/connect-with-unified)