FabricFabricSDK
Plugins

Google Calendar

Manage calendars and events with Google Calendar API.

Authentication

TypeDefaultDetails
oauth_2Google OAuth 2.0 with offline access

Scopes:

  • https://www.googleapis.com/auth/calendar.readonly
  • https://www.googleapis.com/auth/calendar.events

Uses access_type: "offline" and prompt: "consent" for refresh tokens.

Endpoints

PathRiskDescription
calendars.listreadList the user's accessible calendars.
calendars.getreadGet a calendar by id.
events.listreadList events on a calendar (use syncToken for deltas).
events.getreadGet an event by id.
events.insertwriteCreate an event.
events.updatewritePatch an existing event.
events.deletedestructiveDelete an event.
freebusy.queryreadQuery free/busy intervals for one or more calendars.

calendars.list

List calendars accessible to the user.

Input:

FieldTypeDescription
maxResultsnumberMax results per page
pageTokenstringPagination token

Output: { items?: GoogleCalendar[]; nextPageToken?: string }

calendars.get

Get a calendar's metadata.

Input:

FieldTypeRequiredDescription
calendarIdstringCalendar ID (primary or UUID)

Output: GoogleCalendar

events.list

List events on a calendar.

Input:

FieldTypeDescription
calendarIdstring✅ Calendar ID
timeMinstringISO datetime lower bound
timeMaxstringISO datetime upper bound
singleEventsbooleanExpand recurring events
orderByenumstartTime or updated
pageTokenstringPagination token
maxResultsnumberMax results
syncTokenstringDelta sync token

Output: { items?: GoogleCalendarEvent[]; nextPageToken?: string; nextSyncToken?: string }

events.get

Get a single event.

Input:

FieldTypeRequiredDescription
calendarIdstringCalendar ID
eventIdstringEvent ID

Output: GoogleCalendarEvent

events.insert

Create a new event.

Input:

FieldTypeRequiredDescription
calendarIdstringCalendar ID
summarystringEvent title
descriptionstringEvent description
startobject{ date?: string; dateTime?: string; timeZone?: string }
endobjectSame shape as start
attendeesarrayArray of { email: string }
sendUpdatesenumall, externalOnly, none

Output: GoogleCalendarEvent

events.update

Update an existing event.

Input: Same as events.insert plus:

FieldTypeRequiredDescription
eventIdstringEvent ID

Output: GoogleCalendarEvent

events.delete

Delete an event.

Input:

FieldTypeRequiredDescription
calendarIdstringCalendar ID
eventIdstringEvent ID
sendUpdatesenumall, externalOnly, none

Output: { ok: boolean }

freebusy.query

Query free/busy intervals.

Input:

FieldTypeRequiredDescription
timeMinstringISO datetime start
timeMaxstringISO datetime end
itemsarrayArray of { id: string } (calendar IDs)
timeZonestringTime zone ID

Output: { calendars: Record<string, { busy: Array<{ start: string; end: string }>; errors?: unknown }> }

Usage

import { createFabric } from "@fabricorg/integrations";
import { googleCalendar } from "@fabricorg/integrations/plugins";

const fabric = createFabric({
  plugins: [googleCalendar({ accessToken: process.env.GOOGLE_ACCESS_TOKEN })],
});

// Create an event
const event = await fabric.googleCalendar.api.events.insert({
  calendarId: "primary",
  summary: "Team Standup",
  start: { dateTime: "2026-05-14T10:00:00-07:00" },
  end: { dateTime: "2026-05-14T10:30:00-07:00" },
  attendees: [{ email: "alice@example.com" }],
  sendUpdates: "all",
});

// Check availability
const busy = await fabric.googleCalendar.api.freebusy.query({
  timeMin: "2026-05-14T09:00:00-07:00",
  timeMax: "2026-05-14T17:00:00-07:00",
  items: [{ id: "primary" }, { id: "room@example.com" }],
});

Webhooks

Google Calendar uses Pub/Sub push channels for change notifications rather than direct webhooks. The portal's Pub/Sub bridge invokes events.list with syncToken after each push to fetch deltas.

Types

interface GoogleCalendar {
  id: string;
  summary: string;
  timeZone?: string;
  primary?: boolean;
  accessRole?: "owner" | "reader" | "writer" | "freeBusyReader";
}

interface GoogleCalendarEvent {
  id: string;
  status?: "confirmed" | "tentative" | "cancelled";
  summary?: string;
  description?: string;
  start: { date?: string; dateTime?: string; timeZone?: string };
  end: { date?: string; dateTime?: string; timeZone?: string };
  attendees?: Array<{
    email: string;
    displayName?: string;
    responseStatus?: "needsAction" | "declined" | "tentative" | "accepted";
    organizer?: boolean;
  }>;
  hangoutLink?: string;
  htmlLink?: string;
}