From Outlook REST API & EWS to Microsoft Graph
The Outlook REST API v2.0 is gone (March 2024). Exchange Web Services (EWS) hits its hard end-of-life on October 1, 2026. This guide covers every endpoint, OAuth flow, and migration step you need to ship before the deadline.
EWS hard deadline: October 1, 2026. Microsoft confirmed no grace period for Exchange Online. Start your migration now.
// Outlook REST API via Microsoft Graph
// Replace EWS SOAP with a single REST call
const response = await fetch(
'https://graph.microsoft.com/v1.0/me/messages',
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
const { value: messages } = await response.json();
console.log(`Fetched ${messages.length} emails`);What Is the Outlook REST API in 2026?
The term "Outlook REST API" causes confusion in 2026 because Microsoft has used it to describe at least three distinct things over the past decade. Here is the precise current meaning, why it still matters for developers, and what has changed.
Definition: In 2026, "Outlook REST API" is a colloquial term that refers to the Microsoft Graph mail endpoints (https://graph.microsoft.com/v1.0/me/messages). The original dedicated Outlook REST API v2.0 (outlook.office.com/api/v2.0) was permanently decommissioned on March 31, 2024, returning HTTP 410 Gone for all requests. Microsoft Graph is now the single, unified API for mail, calendar, and contacts across Microsoft 365, Exchange Online, Outlook.com, and Teams.
This matters in 2026 for two reasons: first, any application still referencing the old outlook.office.com/api/ domain is broken. Second, applications using Exchange Web Services (EWS) - the older SOAP-based protocol - face a hard enforcement deadline of October 1, 2026 for Exchange Online. Understanding the correct nomenclature is the first step to a successful migration.
| Name | Protocol | Base URL | Status in 2026 |
|---|---|---|---|
| Outlook REST API v2.0 | REST / JSON | outlook.office.com/api/v2.0 | Dead (Mar 2024) |
| Exchange Web Services (EWS) | SOAP / XML | outlook.office365.com/EWS/ | EoL Oct 2026 |
| Microsoft Graph Mail API | REST / JSON | graph.microsoft.com/v1.0/me/messages | Live - Use This |
| MAPI / Outlook COM | COM / Binary | Desktop only | Desktop only |
For a deep dive into Microsoft Graph integration beyond mail (webhooks, delta queries, shared mailboxes), see the Microsoft Graph API email integration guide. The pillar guide covering all email API patterns is at the Email API developer guide.
Building on Outlook in 2026? Unipile gives you a unified email API that handles Microsoft Graph, Gmail, and IMAP with a single integration - no per-provider migration needed.
Build it with UnipileFrom v2.0 to Microsoft Graph: A Brief History
The deprecation of the Outlook REST API v2.0 was not sudden - Microsoft announced it years in advance with multiple deadline extensions. Understanding this history helps you anticipate what Microsoft will do with EWS, and why the October 2026 deadline is being treated as final.
Microsoft introduces a REST-based API at outlook.office.com/api/v2.0 as a modern alternative to EWS. Developers can read mail, manage calendar events, and access contacts via JSON over HTTPS - a significant improvement over SOAP/XML.
Microsoft launches Microsoft Graph as a single endpoint covering all Microsoft 365 services - mail, calendar, contacts, Teams, OneDrive, SharePoint, and more. The graph.microsoft.com domain becomes the canonical way to access Microsoft data programmatically.
Microsoft officially announces the deprecation of the Outlook REST API v2.0 (and v1.0 beta), citing Microsoft Graph as the replacement. The announcement explicitly states the old endpoints will stop working - with a deadline of "late 2022" at the time.
Microsoft extends the deadline twice - first to November 2022, then to March 2023, then to March 2024. Each extension came with a warning: "this is the last extension." Many developers took these extensions as a signal that deadlines were soft. The October 2026 EWS deadline is being enforced more strictly.
The outlook.office.com/api/v2.0 endpoint returns HTTP 410 Gone for all requests. No more extensions. Any application still calling these URLs is broken. "Outlook REST API" now means Microsoft Graph when used correctly. For the full integration guide to Microsoft Graph mail endpoints, see the Microsoft Graph API email integration guide.
Exchange Web Services will stop working for Exchange Online (Microsoft 365 cloud). Microsoft has confirmed this is a hard enforcement date. On-premises Exchange servers are not affected. All cloud-based applications using SOAP/XML EWS calls must have migrated to Microsoft Graph by this date.
Why This Migration Was Inevitable
Modern OAuth 2.0 Security
The older APIs relied on Basic Auth and legacy token formats. Microsoft Graph mandates OAuth 2.0 with Azure Active Directory, aligning with zero-trust security models and eliminating credential exposure risks.
Unified Identity Platform
Microsoft Graph consolidates access to every Microsoft 365 service through a single identity platform. One app registration, one token, one endpoint prefix - versus maintaining separate credentials per legacy API.
Richer Capabilities
Microsoft Graph exposes features EWS never had: delta queries for incremental sync, change notifications (webhooks), search across all content, Teams integration, and Graph-specific analytics - all via clean REST/JSON.
The Real 2026 Deadline: EWS End-of-Life (October 1, 2026)
While the Outlook REST API v2.0 deprecation affected a relatively small group of developers, the EWS end-of-life for Exchange Online is a much larger event. Thousands of enterprise applications, mail clients, calendar sync tools, and backup solutions still rely on Exchange Web Services. October 1, 2026 is the hard cutover - here is what you need to know.
Who Is Affected
- Custom mail clients built on EWS Managed API
- Outlook add-ins using EWS calls (not Graph-based)
- Calendar sync applications (room booking, scheduling)
- Email backup and archiving tools
- CRM / ATS email sync integrations
- Any app using
ExchangeService.NET class
What Stops Working
- NTLM and Kerberos authentication
- Basic Auth over EWS (already deprecated)
- EWS Managed API (
Microsoft.Exchange.WebServices) - Streaming notifications via EWS
- EWS impersonation (
ExchangeImpersonation) - SOAP operations: GetItem, FindItems, SyncFolderItems
What Is NOT Affected
- On-premises Exchange 2016 / 2019 / SE EWS
- Microsoft Graph API (this is the migration target)
- IMAP / SMTP for basic send/receive
- ActiveSync (deprecated separately)
- Outlook desktop app itself (uses proprietary MAPI)
Migration Timeline Reality
- Simple app with 1-2 EWS operations: 1-2 weeks
- Mid-complexity app (mail + calendar + contacts): 4-8 weeks
- Enterprise app with EWS impersonation: 8-16 weeks
- Vendor dependency (waiting for library update): uncontrolled
- Testing + UAT + production deployment: add 2-4 weeks
On a tight timeline for EWS migration? Unipile's unified email API abstracts Microsoft Graph (and Gmail and IMAP) so you migrate once and never touch provider-specific code again. See the full email API guide for architecture patterns.
Start Your MigrationOutlook REST API Endpoints in 2026 (via Microsoft Graph)
All Outlook REST API functionality is now served via Microsoft Graph at https://graph.microsoft.com/v1.0. Below are the key mail, calendar, and contacts endpoints with their HTTP methods and a code sample for each category.
Mail Endpoints
| Method | Endpoint | Description | Required Scope |
|---|---|---|---|
| GET | /me/messages |
List messages in inbox (supports $filter, $orderby, $top, $select) | Mail.Read |
| GET | /me/messages/{id} |
Get a single message by ID with full body and headers | Mail.Read |
| POST | /me/sendMail |
Send a new email immediately (no draft saved) | Mail.Send |
| POST | /me/messages |
Create a draft message (send separately via /send) | Mail.ReadWrite |
| PATCH | /me/messages/{id} |
Update a message (mark read, move, change categories) | Mail.ReadWrite |
| DELETE | /me/messages/{id} |
Delete a message permanently | Mail.ReadWrite |
| GET | /me/mailFolders |
List all mail folders (Inbox, Sent, Drafts, custom) | Mail.Read |
| GET | /me/messages/delta |
Incremental sync - get only changed messages since last sync | Mail.Read |
// POST /me/sendMail - Send via Outlook REST API (Microsoft Graph)
const response = await fetch('https://graph.microsoft.com/v1.0/me/sendMail', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: {
subject: 'Hello from Microsoft Graph',
body: { contentType: 'Text', content: 'EWS migration complete!' },
toRecipients: [{ emailAddress: { address: 'user@example.com' } }]
},
saveToSentItems: true
})
});
// 202 Accepted = sent successfullyCalendar Endpoints
| Method | Endpoint | Description | Required Scope |
|---|---|---|---|
| GET | /me/events |
List all calendar events (supports $filter by start/end) | Calendars.Read |
| GET | /me/calendarView |
Get events in a time range (startDateTime + endDateTime params) | Calendars.Read |
| POST | /me/events |
Create a new calendar event with attendees and recurrence | Calendars.ReadWrite |
| GET | /me/calendars |
List all user calendars (primary, shared, group) | Calendars.Read |
Contacts Endpoints
| Method | Endpoint | Description | Required Scope |
|---|---|---|---|
| GET | /me/contacts |
List all contacts in the default contacts folder | Contacts.Read |
| POST | /me/contacts |
Create a new contact | Contacts.ReadWrite |
| GET | /me/contactFolders |
List contact folders | Contacts.Read |
Want a single API that handles Outlook REST (Microsoft Graph), Gmail, and IMAP? Unipile wraps all three with one unified endpoint. Compare providers at email API providers comparison.
Build with Unified APIOAuth 2.0 Authentication: The Only Path Forward
NTLM, Kerberos, and Basic Authentication are all gone for Microsoft 365. OAuth 2.0 is now the mandatory authentication method for every Microsoft Graph API request. There is no fallback, no compatibility mode, and no timeline extension. If your application still uses legacy auth flows, it is already blocked for new tenants and will break entirely for all tenants when EWS enforcement completes in October 2026.
Azure AD App Registration: 5 Steps
portal.azure.com - Azure Active Directory - App registrations - New registration. Choose a name, set the supported account type (single tenant, multitenant, or personal accounts), and configure a redirect URI.API permissions, add Microsoft Graph permissions. Choose Delegated (user-context) or Application (daemon) permissions based on your use case. Most email/calendar integrations use Delegated permissions.Certificates & secrets, create a new client secret. Copy the value immediately - it is only shown once. For production apps, a certificate is more secure than a client secret.https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize with client_id, scope, redirect_uri, and response_type=code. After consent, exchange the code for tokens at the token endpoint.Mail.ReadWrite.All) require tenant admin consent before any user can authorize. For these, use the admin consent endpoint: /adminconsent flow with a tenant admin account.Required OAuth Scopes for Graph API
| Scope | Type | Use Case |
|---|---|---|
| Mail.Read | Delegated | Read user mailbox messages |
| Mail.ReadWrite | Delegated | Read and modify mailbox messages |
| Mail.Send | Delegated | Send email on behalf of user |
| Calendars.ReadWrite | Delegated | Read and modify calendar events |
| Contacts.Read | Delegated | Read user contacts |
| Mail.ReadWrite.All | Application | Read/write all mailboxes (daemon apps, requires admin consent) |
| Calendars.ReadWrite.All | Application | Read/write all calendars (daemon apps, requires admin consent) |
| offline_access | Delegated | Required to receive a refresh token for long-lived access |
Authorization Code Flow - Node.js Example
// Step 1: Build authorization URL
const authUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize?`
+ new URLSearchParams({
client_id: CLIENT_ID,
response_type: 'code',
redirect_uri: REDIRECT_URI,
scope: 'Mail.Read Mail.Send Calendars.ReadWrite offline_access',
response_mode: 'query'
});
// Step 2: Exchange code for tokens
const tokenRes = await fetch(
`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`,
{
method: 'POST',
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: authCode,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code'
})
}
);
const { access_token, refresh_token } = await tokenRes.json();
// Step 3: Refresh when access token expires (typically 1 hour)
const refreshRes = await fetch(tokenEndpoint, {
method: 'POST',
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
refresh_token: storedRefreshToken,
grant_type: 'refresh_token'
})
});
refresh_token securely in your database and use it to request new access tokens without requiring the user to re-authenticate. Refresh tokens can expire after 90 days of inactivity. Always request the offline_access scope to receive a refresh token.
Migration Checklist: EWS to Microsoft Graph in 10 Steps
Microsoft has confirmed hard enforcement of EWS deprecation for Exchange Online on October 1, 2026. There is no grace period, no rollback option, and no compatibility bridge. Every application still using Exchange Web Services for Microsoft 365 will break on that date.
Code Migration Examples: EWS vs Microsoft Graph
Below are 4 common operations compared side-by-side: the legacy EWS SOAP approach on the left, the Microsoft Graph REST equivalent on the right. The shift from verbose XML to clean JSON is immediately apparent.
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
Traversal="Shallow"
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
Default
MaxEntriesReturned="10"
Offset="0"
BasePoint="Beginning"/>
Id="inbox"/>
GET /me/messages
?$select=subject,from,receivedDateTime,bodyPreview
&$top=10
&$orderby=receivedDateTime desc
Authorization: Bearer {access_token}
// Response (JSON):
{
"value": [
{
"id": "AAMkAGI...",
"subject": "Hello",
"from": {
"emailAddress": {
"address": "sender@example.com"
}
},
"receivedDateTime": "2026-05-27T..."
}
],
"@odata.nextLink": "https://..."
}
MessageDisposition="SendAndSaveCopy"
xmlns="http://schemas.microsoft.com/.../messages">
Hello from EWS
BodyType="HTML">
Message body
to@example.com
POST /me/sendMail
Authorization: Bearer {access_token}
Content-Type: application/json
{
"message": {
"subject": "Hello from Graph",
"body": {
"contentType": "HTML",
"content": "Message body
"
},
"toRecipients": [
{
"emailAddress": {
"address": "to@example.com"
}
}
]
},
"saveToSentItems": true
}
// Response: HTTP 202 Accepted (no body)
Traversal="Shallow">
AllProperties
MaxEntriesReturned="50"
StartDate="2026-05-01T00:00:00Z"
EndDate="2026-05-31T23:59:59Z"
/>
Id="calendar"/>
GET /me/events
?$select=subject,start,end,location,organizer
&$filter=start/dateTime ge '2026-05-01T00:00:00Z'
and end/dateTime le '2026-05-31T23:59:59Z'
&$top=50
&$orderby=start/dateTime asc
Authorization: Bearer {access_token}
// Returns a clean JSON array of
// calendar event objects - no XML parsing
Id="inbox"/>
NewMailEvent
DeletedEvent
POST /subscriptions
Authorization: Bearer {access_token}
Content-Type: application/json
{
"changeType": "created,updated,deleted",
"notificationUrl": "https://yourapp.com/webhook",
"resource": "/me/messages",
"expirationDateTime": "2026-06-03T18:00:00Z",
"clientState": "your-secret-state"
}
// Graph POSTs to your URL on every change.
// Renew subscription before expiry.
// No persistent connection required.
Common Pitfalls: Permissions, Rate Limits, Throttling
Even developers experienced with Exchange Web Services regularly hit the same walls when migrating to Microsoft Graph. These 6 pitfalls account for the majority of production incidents during migration. Understanding them now saves days of debugging later. For a broader perspective on how these challenges compare across providers, see our comparison of email API providers.
| Type | Context | Admin consent |
|---|---|---|
| Delegated | User signed in | Sometimes |
| Application | No user / daemon | Always |
HTTP 429 with a Retry-After header specifying the wait time in seconds. Ignoring this header and retrying immediately results in an extended ban. Always implement exponential backoff with the exact Retry-After value.
@odata.nextLink in the response, you silently miss data. Always loop: if @odata.nextLink is present, make another GET request to that URL (it includes the skip token) until the field is absent.
Mail.ReadWrite.All, Calendars.ReadWrite.All, and User.Read.All require a tenant administrator to grant consent before any user can authorize your app. Without admin consent, the OAuth flow returns an AADSTS65001 error. Use the /adminconsent endpoint during app onboarding for enterprise customers.
deltaLink token in the final page. Store this token persistently - it is your sync cursor. If you lose it, you must perform a full resync. Never hardcode a time range - use the deltaLink to avoid processing duplicates or missing changes.
POST /me/messages/{id}/attachments/createUploadSession) and upload in chunks. Attempting to inline a large attachment results in a 413 Request Entity Too Large error.
Skip the Migration Headache: Unified Email API Approach
A full EWS-to-Graph migration for a complex application takes 4 to 8 weeks of engineering time. You need to register Azure apps, implement OAuth flows, handle token refresh, manage throttling, rewrite every SOAP call, update error handling, and test across environments. Then do it again when Microsoft changes something.
Unipile abstracts Microsoft Graph, Gmail, and IMAP under a single unified API. You authenticate your users once via Unipile, and read/send email, sync calendars, and manage contacts across all three providers with the same endpoints - no Azure app registration, no per-provider OAuth flows, no throttling logic to maintain. See our complete email API guide and email API provider comparison to understand the landscape.
50 lines of Microsoft Graph vs 5 lines of Unipile
// 1. Azure app registration (portal.azure.com)
// 2. OAuth authorization code flow
const authUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize?`
+ new URLSearchParams({
client_id: CLIENT_ID,
response_type: 'code',
redirect_uri: REDIRECT_URI,
scope: 'Mail.Read offline_access',
response_mode: 'query'
});
// 3. Handle redirect, exchange code for tokens
const tokenRes = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
method: 'POST',
body: new URLSearchParams({
client_id: CLIENT_ID, client_secret: CLIENT_SECRET,
code: authCode, redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code'
})
});
const { access_token, refresh_token } = await tokenRes.json();
// 4. Store + refresh tokens on expiry (every hour)
// 5. Call Graph with Bearer token
const res = await fetch('https://graph.microsoft.com/v1.0/me/messages?$top=10', {
headers: { Authorization: `Bearer ${access_token}` }
});
// 6. Handle throttling (HTTP 429 + Retry-After)
if (res.status === 429) {
const retryAfter = res.headers.get('Retry-After');
await sleep(retryAfter * 1000);
// retry...
}
// 7. Paginate via @odata.nextLink
const data = await res.json();
let messages = data.value;
while (data['@odata.nextLink']) { /* ... */ }
// No Azure app, no OAuth flows to implement,
// no throttling logic, no token refresh.
// Works for Outlook AND Gmail AND IMAP.
const client = new UnipileClient(API_KEY);
const messages = await client.email.listMessages({
account_id: userAccountId, // linked account
folder: 'INBOX',
limit: 10
});
// Same code, same response format
// for Outlook, Gmail, and IMAP.
// Unipile handles OAuth, throttling,
// pagination, and token refresh.
Outlook REST API & EWS - FAQ
Common questions about Outlook REST API retirement, EWS deprecation, and migration to Microsoft Graph
No. The Outlook REST API (v2.0 and beta) was retired by Microsoft. All requests to the legacy Outlook REST endpoints now fail. The official replacement is Microsoft Graph, which covers all the same email and calendar operations plus much more. If your application still uses Outlook REST endpoints, migration to Graph is not optional.
The Outlook REST API was a dedicated REST API covering only Outlook mailbox operations. Microsoft Graph is the unified API for the entire Microsoft 365 ecosystem: Outlook mail, calendar, contacts, Teams, SharePoint, OneDrive, and more. Both use OAuth 2.0 authentication, but Graph uses the single base URL https://graph.microsoft.com/v1.0 and offers a more consistent, feature-rich interface than the retired Outlook-specific endpoints.
Microsoft has set October 1, 2026 as the hard enforcement date for EWS deprecation in Exchange Online (Microsoft 365). After this date, EWS will no longer function for Microsoft 365 mailboxes. There is no grace period and no announced extension. EWS will continue to work for on-premises Exchange Server installations, which are not affected by this deadline.
Microsoft Graph is the official replacement for EWS. Every EWS operation has a Graph equivalent: FindItem becomes GET /me/messages, CreateItem (send mail) becomes POST /me/sendMail, streaming notifications become Graph webhooks via POST /subscriptions. Authentication changes from NTLM/Kerberos/Basic Auth to OAuth 2.0 via Azure AD. For teams that need a simpler path, a unified email API like Unipile abstracts all three providers under one SDK.
No. The Outlook REST API v2.0 is retired. Requests to those endpoints will fail with errors. Microsoft Graph is the only supported path for Outlook email and calendar integration. All new integrations must target https://graph.microsoft.com/v1.0 and use OAuth 2.0 authentication.
Effort depends on your EWS implementation's complexity. A simple integration with a few read/write operations typically takes 1-2 weeks. A complex application with streaming notifications, delta sync, multi-folder operations, and extensive error handling can take 4-8 weeks. The migration requires: Azure AD app registration, OAuth 2.0 implementation, endpoint-by-endpoint replacement, throttling logic, pagination updates, and error format changes. An alternative is to use Unipile's Microsoft Graph abstraction, which handles most of this complexity automatically.
The October 2026 deadline applies specifically to Exchange Web Services (EWS) usage in Exchange Online. Outlook add-ins that use the Office.js API are on a separate timeline. However, Microsoft has been phasing out legacy COM and VSTO add-ins in favor of web-based Office Add-ins. If your add-in makes EWS calls internally, those calls will break in October 2026 regardless of the add-in framework. Check the Microsoft 365 roadmap for the latest guidance specific to your add-in type.
Since the Outlook REST API is retired, the relevant scopes are for Microsoft Graph. Core email scopes: Mail.Read (read messages), Mail.Send (send email), Mail.ReadWrite (read and modify messages), Calendars.ReadWrite (calendar access), Contacts.Read (contacts). Always include offline_access to receive a refresh token. Application-level scopes like Mail.ReadWrite.All require admin consent from the tenant administrator and should only be used for daemon scenarios with no user context. See our Microsoft Graph OAuth guide for a complete setup walkthrough.
Microsoft Graph enforces rate limits at approximately 10,000 requests per 10 minutes per application per tenant. When throttled, the API returns HTTP 429 Too Many Requests with a Retry-After header specifying the exact number of seconds to wait. The critical rule: always honor the Retry-After value exactly. Retrying before that window closes extends the throttling period. For multi-tenant SaaS applications where each tenant has separate limits, throttling at one tenant does not affect others. Also compare IMAP as an alternative if throttling at scale is a concern.
Unipile is a unified email API that wraps Microsoft Graph, Gmail, and IMAP under a single SDK. Rather than implementing Microsoft Graph OAuth flows, managing access tokens, handling throttling, and writing per-provider code, you connect your users' accounts through Unipile and use one consistent API for all three providers. This is particularly effective for SaaS applications that need to support Outlook and Gmail simultaneously without maintaining separate integration code for each. Unipile operates as an independent technical intermediary, acting on behalf of each authenticated user, and is not affiliated with or endorsed by Microsoft.
Skip the EWS migration entirely. Our team is here to help.
Build Now