NewThe TypeScript SDK is on npm as an alpha. Try the quickstart

Early accessNow onboarding early-access teams

One API for every inbox, calendar and contact book.

Connect your customers' Gmail, Microsoft 365 and IMAP accounts. Workwae keeps them in sync, sends from them and calls your webhook on every change.

Code examples

One hosted link for Google, Microsoft and IMAP. Your webhook hears when the account is ready.

connect.ts
// One link: Google, Microsoft or any IMAP mailbox
const session = await workwae.connectSessions.create({
  redirectUri: "https://app.example.com/mail/connected", // allowlisted first, under Settings
  providers: ["google", "microsoft", "imap"],
  externalRef: user.id,
  options: { calendarEnabled: true, contactsEnabled: true },
});

return redirect(session.url);
account.connected
{
  "id": "1849203",
  "type": "account.connected",
  "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b",
  "createdAt": "2026-05-04T09:30:00.000Z",
  "data": {
    "email": "ada@example.com",
    "provider": "gmail",
    "cloud": null,
    "externalRef": "user_42",
    "reauthorized": false
  }
}

Sent from the user's own mailbox, queued and retried. Sent, opened, clicked and bounced come back with your reference.

send.ts
const send = await workwae.outbox.create({
  accountId,
  to: [{ name: "Grace Hopper", address: "grace@example.org" }],
  subject: "Invoice 1001",
  text: "Hi Grace, your invoice is attached.",
  reference: "invoice-1001",
  tracking: { opens: true, clicks: true },
});
send.sent
{
  "id": "1849377",
  "type": "send.sent",
  "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b",
  "createdAt": "2026-05-04T09:30:01.000Z",
  "data": {
    "outboxId": "7b9d1f3a-5c7e-4a9b-8d1f-3a5c7e9b1d3f",
    "reference": "invoice-1001",
    "attempt": 1,
    "providerMessageId": "18f2a3b4c5d6e7f9",
    "internetMessageId": "<20260504093000.1a2b3c@example.com>",
    "sentAt": "2026-05-04T09:30:00.000Z"
  }
}

Provider push turned into signed webhooks. Check the signature, then deduplicate on the event id.

webhook.ts
import { parseWebhook } from "@workwae/sdk";

export async function POST(request: Request) {
  const body = await request.text();
  // Checks the signature and the timestamp
  const event = await parseWebhook(secret, request.headers, body);

  if (event.known && event.type === "message.created") {
    await queue.add(event.id, event.data.message.subject);
  }
  return new Response(null, { status: 204 });
}
message.created
{
  "id": "1849412",
  "type": "message.created",
  "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b",
  "createdAt": "2026-05-04T09:30:00.000Z",
  "data": {
    "message": {
      "subject": "Quarterly report",
      "from": { "name": "Grace Hopper", "address": "grace@example.org" },
      "snippet": "Hi Ada, the numbers for the quarter are attached.",
      "direction": "inbound"
      // id, threadId, to, flags and more
    },
    "mailboxes": [{ "name": "INBOX", "role": "inbox" }]
  }
}

Once a user links Zoom or Webex, any event can carry a meeting that moves and cancels with it.

meeting.ts
const event = await workwae.calendarEvents.create({
  accountId,
  calendarId,
  subject: "Intro call",
  start: { dateTime: "2026-11-04T15:00:00", timeZone: "UTC" },
  end: { dateTime: "2026-11-04T15:30:00", timeZone: "UTC" },
  attendees: [{ address: "sam@example.com" }],
  onlineMeetingService: "zoom",
});

event.onlineMeetingUrl; // the Zoom join link
response
{
  "id": "e1f3a5c7-9b2d-4f6e-a8c0-2e4f6a8b0d1c",
  "subject": "Intro call",
  "onlineMeetingUrl": "https://example.zoom.us/j/84012345678"
  // start, end, attendees, organizer and more
}

Sign-in and every call go to the tenant's own Microsoft cloud, next to worldwide tenants.

gcc-high.ts
// Your own UI, the tenant's own Microsoft cloud
const { authorizeUrl } = await workwae.oauthAuthorizations.create({
  provider: "microsoft",
  oauthAppId: gccHighApp.id, // your app registration for GCC High
  redirectUri: "https://app.example.com/mail/connected",
});

return redirect(authorizeUrl);
account.connected
{
  "id": "1849530",
  "type": "account.connected",
  "accountId": "6f1c2a4e-8b3d-4e5f-9a7b-1c2d3e4f5a6b",
  "createdAt": "2026-05-04T09:30:00.000Z",
  "data": {
    "email": "ada@agency.example",
    "provider": "graph",
    "cloud": "gcc-high",
    "externalRef": "user_42",
    "reauthorized": false
  }
}
GCC High and DoD
Microsoft 365 government clouds, next to worldwide tenants
United States
Where your users' data is stored, on AWS; traffic passes through Cloudflare, and opt-in AI features send text to our AI gateway and its model providers (subprocessors)
AES-256-GCM
Per-record encryption, with keys in HashiCorp Vault
Zoom and Webex
Meetings that follow their calendar events
Connects
  • Gmail
  • Google Workspace
  • Microsoft 365
  • Outlook.com
  • IMAP and SMTP
  • CalDAV
  • CardDAV
Meetings
  • Zoom
  • Webex
  • Microsoft Teams
  • Google Meet
Comparison

Measured against the alternatives.

From each vendor's own public pages, checked October 17, 2026. The full comparison has every row, sources, and where others are ahead.

Full comparison
Workwae, Nylas, Unipile and Aurinko compared
Workwae Nylas Unipile Aurinko
Microsoft 365 GCC High and DoD Yes No N2 Not documented Not documented
Zoom and Webex meetings created with events Yes Partly N7 No U6 Not documented
Import from EmailEngine without re-consent Yes Partly N10 Not documented Not documented
Data hosting United States US or Europe N13 France U12 Not documented
SOC 2 report No Yes N14 Yes U12 No A15

Sources for every competitor cell, read October 17, 2026

Security and privacy

Built for data people trust you with.

Connecting an account is the account owner's decision, and they can take it back at any time.

How we handle data

Only what you approve

Gmail access is gmail.modify, not full mail access, and data is used only to provide your features.

Encrypted value by value

AES-256-GCM per record, with data keys wrapped by a key in HashiCorp Vault. Details.

No ads, sales or AI training

Your users' mail is never sold, used for advertising or used to train AI models.

Disconnect anytime

Deleting an account stops access at once and queues its Google grant for revocation; its data is deleted within 30 days, or at once on request.

Start with one connected account.

We are onboarding a small number of teams. Tell us what you are building.