1. Features
  2. Organization connections
Organization connections

Connect a whole organization, without asking every user.

A Google Workspace or Microsoft 365 administrator authorizes workwae once. You list the directory, add mailboxes by address, and each one becomes an account with the same mail, calendar and contacts API as an account a user connected.

contoso.ts
// Your own Entra app, signed with a certificate
const connection = await workwae.orgConnections.create({
  kind: "microsoft_app",
  name: "Contoso",
  cloud: "global",
  credential: {
    type: "certificate",
    clientId,
    certificate,
    privateKey,
  },
  directoryId,
});

// Request a token the way accounts will
const { checks } = await workwae.orgConnections.test({
  connectionId: connection.id,
});

// Pick mailboxes from the directory
const page = await workwae.orgConnections.directoryEntries({
  connectionId: connection.id,
  query: "sales",
});
What you get

Organization-wide access, with the checks built in

One API for Google Workspace domain-wide delegation, Microsoft 365 app-only access and shared mailboxes. Accounts added this way sync and send like any other.

Google Workspace delegation

Upload a service account key. workwae checks and seals it, then returns the client id and the exact scopes for the Workspace admin to authorize under Security, API controls, Domain-wide delegation.

Microsoft 365 app-only access

Use workwae's app with admin consent, or your own app registration with a client secret or a certificate and its PKCS#8 private key.

Every Microsoft cloud

A Microsoft connection names its cloud: worldwide (including GCC), GCC High, DoD or 21Vianet. Sign-in and Graph calls stay in that cloud.

Directory listing

Page through the organization's users, up to 200 at a time, matching the start of names and addresses. Each entry shows the account already added for it, if any.

Add mailboxes in bulk

Up to 100 addresses per call. Each mailbox is checked through the connection first, and you get one result per address: created, exists or failed with the reason.

A test that names what's missing

Testing requests a token the way accounts will and reports each check, required or optional, so an administrator sees which scope or permission still needs granting.

Shared mailboxes

Open a Microsoft 365 shared mailbox as an account of its own, through the grant of a user who can already open it, over Graph or Exchange IMAP.

Revoked access, recovered

When an administrator withdraws authorization, the affected accounts stop with consent_revoked. Restore it, test the connection, and they resume on their own.

Consent bound to the sign-in

With workwae's Microsoft app, the directory is taken from the administrator's own sign-in and recorded only for the console session that started it. A directory belongs to one such connection.

How it works

Three ways to reach mailboxes nobody signed in to

What each kind of access asks the administrator for, how workwae reaches the mailbox, and what happens when authorization is withdrawn.

Organization access methods compared
Google Workspace delegation Microsoft 365 app-only Microsoft 365 shared mailbox
Who authorizes A Workspace admin authorizes the service account's client id for the connection's scopes in the Admin console. A directory administrator grants admin consent to the app. A user who can already open the mailbox connects with shared mailbox access turned on (options.sharedMailboxesEnabled).
Credential The service account key, sealed. Each token is a signed assertion for one mailbox. workwae's app for the cloud, or your own app registration with a client secret or a certificate. The delegating user's own grant; the shared mailbox holds none of its own.
Scopes and permissions gmail.modify always; calendar by default; contacts when you choose; admin.directory.user.readonly with a directory admin. Required: Mail.ReadWrite, Mail.Send. Optional: Calendars.ReadWrite, MailboxSettings.Read, Contacts.ReadWrite, User.Read.All. Mail.ReadWrite.Shared and Mail.Send.Shared, plus Calendars.ReadWrite.Shared and Contacts.ReadWrite.Shared for calendar and contacts.
Directory The Admin SDK user list, read as the directory admin you name, only when you ask. Graph's user list, with User.Read.All. Not applicable
How the mailbox is reached Gmail, Calendar and People work unchanged, as for any Google account. Graph, addressed as /users/{mailbox}, change notification subscriptions included. Graph as /users/{mailbox}, or Exchange IMAP logged in as user@domain\shared.
When access is withdrawn Google refuses the token: the accounts move to reauth_required with consent_revoked. A token without Mail.ReadWrite means consent was withdrawn: consent_revoked. The delegating account is deleted: reauth_required with delegate_missing.
  • Connection status

    pending_consent until a Microsoft directory consents, unverified after a credential or scope change, then active or failing with the failed check as its detail.

  • Optional means optional

    A missing optional permission limits only calendar, contacts or the directory. An account without contacts access reports what to grant, and its mail keeps syncing.

  • Authorize every listed scope

    Every Google mailbox token asks for all of the connection's scopes, so the admin must authorize each one the connection lists, or no token is issued and mail stops too.

  • The connection owns its accounts

    Accounts added through a connection can't be taken over by a user sign-in, and a connection can't be deleted while live accounts still use it.

National clouds

Microsoft 365 in the cloud the organization uses

Tokens don't cross clouds, and each cloud needs its own app registration. Every Microsoft connection and account records its cloud, and workwae signs in and calls Graph there.

