---
title: "Migrate from Exchange Web Services (EWS) · Workwae"
description: "Exchange Online is retiring EWS. Replace your EWS integration with one API over Microsoft Graph: connect mailboxes, map operations, swap streams for webhooks."
url: https://workwae.com/migrate/ews
---

1. [Migrate](https://workwae.com/migrate/)
2. Exchange Web Services

MigrateFrom EWS

# Replace your EWS integration before April 2027.

Exchange Online started switching EWS off on October 1, 2026. Workwae connects Microsoft 365 mailboxes through Microsoft Graph and gives your code one API for mail, calendars and contacts, so there is no EWS client left to port.

[Plan your migration](https://workwae.com/early-access/) How it works

- Graph under the hood
- [GCC High](https://workwae.com/glossary#gcc-high) and [DoD](https://workwae.com/glossary#dod)
- Webhooks instead of streams

unread.tsunread.py

```ts
// Before: FindItem over EWS, SOAP, a stored mailbox login
// After: one call, whichever provider the mailbox is on
const { items } = await workwae.messages.list({
  accountId,
  unread: true,
});
```

```python
# Before: FindItem over EWS, SOAP, a stored mailbox login
# After: one call, whichever provider the mailbox is on
page = workwae.messages.list(
    account_id=account_id,
    unread=True,
)
```

Why now

## The dates that decide your plan.

As of October 30, 2026, from Microsoft’s [deprecation page](https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-ews-exchange-online) and [Exchange Team blog](https://techcommunity.microsoft.com/blog/exchange/exchange-online-ews-your-time-is-almost-up/4492361).

### October 1, 2026

Phased disablement starts. Tenants that never set `EWSEnabled` are switched to `False`, and EWS calls get a 403.

### An admin can re-enable it

Until April 2027, a tenant admin can turn EWS back on, with an app ID allow list. Your customers decide that, not you.

### April 1, 2027

EWS is disabled for good in Exchange Online, with no exceptions past that date.

### On-premises Exchange stays

Exchange Server keeps EWS. Workwae does not speak EWS, so on-premises servers connect over IMAP and SMTP.

The full timeline, the tenant controls and the Graph mapping are in [Exchange Web Services is being retired](https://workwae.com/blog/ews-retirement-microsoft-graph).

How it works

## Rewrite the calls, reconnect the mailboxes.

There is no EWS import. Workwae has no EWS connector, so the move is a code change plus one sign-in or [admin consent](https://workwae.com/glossary#admin-consent) per mailbox.

1.

   ### Inventory what you call

   List the EWS operations your code uses and whether it runs as the user or impersonates mailboxes. Most apps use a handful.

2.

   ### Pick the connection

   Delegated sign-in for each user, or an organization connection that an administrator consents to for many mailboxes.

3.

   ### Connect mailboxes

   Send users through hosted connect, keyed to your own record with `externalRef`.

4.

   ### Swap the calls

   Replace each EWS operation with its Workwae call, from the table below.

5.

   ### Replace subscriptions

   Drop the streaming, pull or push subscription and add a Workwae webhook endpoint.

6.

   ### Switch and retire

   Run both side by side per mailbox, then remove your app from the tenant’s EWS allow list.

Consent

## Graph permissions are a new consent.

An EWS app holds `EWS.AccessAsUser.All` or `full_access_as_app`. Graph asks for separate permissions, so plan for users or an administrator to consent again.

### Delegated, per user

Hosted connect asks for `Mail.ReadWrite` and `Mail.Send`, plus `Calendars.ReadWrite` and `Contacts.ReadWrite` only when you turn those on.

### App-only, per directory

An organization connection uses your Entra app with Graph application permissions, consented by an administrator. It replaces `full_access_as_app` and impersonation.

### Your app or ours

Use your own Entra app so the consent screen names your product, or the platform app. GCC High and DoD need an app registered in that cloud.

### Shared mailboxes

A delegated grant with the `.Shared` permissions opens the shared mailboxes the user can reach.

connect.tsconnect.py

```ts
// Delegated: one link per user, keyed to your own record
const session = await workwae.connectSessions.create({
  redirectUri: "https://app.example.com/mail/connected", // allowlisted first, under Settings
  providers: ["microsoft"],
  externalRef: user.id,
  loginHint: user.email,
  options: { calendarEnabled: true, contactsEnabled: true },
});

// App-only: your Entra app, consented by the directory's administrator
const connection = await workwae.orgConnections.create({
  kind: "microsoft_app",
  name: "Contoso",
  cloud: "global",
  credential: { type: "certificate", clientId, certificate, privateKey },
  directoryId,
});
await workwae.orgConnections.test({ connectionId: connection.id });
```

```python
# Delegated: one link per user, keyed to your own record
session = workwae.connect_sessions.create(
    redirect_uri="https://app.example.com/mail/connected",  # allowlisted first, under Settings
    providers=["microsoft"],
    external_ref=user.id,
    login_hint=user.email,
    options={"calendar_enabled": True, "contacts_enabled": True},
)

# App-only: your Entra app, consented by the directory's administrator
connection = workwae.org_connections.create(
    kind="microsoft_app",
    name="Contoso",
    cloud="global",
    credential={
        "type": "certificate",
        "client_id": client_id,
        "certificate": certificate,
        "private_key": private_key,
    },
    directory_id=directory_id,
)
workwae.org_connections.test(connection_id=connection.id)
```

What maps where

## From EWS operations to Workwae calls.

Workwae has its own mail, calendar and contact model, the same for Gmail, Microsoft 365 and IMAP. It is not a pass-through of Graph.

**Operation mapping**

| In EWS | In Workwae |
| --- | --- |
| `FindItem`, `GetItem` on messages | `messages.list` and `messages.get`; ranked full-text search over the synced index |
| `UpdateItem` (read state and similar) | `messages.update`, written to the provider and the index |
| `CreateItem` and `SendItem` for mail | `outbox.create`, with scheduling and undo |
| Calendar items | `calendarEvents.create`, `calendarEvents.update` and `calendarEvents.respond` |
| `GetUserAvailability` | `availability.find` |
| Contacts | `contacts.create` and `contacts.update` |
| `SyncFolderItems`, `GetEvents` | The [change feed](https://workwae.com/glossary#change-feed), paged by transaction id |
| Streaming, pull and push subscriptions | Signed webhooks with a delivery log and replays |
| Impersonation with `full_access_as_app` | An organization connection with application permissions |

**Not offered, with or without EWS**

Workwae has no calls for these. Microsoft’s [parity roadmap](https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-ews-exchange-online) says which have a Graph equivalent.

- Public folders
- Archive mailboxes and mailbox import and export
- Inbox rules, out-of-office settings and MailTips

**Stored ids need new keys**

Workwae ids are new. Keep the mailbox’s `externalRef` as your link, and key messages by Workwae id after each account’s first sync, which ends with `account.initialized`.

FAQ

## Questions teams ask.

**Will our users have to sign in again?**

Yes, in most cases. An EWS grant is a different permission from the Graph ones Workwae uses, so users sign in through hosted connect, or an administrator consents once for an organization connection. If your own app already holds Graph consent for some users, you can import their refresh tokens with `accounts.create` instead ([your own OAuth app](https://workwae.com/migrate/#own-app)).

**Can we keep running EWS while we migrate?**

Only if the customer’s tenant admin allows it. Admins can re-enable EWS until April 1, 2027, in Baseline Security Mode or with `Set-OrganizationConfig -EWSEnabled $true`. After that there is no switch.

**Does Workwae connect to on-premises Exchange?**

Not over EWS. A server that allows IMAP and SMTP connects as an [IMAP account](https://docs.workwae.com/guides/imap). Microsoft is not retiring EWS in Exchange Server.

**Do we need our own Entra app registration?**

No, but your own app puts your product name on the consent screen and is the way to connect GCC High and DoD, where each cloud needs its own registration ([GCC High and DoD](https://workwae.com/blog/gcc-high-email-api)).

**What replaces EWS streaming notifications?**

Webhooks. Workwae keeps the Graph subscriptions and delta queries, with a backstop poll, and sends your endpoint signed events such as `message.created`. Verify them with `parseWebhook` in the TypeScript SDK or `parse_webhook` in the Python SDK ([webhooks guide](https://docs.workwae.com/guides/webhooks)).

**Which Microsoft clouds work?**

Commercial and GCC, GCC High and DoD over Graph. 21Vianet mailboxes connect over IMAP and SMTP, because Graph mail sync does not run there yet ([Microsoft 365](https://workwae.com/providers/microsoft-365)).

**Are the SDKs stable?**

Not yet. `@workwae/sdk` for TypeScript is at 0.1.0-alpha and `workwae` for Python is at 0.1.0a2, and Workwae is in early access.

## Ready to move off EWS?

Tell us what your integration calls and which Microsoft clouds your customers are in, and we will plan the move with you.

[Request early access](https://workwae.com/early-access/) [Talk to us](https://workwae.com/support)
