Skip to content

Calendar API

This document describes the endpoints for integrating external calendars (Google, Outlook) with the user's workspace. All endpoints require authentication.


Google Integration

Initiate Google Connection

Generates a Google OAuth authorization URL wrapped by WorkOS. The frontend should redirect the user to the returned redirectUrl to begin the consent flow.

Endpoint: POST /api/v1/calendar/google/connect

Request Body:

{
  "state": "random_string_xyz",
  "codeChallenge": "pkce_challenge_string"
}

Parameters:

  • state (required): A random string generated by the client to prevent CSRF attacks.
  • codeChallenge (required): The PKCE code challenge generated by the client.

Success Response: 200 OK

{
  "authData": {
    "redirectUrl": "https://api.workos.com/oauth/authorize?response_type=code&client_id=...&provider=Google..."
  }
}

Finalize Connection

Completes the OAuth flow by exchanging the authorization code for access and refresh tokens. This endpoint is called after the user is redirected back from Google/WorkOS.

Endpoint: POST /api/v1/calendar/google/finalize-connection

Request Body:

{
  "code": "0192e...",
  "codeVerifier": "pkce_verifier_string..."
}

Parameters:

  • code (required): The authorization code received in the query parameters from the WorkOS redirect.
  • codeVerifier (required): The original PKCE verifier used to generate the codeChallenge in the initiate step.

Success Response: 200 OK

List Calendars

Retrieves the list of all calendars associated with the user's Google account (e.g., Primary, Birthdays, Shared Calendars).

Endpoint: GET /api/v1/calendar/google/calendars

Request Body: None

Success Response: 200 OK

[
  {
    "id": "primary",
    "name": "john.doe@example.com",
    "color": "#123456"
  },
  {
    "id": "addressbook#contacts@group.v.calendar.google.com",
    "name": "Birthdays",
    "color": "#92e1c0"
  }
]

Batch List Events

Retrieves events for multiple calendars or time ranges in a single request. This endpoint is optimized to reduce payload size by returning instances for recurring events (expanded) but stripping unused metadata.

Endpoint: POST /api/v1/calendar/google/events

Request Body:

{
  "calendars": [
    {
      "calendarId": "primary",
      "timeMin": "2025-12-01T00:00:00Z",
      "timeMax": "2026-01-31T23:59:59Z"
    },
    {
      "calendarId": "team@example.com",
      "timeMin": "2025-12-01T00:00:00Z",
      "timeMax": "2026-01-31T23:59:59Z"
    }
  ]
}

Parameters:

  • calendarId (required): The ID of the calendar to fetch (use "primary" for the main calendar).
  • timeMin (required): Start of the time range (RFC3339 format).
  • timeMax (required): End of the time range (RFC3339 format).

Success Response: 200 OK

Returns an array of objects, each representing a calendar's result

[
  {
    "calendarId": "primary",
    "events": [
      {
        "id": "73qusdveu121_20260119T110000Z",
        "calendarId": "primary",
        "title": "Weekly Standup",
        "start": "2026-01-19T12:00:00+01:00",
        "startTimezone": "Europe/Rome",
        "end": "2026-01-19T12:30:00+01:00",
        "endTimezone": "Europe/Rome",
        "recurringEventId": "73qusdveu121", 
        "organizer": { 
          "email": "boss@example.com" 
          },
        "attendees": [
          { 
            "email": "me@example.com", 
            "status": "accepted"
          }
        ]
      }
    ]
  },
  {
    "calendarId": "anothercalendar@example.com",
    "events": [
      {
        "id": "73qusdv42dd121_20260319T110000Z",
        "calendarId": "anotherone",
        "title": "Hello World",
        "start": "2026-01-19T12:00:00+01:00",
        "startTimezone": "Europe/Rome",
        "end": "2026-01-19T12:30:00+01:00",
        "endTimezone": "Europe/Rome",
        "recurringEventId": "3qusdv42dd121", 
        "organizer": { 
          "email": "team@example.com"
          },
        "attendees": [
          { 
            "email": "me@example.com", 
            "status": "pending" 
            }
        ]
      }
    ],
  }
]

Batch Get Event Details

Retrieves full details for specific events given a list of IDs.

Primary Use Case: Fetching the "Master" event for a recurring series to obtain the recurrence rule (RRULE), which is usually missing from the expanded instances returned by the List endpoint.

Endpoint: POST /api/v1/calendar/google/events/details

Request Body:

{
  "events": [
    {
      "calendarId": "primary",
      "eventId": "73qusdveu121" 
    }
  ]
}
Parameters: - events (required): An array of objects containing: - calendarId: The ID of the calendar where the event exists. - eventId: The ID of the event to fetch.

Tip: Pass the recurringEventId (e.g., "73qusdveu121") found in the List endpoint response, not the instance ID (e.g., "73qusdveu121_2026..."), if you want to get the recurrence rules.

Success Response: 200 OK

Returns a flat array of the requested events.

[
  {
    "id": "73qusdveu121",
    "calendarId": "primary",
    "title": "Weekly Standup",
    "description": "Full agenda in the doc...",
    "start": "2026-01-19T12:00:00+01:00",
    "startTimezone": "Europe/Rome",
    "end": "2026-01-19T12:30:00+01:00",
    "endTimezone": "Europe/Rome",
    "recurrence": "RRULE:FREQ=WEEKLY;BYDAY=MO", 
    "organizer": {
      "email": "boss@example.com",
      "name": "The Boss"
    },
    "attendees": [
        { 
        "email": "me@example.com", 
        "status": "accepted" 
        }
    ]
  }
]

<!-- ### Get Connection Status Checks if the Google calendar integration is currently enabled for the authenticated user.

Endpoint: GET /api/v1/calendar/google/status

Request Body: None

Success Response: 200 OK

{
  "isCalendarEnabled": true
}

Update Connection Status

Toggles the active state of the calendar integration (soft disable/enable) without deleting the stored tokens.

Endpoint: POST /api/v1/calendar/google/status/update

Request Body:

{
  "enabled": false
}
Parameters: - enabled (required): A bool value that set display user preferences.

Success Response: 200 OK Returns the updated state.

{
  "isCalendarEnabled": false
}
``` -->

### <span style="color: #2196F3;">Disconnect Google Calendar</span>
Disconnects the Google Calendar integration by deleting the stored refresh token, without revoking the token on the provider side.

**Endpoint:** `POST /api/v1/calendar/google/disconnect`

**Request Body:** None

**Success Response:** `200 OK`

---

## <span style="color: #2196F3;">Microsoft Integration (FUTURE)</span>

### <span style="color: #2196F3;">Initiate Outlook Connection (FUTURE)</span>

Generates a Microsoft OAuth authorization URL.

**Endpoint:** `POST /api/v1/calendar/microsoft/connect`

**Request Body:**

```json
{
  "state": "random_string_xyz",
  "codeChallenge": "pkce_challenge_string"
}

Parameters:

  • state (required): A random string generated by the client to prevent CSRF attacks.
  • codeChallenge (required): The PKCE code challenge generated by the client.

Success Response: 200 OK

{
  "redirectUrl": "https://api.workos.com/oauth/authorize?..."
}

Disconnect Calendar (FUTURE)

Revokes the integration with the microsoft calendar provider and deletes the stored tokens. This stops all background synchronization.

Endpoint: POST /api/v1/calendar/microsoft/disconnect

Request Body: None

Success Response: 200 OK