Calendar sync
Two-way sync between CRM appointments and your Google or Outlook calendar — connect in a click, bookings flow both ways every 15 minutes.
Calendar sync
Calendar sync keeps your CRM appointments and your personal calendar in step. Connect your Google or Microsoft Outlook account from Settings, and from then on: appointments booked in the CRM appear on your calendar, and events you create in your calendar come back into the CRM — checked every 15 minutes.
Who this is for
Anyone who owns appointments — sales agents, managers, admins. Each person connects their own calendar; sync is per user, not per workspace.
Difficulty: Easy · Time: under 5 minutes (client side) · Prerequisites:
- The platform operator has registered the calendar app with Google/Microsoft and set the client credentials (see "For the operator" below). If the provider row shows as unavailable, ask your Super Admin.
- Access to the calendar account you want to connect.
Step 1 — Open the calendar settings
Go to Settings → Communication → Calendar.
You will see a card per provider — Google Calendar and Microsoft Outlook — each with a Connect button.
Step 2 — Connect
- Click Connect next to the provider you use.
- You are sent to that provider's official consent screen (Google or Microsoft). Sign in and grant the calendar permissions shown.
- You return to the CRM's callback and the row flips to connected.
What the permissions mean The CRM asks for read/write access to calendar events plus your email address, so it can tell which calendar belongs to you. It does not read your mail, contacts or files. You can revoke access at any time from your Google/Microsoft account security page — or use Disconnect here.
Step 3 — Verify and forget about it
- The card shows the connection as connected.
- Book a test appointment in the CRM on your own behalf (Appointments & calendar) and give sync a minute — the event should appear on your calendar (the account's primary/default calendar).
What syncs in each direction
| Direction | What happens |
|---|---|
| CRM → calendar | An appointment (MeetingBooking) created in the CRM is posted to the connected calendar |
| Calendar → CRM | Every 15 minutes the sync fetches new, updated and cancelled events since the last sync token and updates the corresponding CRM records |
| Token upkeep | OAuth tokens refresh proactively so the connection does not drop silently |
Outlook disconnect is CRM-side only Disconnect on a Google connection also revokes the refresh token at Google (best effort). On an Outlook connection it removes the CRM's stored connection — the Microsoft-side token grant may remain until it expires or you remove it in your Microsoft account. If in doubt, revoke "Zodiac CRM" in your Microsoft account settings.
One connection per person per provider: connecting again simply updates the existing connection.
Expected result
The provider card shows connected; new CRM appointments show up in your calendar; events created in the calendar appear in the CRM within about 15 minutes (scheduler permitting — on a live install the scheduler runs every minute and the sync job fires every 15).
Common mistakes
- Connecting with the wrong Google/Microsoft account (e.g. a personal account when you work from another one). Disconnect and reconnect with the right account.
- Expecting a different calendar than primary/default to sync. The connection targets the account's primary calendar (Google) / default calendar (Outlook); choosing a specific calendar is not currently offered in the UI.
- Revoking access on the provider side but leaving the CRM row. Disconnect in the CRM too, then reconnect.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Consent screen error when connecting | The OAuth app is not configured or the redirect URI does not match | Operator must fix credentials and the callback URI — see below |
| "State mismatch" / forbidden after consent | The login started in another browser tab, the session changed, or the CRM URL changed mid-flow | Start the connect again from the same browser session |
| Connection shows connected but nothing syncs | Scheduler/worker not running on the server | See Cron & queue workers |
| Events stopped after a password change | Provider revoked the refresh token | Disconnect, reconnect |
| Google connects, Outlook does not (or vice versa) | That provider's credentials are missing in .env |
Operator adds them (below) |
For the operator (Super Admin / developer)
Calendar sync needs one-time app registrations on the provider side:
- Google Cloud Console: create an OAuth client (type: Web application) and register the redirect URI exactly:
Sethttps://your-domain/admin/calendar/oauth/callbackGOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETin the server environment. - Microsoft Entra (Azure AD): register an application and also use the same callback URI
https://your-domain/admin/calendar/oauth/callback. Grant (delegated) permissionsCalendars.ReadWrite,User.Readandoffline_access(the last one is what enables refresh tokens). SetMICROSOFT_CLIENT_IDandMICROSOFT_CLIENT_SECRETin the environment. - Both sets of variables ship commented-out in
.env.example— see Environment variables.
Missing credentials simply mean that provider's Connect button is unavailable; the other provider still works.
Technical details
- Page:
/admin/settings/calendar(Settings → Communication group). Connect route:/admin/calendar/connect/{provider}; callback:/admin/calendar/oauth/callback, protected by a user-bound HMAC-SHA256state(mismatch → 403). Disconnect:POST /admin/calendar/disconnect/{id}. - Model:
CalendarConnection(PROVIDER_GOOGLE,PROVIDER_OUTLOOK); one row per user per provider. - Scopes: Google —
calendar.events,userinfo.email(calendarprimary); Microsoft —Calendars.ReadWrite,User.Read,offline_access(calendardefault). - Sync command:
leadhub:sync-calendars, scheduled every 15 minutes; uses incremental sync tokens per connection and refreshes tokens proactively. - CRM appointments are
MeetingBookingrows; inbound calendar events update the matching bookings.
Related guides
Was this page helpful?
Thanks — noted. ✦