Skip to main content
Was this helpful?

External Sync API

External Calendar Sync

Connect Google or Microsoft calendars and map them to PrimeCal

This controller manages provider connection state, OAuth handoff, mapped calendar sync, provider disconnects, and manual sync execution.

JWT for setupPublic OAuth callbackGoogle and MicrosoftOptional automation linkage

Source

  • Controller: backend-nestjs/src/modules/calendar-sync/calendar-sync.controller.ts
  • DTOs: backend-nestjs/src/dto/calendar-sync.dto.ts, backend-nestjs/src/modules/calendar-sync/dto/oauth-callback.query.dto.ts
  • Provider enum: backend-nestjs/src/entities/calendar-sync.entity.ts

Authentication and Permissions

  • Setup and management routes require authentication.
  • The OAuth callback is public because the provider must call it directly.
  • The callback resolves the user from the state value or the userId query param.
  • Sync state is always user-scoped.

Endpoint Reference

MethodPathPurposeRequest or queryAuthSource
GET/api/calendar-sync/statusGet provider connection and sync status.NoneJWT or user API keymodules/calendar-sync/calendar-sync.controller.ts
GET/api/calendar-sync/auth/:providerGet the provider OAuth URL.Path: providerJWT or user API keymodules/calendar-sync/calendar-sync.controller.ts
GET/api/calendar-sync/callback/:providerHandle the OAuth callback and redirect to the frontend.Path: provider, query: code,state,userId,session_state,iss,scopePublicmodules/calendar-sync/calendar-sync.controller.ts
POST/api/calendar-sync/syncPersist the selected external calendar mappings.Body: provider,calendarsJWT or user API keymodules/calendar-sync/calendar-sync.controller.ts
POST/api/calendar-sync/disconnectDisconnect all sync providers for the user.NoneJWT or user API keymodules/calendar-sync/calendar-sync.controller.ts
POST/api/calendar-sync/disconnect/:providerDisconnect one provider.Path: providerJWT or user API keymodules/calendar-sync/calendar-sync.controller.ts
POST/api/calendar-sync/forceRun a manual sync immediately.NoneJWT or user API keymodules/calendar-sync/calendar-sync.controller.ts

Request Shapes

Providers

Current SyncProvider enum values:

  • google
  • microsoft

Sync mappings

SyncCalendarsDto in backend-nestjs/src/dto/calendar-sync.dto.ts

  • provider: required enum google|microsoft
  • calendars: required array of CalendarSyncDto

CalendarSyncDto

  • externalId: required string
  • localName: required string
  • bidirectionalSync: optional boolean, default true
  • triggerAutomationRules: optional boolean, default false
  • selectedRuleIds: optional number array

OAuth callback query

OAuthCallbackQueryDto

  • code: required string, max 2048 chars
  • state: optional string, max 512 chars
  • userId: optional integer, minimum 1
  • session_state: optional string, max 256 chars
  • iss: optional string, max 512 chars
  • scope: optional string, max 2048 chars

Example Calls

Read sync status

curl "$PRIMECAL_API/api/calendar-sync/status" \
-H "Authorization: Bearer $TOKEN"

Start provider OAuth

curl "$PRIMECAL_API/api/calendar-sync/auth/google" \
-H "Authorization: Bearer $TOKEN"

Save external calendar mappings

curl -X POST "$PRIMECAL_API/api/calendar-sync/sync" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "google",
"calendars": [
{
"externalId": "primary",
"localName": "Family Calendar",
"bidirectionalSync": true,
"triggerAutomationRules": true,
"selectedRuleIds": [14]
}
]
}'

Disconnect one provider

curl -X POST "$PRIMECAL_API/api/calendar-sync/disconnect/microsoft" \
-H "Authorization: Bearer $TOKEN"

Response and Behavior Notes

  • GET /api/calendar-sync/status returns a providers array with provider, isConnected, calendars, and syncedCalendars.
  • GET /api/calendar-sync/auth/:provider returns { authUrl }.
  • The callback redirects to /calendar-sync on the configured frontend with success=connected or an encoded error.
  • Mapping writes, disconnects, and force-sync calls return short { message } payloads.

Best Practices

  • Always read /api/calendar-sync/status before rendering sync settings or import pickers.
  • Use the backend-generated auth URL from /api/calendar-sync/auth/:provider; do not build provider URLs on the client.
  • Keep selectedRuleIds as small as possible when enabling automation triggers on imported calendars.
  • Use /api/calendar-sync/force for manual repair or support flows, not as a polling mechanism.
  • Handle callback failures via the redirected error query string and show a user-friendly retry path.