Bookings Staff Availability Sync from Outlook
On a schedule, the flow reads staff out-of-office and busy time from their Outlook calendars and blocks the matching time in Microsoft Bookings so customers can't book over PTO, meetings, or leave. Notifies staff of the synced blocks and flags conflicts with existing appointments. Keeps Bookings availability accurate.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow keeps Microsoft Bookings availability accurate by syncing each staff member's Outlook calendar. On an hourly schedule it reads Busy and Out-of-Office (OOF) time across a configurable window and creates matching availability blocks in Bookings so customers can't book over PTO, meetings, or leave. It flags conflicts with existing Bookings appointments in Teams rather than overwriting them, notifies staff of synced blocks, and writes an idempotency ledger to Dataverse so the same event is never blocked twice.
Why it matters: A customer booking onto a staffer's PTO or meeting is a guaranteed bad experience. Syncing real availability from Outlook prevents it - automatically.
Status: Built. Ships Off (demo). Going live requires only connection authorization and environment-variable configuration. Solution: FlowLibsBookingsStaffAvailabilitySync.
Idempotency / conflict design: every busy event is keyed by its Outlook event id in the Dataverse ledger (flowlibs_BookingAvailabilityBlock). On each run, already-synced events are skipped. New events are only blocked when no existing Bookings appointment overlaps; otherwise the overlap is logged as a Conflict and flagged in Teams so it is never silently overwritten.
Dataverse table flowlibs_BookingAvailabilityBlock (Bookings Availability Block) columns: flowlibs_name (Block Key, primary), flowlibs_staffemail, flowlibs_staffname, flowlibs_sourceeventid, flowlibs_sourcesubject, flowlibs_showas, flowlibs_blockstart, flowlibs_blockend, flowlibs_bookingsblockid, flowlibs_syncstatus, flowlibs_syncedon.
Use Case
A services team wants Bookings availability to reflect each staffer's true Outlook calendar automatically, with no manual blocking. Operations gets a run summary; conflicts that need a human are routed to a Teams channel.
Flow Architecture
Recurrence
Recurrence (Hourly)Sync cadence.
Initialize varSyncWindowDays / varWindowStart / varWindowEnd / varStaffMap
Initialize VariableCompute the sync window and parse the staff -> calendar / staff-id map JSON.
List Bookings Businesses
Bookings ListBookingsBusinessUserAsAdminConnector-first: validate the Bookings business the connection administers.
For Each Staff
Apply to each (sequential)Process each staffer one at a time.
Get Staff Busy Time -> Filter Busy And OOF
Outlook GetEventsCalendarView + Filter arrayRead the staffer's Outlook calendar across the window and keep only Busy/OOF events.
For Each Busy Event -> Check Existing Block -> Condition Is New Block
Apply to each + Dataverse ListRecords + ConditionIdempotency: skip events already synced; only new events proceed.
Check Bookings Conflict -> Condition Has Conflict
HTTP -> Microsoft Graph calendarView + ConditionList existing Bookings appointments overlapping the busy event.
Flag Conflict Teams / Log Conflict Record (conflict) or Create Bookings Block / Log Block Record (no conflict)
Teams + Dataverse CreateRecord, or HTTP -> Graph appointments + Dataverse CreateRecordOn overlap, flag in Teams and log a Conflict row; otherwise create the Bookings block and log a Blocked row.
Notify Staff Teams
Teams PostMessageToConversationTell the staffer how many events were synced.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_BookingsBusinessId | String | contoso@contoso.onmicrosoft.com | Target Bookings business (SMTP/id). |
| flowlibs_StaffCalendarMap | String | [{"email":"alice@contoso.com","name":"Alice","calendarId":"...","staffId":"..."}] | JSON array mapping staff -> Outlook calendar id + Bookings staff id. |
| flowlibs_SyncWindowDays | String | 30 | How many days ahead to sync. |
| flowlibs_BookingsBlockServiceId | String | REPLACE_BOOKINGS_BLOCK_SERVICE_ID | Bookings service id used to represent a hold/block appointment. |
| flowlibs_BookingsSyncNotifyEmail | String | ops@yourcompany.com | Ops mailbox for the run summary. |
| flowlibs_AzureTenantId | String | <your-tenant-id> | Graph OAuth tenant. |
| flowlibs_GraphClientId | String | <configure> | Graph OAuth client id. |
| flowlibs_GraphClientSecret | String | <configure> | Graph OAuth client secret. |
| flowlibs_AdminTeamsGroupId | String | <your-team-id> | Teams team (group) for notifications. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Office 365 Outlook | shared_office365 | GetEventsCalendarView SendEmailV2 |
| Microsoft Teams | shared_teams | PostMessageToConversation |
| Microsoft Bookings | shared_microsoftbookings | ListBookingsBusinessUserAsAdmin |
| Microsoft Dataverse | shared_commondataserviceforapps |
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Buffer
- Add a travel buffer around external meetings by widening the block start/end before Create Bookings Block.
- Selective
- The Filter already keeps only Busy/OOF; add tentative to also block tentative holds.
- Two-way
- Extend with a reverse leg that writes Bookings appointments back onto the staffer's Outlook calendar.
- Cadence / horizon
- Change the Recurrence interval and flowlibs_SyncWindowDays for a longer or shorter look-ahead.
- Routing
- Point conflict alerts at a dedicated scheduling-ops Teams channel via the Teams env vars.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Window end
Upper bound of the sync window.
EXPR.02Busy/OOF filter
Keeps only Busy or Out-of-Office events.
EXPR.03Idempotency key
Unique key per staffer + event.
EXPR.04Already-synced test
True when the event has not been synced yet.
EXPR.05Conflict test
True when an existing appointment overlaps.
EXPR.06Graph block endpoint
Endpoint to create a Bookings block appointment.
Customize & download
Generate a ready-to-import copy of this solution with your environment-variable values baked in — available on Base, Pro, or Team.
Upgrade to customize
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.