Calendars: the user's calendar list (the calendars they see, with their colors and access roles), calendar metadata, creating secondary calendars, the color palette, and free/busy queries.

Scopes. Reads use calendar.readonly; create-calendar uses calendar; query-free-busy uses calendar.freebusy (calendar.readonly works too).

Functions

build-calendar

fn (summary: Str, opts: Map): Map

The calendars.insert body (pure): {summary} plus timeZone (IANA), description and location from opts when set.

build-free-busy

fn (time-min: Str, time-max: Str, calendar-ids: Vec, opts: Map): Map

The freeBusy body (pure): {timeMin, timeMax, items: [{id}]} plus timeZone, groupExpansionMax and calendarExpansionMax from opts when set. calendar-ids may name users' primary calendars by email, or groups.

busy-periods

fn (response: Map, calendar-id: Str): Vec

The busy periods ([{start, end}]) for one calendar in a query-free-busy response (pure), or an Err carrying Google's error reasons when that calendar could not be read.

create-calendar

fn (summary: Str): Map
fn (summary: Str, opts: Map): Map

POST /calendars - create a secondary calendar owned by the user. Options: timeZone, description, location. Returns the calendar with its new id. Scope: calendar.

get-calendar

fn (calendar-id: Str): Map
fn (calendar-id: Str, opts: Map): Map

GET /calendars/{calendarId} - calendar metadata: id, summary, description, timeZone, location. "primary" is the user's main calendar. Scope: calendar.readonly.

get-calendar-list-entry

fn (calendar-id: Str): Map
fn (calendar-id: Str, opts: Map): Map

GET /users/me/calendarList/{calendarId} - the user's entry for one calendar (summary, color, accessRole, notification settings). Scope: calendar.readonly.

get-colors

fn (): Map
fn (opts: Map): Map

GET /colors - the color palette: {calendar: {id: {background, foreground}}, event: {...}}. Use the ids as colorId on events and calendar-list entries. Scope: calendar.readonly.

list-all-calendars

fn (): Vec
fn (opts: Map): Vec

Every calendar on the user's list (all pages). Same options as list-calendars. Scope: calendar.readonly.

list-calendars

fn (): Map
fn (opts: Map): Map

GET /users/me/calendarList - one page of the user's calendars: {items: [{id, summary, timeZone, accessRole, primary?, ...}], nextPageToken?, nextSyncToken?}. Options: minAccessRole (freeBusyReader, reader, writer, owner), showHidden, showDeleted, maxResults (max 250), pageToken, syncToken. Scope: calendar.readonly.

query-free-busy

fn (time-min: Str, time-max: Str, calendar-ids: Vec): Map
fn (time-min: Str, time-max: Str, calendar-ids: Vec, opts: Map): Map

POST /freeBusy - busy periods for calendars between time-min and time-max (RFC 3339). Returns {calendars: {id: {busy: [{start, end}], errors?}}, groups?, timeMin, timeMax}; a calendar you cannot see has errors instead of busy. Scope: calendar.freebusy.

fb ::google::calendar::calendars/query-free-busy("2026-11-03T13:00:00Z", "2026-11-03T22:00:00Z", ["ada@example.com", "bob@example.com"])
::google::calendar::calendars/busy-periods(fb, "ada@example.com")