Skip to content

Microsoft Outlook#

Microsoft Outlook is registered for Microsoft Graph OAuth-backed calendar sync with sync-coupled user import. It pulls events from the authenticated user's default Outlook calendar into a reviewable import session, proposes TeamBoost user mappings from the signed-in account and event actors, and projects each event into the internal integrations task-create draft for operator review.

Capability Method Status
CSV_IMPORT Not built
SYNC Pull default-calendar events from Microsoft Graph v1.0 ✅ Built
USER_IMPORT Signed-in account, organizer, and attendees imported during sync ✅ Built
WEBHOOK Not built

The endpoints below live under /api/v1/providers/microsoft-outlook/.... The authorization URL route and sync route require an organization-scoped user token. The OAuth callback route is unauthenticated for provider redirects; the signed state value supplies the organization binding.

OAuth Setup#

Microsoft Outlook uses the Microsoft identity platform OAuth 2.0 authorization code flow, not an API key. Configure these environment variables before using the OAuth routes:

MICROSOFT_OUTLOOK_CLIENT_ID=<entra-app-client-id>
MICROSOFT_OUTLOOK_CLIENT_SECRET=<entra-app-client-secret>
MICROSOFT_OUTLOOK_REDIRECT_URI=https://<host>/api/v1/providers/microsoft-outlook/oauth/callback
MICROSOFT_OUTLOOK_AUTHORITY=https://login.microsoftonline.com/common
MICROSOFT_OUTLOOK_SCOPES=openid email profile offline_access User.Read Calendars.Read

The redirect URI must exactly match the URI configured on the Microsoft Entra app registration. Missing app config returns oauth_not_configured. The default authority supports both Microsoft work/school and personal accounts; set it to https://login.microsoftonline.com/organizations when the registered app is work/school-only.

OAuth Authorization#

Start authorization:

GET /api/v1/providers/microsoft-outlook/oauth/authorize?organization_id=<id>

Returns an authorization URL plus a signed, expiring state:

{
  "status": "success",
  "data": {
    "provider": "microsoft-outlook",
    "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?...",
    "state": "<signed-state>",
    "expiresAt": "2026-07-01T12:10:00.000Z"
  }
}

Complete the callback:

GET /api/v1/providers/microsoft-outlook/oauth/callback?state=<signed-state>&code=<code>

The callback exchanges the code for Microsoft OAuth tokens, probes GET https://graph.microsoft.com/v1.0/me, and stores an encrypted OAUTH_TOKEN bundle for the organization. The response returns only metadata:

{
  "status": "success",
  "message": "OAuth credential stored.",
  "data": {
    "provider": "microsoft-outlook",
    "configured": true,
    "accountId": "00000000-0000-0000-0000-000000000000",
    "accountName": "Mara Creator",
    "credentialType": "OAUTH_TOKEN",
    "updatedAt": "2026-07-01T12:00:00.000Z"
  }
}

Access and refresh tokens are never returned by an endpoint. Invalid or expired state returns invalid_oauth_state; a provider callback error returns oauth_authorization_failed; a failed code exchange returns oauth_exchange_failed. See the shared OAuth callback contract for callback bounds, duplicate refusal, and the authenticated relay shape.

Credential Status And Verification#

The generic credential status, verify, and delete routes work for Microsoft Outlook:

GET /api/v1/providers/microsoft-outlook/credentials?organization_id=<id>
POST /api/v1/providers/microsoft-outlook/credentials/verify?organization_id=<id>
DELETE /api/v1/providers/microsoft-outlook/credentials?organization_id=<id>

Verification uses the stored OAuth bundle to call GET /me. If the token is near expiry, verification and sync refresh it before calling Microsoft Graph.

Importing From Microsoft Outlook#

POST /api/v1/providers/microsoft-outlook/imports/sync?organization_id=<id>

The first shipped sync is intentionally bounded:

  • default calendar only;
  • expanded event instances through Microsoft Graph calendarView;
  • a review window from 7 days in the past through 90 days in the future;
  • immutable Outlook item ids requested with the Graph Prefer header;
  • UTC event times requested with the Graph Prefer header.

The adapter calls:

  • GET https://graph.microsoft.com/v1.0/me
  • GET https://graph.microsoft.com/v1.0/me/calendars
  • GET https://graph.microsoft.com/v1.0/me/calendar
  • GET https://graph.microsoft.com/v1.0/me/calendar/calendarView

Graph pagination via @odata.nextLink is followed. Microsoft Graph 429 responses are retried with bounded backoff. Invalid or revoked OAuth tokens return credential errors, and refresh failures return oauth_token_refresh_failed.

Projection Field Coverage#

Microsoft Outlook source TeamBoost draft field Notes
Event subject title Missing subjects are blocking projectionErrors.
Event resource type Calendar events default to OTHER with a mapping note.
Event bodyPreview description Passed through when present. Text bodies are used only when no preview exists.
Event cancelled flag status Active events map to NOT_STARTED; cancelled events map to CANCELED.
Event importance priority high maps to HIGH; low maps to LOW; other values default to UNKNOWN with a note.
Event organizer creatorId Resolved through the user mapping when matched; otherwise left unset with a note.
Event attendees ownerId Attendees are imported for user matching but are not assigned as owners automatically.
Organizer requestedById Preserved in descriptionJson; requester mapping is left unset until the product rule is confirmed.
Event start/end plannedStartDate, estimatedStartDate, plannedEndDate Calendar length is not converted into TeamBoost effort duration.
Calendar name projectTitle
Calendar/event refs descriptionJson Preserves calendar id/name, event id, iCalUId, web link, recurrence refs, sensitivity, online meeting URL, actors, and raw start/end context.

User Import During Sync#

USER_IMPORT rides sync. Proposed users come from the signed-in /me account, event organizer, and attendees. Users are deduped by provider account id, email, then name where possible. Microsoft Outlook is not using Microsoft Graph directory or People APIs in this first ship; standalone directory import is not built.

Not Built Yet#

  • CSV, PST, or .ics file import.
  • Calendar selection and per-organization sync window preferences.
  • Persisted delta sync state.
  • Microsoft Graph change notifications/webhooks.
  • Standalone Microsoft Entra directory or People API import.
  • Live OAuth validation in this repo's automated tests; use a real Entra app, mailbox, and test calendar for release smoke.