Skip to content

Enterprise Integration

Microsoft 365 + Graph API Integration — How Velocity X Syncs Outlook Calendars, Room Booking, and Teams Meetings

Webhooks, Conflict Resolution, and Tenant Isolation

📅 🔗 👥

Google Calendar integration is table stakes. Most field-sales tools sync with Google, squint at Outlook, and call it a day. If you're selling to Australian enterprise — banks, insurance, logistics, public service — you're walking straight into Outlook-only tenants where Google Calendar is forbidden. Velocity X syncs bidirectionally with Microsoft 365: reps book time on the map, Outlook updates. Admin assigns a meeting room in Teams, Velocity X reflects it in 2 seconds. No polling, no manual reconciliation, no eventual consistency.

Here's what makes it hard, and how we solved it.

Microsoft Graph Permissions and Tenant Isolation

Google OAuth is simple: you approve once, you're in. Microsoft Graph requires tenant-specific authority URLs and delegated vs. application permissions. Velocity X uses delegated permissions so the sync respects RLS — if a rep can't see a calendar, the integration won't expose it either. The scopes are narrow: Calendars.ReadWrite, Calendars.ReadWrite.Shared, and User.Read to fetch the logged-in user's identity.

During OAuth, we redirect to https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize instead of the common endpoint. This locks the connection to a single tenant — a hard requirement for orgs with strict identity policies. On token exchange, we store the tenant ID alongside the refresh token, encrypted in Postgres bytea. Silent refresh happens 5 minutes before expiry so users never see a "reconnect" prompt.

Subscription Webhooks and Change Notifications

Once OAuth completes, Velocity X creates a Microsoft Graph subscription for me/events with changeType: updated,created,deleted. Microsoft delivers change notifications to a Netlify function within 1–3 minutes (not real-time, but tolerable). Each notification includes a resourceData object with the event's ID and changeKey — a server-side ETag that uniquely identifies the event version.

We queue notifications with processed = false. A background job (5-second interval) fetches the full event from Graph using the event ID, verifies the changeKey matches (to reject stale notifications), and reconciles it into our state. If the changeKey differs, it means a newer version exists — we fetch the latest. This prevents race conditions where multiple notifications for the same event arrive out-of-order.

Calendar Conflict Resolution with ETags

Both the rep and the Outlook admin can edit the same event. Velocity X uses ETag-based conflict detection: the changeKey is the conflict marker. When the rep updates an event locally, we fetch the current state from Graph, compare the ETag, and if it differs, someone else edited it. We apply a last-write-wins rule: the system with the most recent lastModifiedDateTime wins. Timestamps are server-side (Graph uses ISO 8601), so no clock-skew surprises.

Example: rep books a client call for 3pm, sends it to Velocity X (local timestamp 3:02pm). Admin in Outlook moves it to 4pm (Outlook timestamp 3:05pm). Webhook arrives. We compare: Outlook is newer, so 4pm wins. The rep's local state updates on next sync. No UI modal, no conflict warning — just convergence.

Room Booking and Resource Calendars

Enterprise orgs publish resource calendars (meeting rooms, vehicles, equipment). Velocity X can sync with these: the org maps room calendars to the Velocity X field territory, and when a rep books a slot, the room's Outlook calendar blocks automatically. This requires Calendars.ReadWrite.Shared scope to update shared calendars. Microsoft enforces organizer constraints — only the org's resource account can edit its own calendar — so Velocity X creates events on behalf of the resource, signing the API request with a service principal if the org is large enough. For smaller orgs, we fall back to delegate-on-behalf scopes.

Teams Meeting Links and Auto-Attach

When a rep creates an event in Velocity X, the backend adds a Teams meeting link if the org has a Teams license. The Graph API supports isOnlineMeeting: true, which auto-generates a onlineMeeting.joinUrl on create. Teams meeting links work cross-tenant for guests — a rep invites a customer with a different tenant, the customer gets a Teams join link, no Microsoft account required. Velocity X strips the link from the invite if the org disables it via admin panel.

Frequently Asked Questions

Does Velocity X support shared mailboxes?

Partially. A shared mailbox calendar can be synced if the user has been granted delegate access. We fetch the calendar via /users/{shared-mailbox}/calendar. Write support requires the org's resource account to own the event, which gets complex. Most orgs avoid shared mailbox calendars in favour of resource calendars (rooms) or distribution groups.

What if an event is marked private or confidential?

Velocity X respects the sensitivity flag. Private events show as "Busy" on the map (no details). Confidential events are hidden entirely unless the rep is the organizer. This is enforced client-side and server-side — we never log private event data.

Can I use both Google and Outlook for different teams?

Yes. Each org can connect multiple calendar systems simultaneously. If some reps use Google Workspace and others use Microsoft 365, Velocity X syncs both. The conflict-resolution rule applies across both: last-write-wins uses server timestamps, regardless of calendar backend.

What happens if the org revokes the app's access?

Graph subscriptions are invalidated immediately. The background job fails on next fetch, the org admin gets a Slack notification, and calendar sync pauses. One re-auth click resumes syncing. Events already in Velocity X remain cached; you don't lose the map.

How does Velocity X handle recurring events and exceptions?

Recurring events are synced as a series. If a rep edits one instance (creates an exception), Graph sends a separate event with isReminderOn: false (the API's way of marking exceptions). Velocity X tracks both the series and the exception so the calendar reflects all-day shifts accurately.

What's the typical sync latency?

Outlook change → Graph notification = 1–3 minutes. Webhook processing + fetch = 2–5 seconds. Total = 60–180 seconds for the map to reflect an Outlook edit. Reverse (Velocity X → Outlook) = sub-second if no tenant throttling applies.

The Bottom Line

Microsoft Graph is more verbose than Google Calendar API, but it's also stricter about security and tenant isolation — exactly what large AU enterprises demand. Velocity X handles OAuth-per-tenant, ETag conflict resolution, shared calendar access, Teams meeting generation, and transparent reconnection all in one step. If you're bidding on organisations with Microsoft-only stacks, look for a partner that's built this depth. Check the pricing or read our breakdown of calendar sync architecture for white-label portals.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.