Skip to content

Google Calendar#

Google Calendar is registered for OAuth-backed API sync with sync-coupled user import. It pulls events from the authenticated user's primary calendar into a reviewable import session, proposes TeamBoost user mappings from 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 primary-calendar events from Google Calendar API v3 ✅ Built
USER_IMPORT Event actors imported during sync ✅ Built
WEBHOOK Not built

The endpoints below live under /api/v1/providers/google-calendar/.... 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#

Google Calendar uses OAuth 2.0, not an API key. Configure these environment variables before using the OAuth routes:

GOOGLE_CALENDAR_CLIENT_ID=<google-oauth-client-id>
GOOGLE_CALENDAR_CLIENT_SECRET=<google-oauth-client-secret>
GOOGLE_CALENDAR_REDIRECT_URI=https://<host>/api/v1/providers/google-calendar/oauth/callback
GOOGLE_CALENDAR_SCOPES=https://www.googleapis.com/auth/calendar.readonly

The redirect URI must exactly match the URI configured on the Google OAuth client. Missing app config returns oauth_provider_not_configured.

OAuth Authorization#

Start authorization:

GET /api/v1/providers/google-calendar/oauth/authorize?organization_id=<id>

Returns an authorization URL plus a signed, expiring state:

{
  "status": "success",
  "data": {
    "provider": "google-calendar",
    "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth?...",
    "state": "<signed-state>",
    "expiresAt": "2026-07-01T12:10:00.000Z"
  }
}

Complete the callback:

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

The callback exchanges the code for Google OAuth tokens and stores an encrypted OAUTH_TOKEN credential for the organization. The response returns only metadata:

{
  "status": "success",
  "message": "OAuth credential stored.",
  "data": {
    "provider": "google-calendar",
    "configured": true,
    "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_token_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 Google Calendar:

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

Verification uses the stored OAuth access token to make a cheap CalendarList probe. If the token has expired, verification and sync refresh it before calling Google.

Importing From Google Calendar#

POST /api/v1/providers/google-calendar/imports/sync?organization_id=<id>

The first shipped sync is intentionally bounded:

  • primary calendar only;
  • expanded event instances (singleEvents=true);
  • a review window from 7 days in the past through 90 days in the future;
  • deleted/cancelled events included when the API returns them.

The adapter calls:

  • GET https://www.googleapis.com/calendar/v3/users/me/calendarList
  • GET https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events

CalendarList and Events pagination are followed. Google quota responses (429 and 403 usage-limit 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#

Google Calendar source TeamBoost draft field Notes
Event summary title Missing or hidden summaries are blocking projectionErrors.
Event resource type Calendar events default to OTHER with a mapping note.
Event description description Passed through when present.
Event status status confirmed and tentative map to NOT_STARTED; cancelled maps to CANCELED; tentative adds a mapping note.
Calendar priority priority Calendar has no priority; defaults to UNKNOWN.
Event creator creatorId Resolved through the user mapping when matched; otherwise left unset with a note.
Event attendees ownerId Attendees are imported for user mapping 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 summary projectTitle
Calendar/event refs descriptionJson Preserves calendar id, event id, iCalUID, HTML link, recurrence refs, visibility, actors, and raw start/end context.

User Import During Sync#

USER_IMPORT rides sync. Proposed users come from event creator, organizer, and attendees, deduped by provider id, email, then name. Google Calendar is not a Workspace directory API; standalone directory import is not built.

Not Built Yet#

  • CSV or .ics file import.
  • Calendar selection and per-organization sync window preferences.
  • Persisted incremental sync token state.
  • Google Calendar push notifications/webhooks.
  • Standalone Google Workspace directory import.
  • Live OAuth validation in this repo's automated tests; use a real Google Cloud OAuth client and test calendar for release smoke.