Microsoft clouds and their endpoints
Cloud Covers Sign-in Graph
global Worldwide Microsoft 365, including GCC login.microsoftonline.com graph.microsoft.com
gcc-high US Government GCC High login.microsoftonline.us graph.microsoft.us
dod US Government DoD login.microsoftonline.us dod-graph.microsoft.us
china Microsoft 365 operated by 21Vianet login.chinacloudapi.cn microsoftgraph.chinacloudapi.cn
  • GCC (moderate) is part of the worldwide cloud; only GCC High and DoD have their own endpoints.
  • Some Graph features arrive late in national clouds. Where change notifications are missing, the scheduled poll keeps accounts current.
  • In 21Vianet, Graph has no message delta yet, so Graph mail sync, app-only included, does not run there. Mail for those mailboxes runs over IMAP and SMTP with a user's Microsoft sign-in.
  • A connection through workwae's app needs workwae's app registration in that cloud. In any cloud, you can register your own app and connect with its secret or certificate.
Build it

Set up Google Workspace delegation

Register the service account key, hand the admin the client id and scopes, and test once they're authorized.

  • Scopes come back in the Admin console's order, ready to paste next to the client id.
  • Calendar is on and contacts off by default. Leaving one out stops only that sync; mail keeps working.
  • A directory admin is optional. Without one, add mailboxes by address; tests then impersonate the user you name.
workspace.ts
const connection = await workwae.orgConnections.create({
  kind: "google_delegation",
  name: "Acme Workspace",
  domain: "acme.com",
  serviceAccountKey, // the JSON key file
  calendarEnabled: true,
  contactsEnabled: true,
  directoryAdmin: "it-admin@acme.com",
});

// For the admin: Security > API controls > Domain-wide delegation
showAdmin(connection.clientId, connection.google?.scopes);

// After they authorize it, test as the directory admin
const result = await workwae.orgConnections.test({
  connectionId: connection.id,
});
for (const check of result.checks) {
  if (!check.isOk) console.warn(check.name, check.detail);
}
Build it

Add the mailboxes you need

Walk the directory, skip mailboxes that are already accounts, and add the rest. Every address gets its own result, in request order.

  • Checked before it's created: a delegated token for Google, the inbox for Microsoft.
  • Failures say why, with the reason the API would answer: no such user, scopes not granted, no mailbox access, or the plan's account limit.
  • Bring your own ids. An externalRef per mailbox links the account to your records.
add-mailboxes.ts
import { paginate } from "@workwae/sdk";

const listDirectory = workwae.orgConnections.directoryEntries;
const query = { connectionId, query: "support" };

const mailboxes = [];
for await (const entry of paginate(listDirectory, query)) {
  if (entry.accountId) continue; // already an account
  const { email, id: externalRef } = entry;
  mailboxes.push({ email, externalRef });
}

const { items } = await workwae.orgConnections.addAccounts({
  connectionId,
  mailboxes,
});
for (const added of items) {
  if (added.status !== "failed") continue;
  // e.g. invalid_grant (no such user) or consent_revoked
  console.warn(added.email, added.error?.reason);
}
Build it

With your own app registration, send the administrator to a consent link and get them back to your app. Shared mailboxes need only a user's grant.

  • The return names the outcome: status, connection_id, error and your state. The consenting directory is recorded and the connection tested.
  • workwae's own app is consented from the console, so the directory comes from the administrator who actually signed in.
  • Shared mailboxes open with a grant connected with shared mailbox access. Gmail has no delegated shared mailboxes; use domain-wide delegation there.
consent.ts
// Your own app registration, in GCC High
const connection = await workwae.orgConnections.create({
  kind: "microsoft_app",
  name: "Contoso (GCC High)",
  cloud: "gcc-high",
  credential: { type: "client_secret", clientId, clientSecret },
});

// Send the administrator here
const { consentUrl } = await workwae.orgConnections.consent({
  connectionId: connection.id,
  redirectUri: "https://app.example.com/admin/consent-done",
  state: tenantRef,
});

// A shared mailbox, through a user's own grant
const billing = await workwae.sharedMailboxes.create({
  accountId: userAccountId,
  email: "billing@contoso.us",
});
Events

Know when access changes

Accounts added through a connection announce the same account events as any other, as signed webhooks and in the change feed.

Account events for organization connections
Event When
account.connected A mailbox became an account. After a passing test brings stopped accounts back, it arrives again with reauthorized: true.
account.reauth_required The connection's authorization was refused for the account; reason carries the provider's refusal.
account.initialized The first sync of a new account finished, with its mailbox and message counts.
account.updated An account's status, settings or other fields changed.
FAQ

Questions administrators ask

Do users have to sign in?

No. Once an administrator has authorized the connection, you add mailboxes by address. Each one is checked through the connection before its account is created.

What happens if the administrator removes access?

The affected accounts move to reauth_required with consent_revoked, and the next test marks the connection failing. Once access is restored, a passing test returns those accounts to active and announces them again.

Can a user fix a stopped connection account by signing in?

No. Accounts added through a connection belong to it, so a user sign-in can't re-authorize them. Fix the connection, then test it.

Can I open a delegated or shared Gmail mailbox?

Gmail has no delegated access to another user's mailbox through its API. Add such mailboxes through a Google Workspace domain-wide delegation connection.

Why is consent to workwae's Microsoft app started from the console?

workwae's app is shared by every customer, so the directory is recorded only from the administrator's own sign-in and only for the console session that started it. A consent link forwarded to another organization's administrator attaches nothing. With your own app registration, you can start consent through the API.

Can I delete a connection?

Yes, once no live account uses it. Delete its accounts first; while any remain, the delete is refused with connection_in_use.

Early access

Bring a whole organization in at once.

workwae is in early access. Tell us what you are building, and read the docs in the meantime.