Events: list (every filter) and list-all, get, create, full update, patch, delete, quick add from text, move to another calendar, recurring-event instances, and pure builders for event bodies and Google Meet links.

Write options (create, update, patch, delete, quick-add, move): sendUpdates (all, externalOnly, none; who gets email about the change, none when unset), and for create/update/patch conferenceDataVersion (set to 1 automatically when the body has conferenceData, which creating a Meet link needs), supportsAttachments (set automatically when the body has attachments), maxAttendees.

Scopes. Reads use calendar.events.readonly, writes calendar.events; calendar and calendar.readonly also work, and calendar.events.owned covers calendars the user owns.

Values

BUILD_KEYS

BUILD_KEYS: Vec [
  "start",
  "end",
  "time-zone",
  "attendees",
  "meet",
  "meet-request-id",
  "reminders-minutes"
]

DATE_PATTERN

DATE_PATTERN: Str "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"

MAX_PAGE_SIZE

MAX_PAGE_SIZE: Int 2500

SEND_UPDATES

SEND_UPDATES: Vec [
  "all",
  "externalOnly",
  "none"
]

Functions

attendee

fn (value: Any): Map

An attendee from an email Str or a Map ({email, displayName?, optional?, responseStatus?}) (pure).

build-event

fn (fields: Map): Map

An event body from friendlier fields (pure). Shorthands:

  • start, end - Str (date or RFC 3339) or EventDateTime Map; see event-time. time-zone (IANA) is applied to both.
  • attendees - emails or attendee Maps (a single Str is one email)
  • meet: true - request a Google Meet link (meet-request-id to set its request id)
  • reminders-minutes - popup reminders, e.g. [10, 60], instead of the calendar's defaults

Every other field is passed through as the API's own (summary, description, location, recurrence like ["RRULE:FREQ=WEEKLY;COUNT=10"], visibility, transparency, colorId, guestsCanModify, extendedProperties, ...). Null fields are dropped.

::google::calendar::events/build-event({
  summary: "Standup",
  start: "2026-11-02T09:00:00",
  end: "2026-11-02T09:15:00",
  time-zone: "America/Chicago",
  recurrence: ["RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"],
  attendees: ["ada@example.com", {email: "bob@example.com", optional: true}],
  meet: true,
  reminders-minutes: [5]
})

create-event

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

POST /calendars/{id}/events - create an event from an Event body (build-event makes one): summary, start/end, attendees, conferenceData, recurrence, reminders, ... Null fields are dropped. Returns the event (with id, htmlLink, and hangoutLink for Meet). Attendees are not emailed unless sendUpdates: "all". Scope: calendar.events.

::google::calendar::events/create-event("primary", ::google::calendar::events/with-meet({
  summary: "Kickoff",
  start: {dateTime: "2026-11-05T10:00:00-05:00"},
  end: {dateTime: "2026-11-05T10:45:00-05:00"},
  attendees: [{email: "ada@example.com"}]
}), {sendUpdates: "all"})

delete-event

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

DELETE /calendars/{id}/events/{eventId} - cancel and remove an event (deleting one instance of a recurring event cancels just that occurrence). Options: sendUpdates. Returns true. Scope: calendar.events.

event-time

fn (value: Any): Map
fn (value: Any, time-zone: Str?): Map

An EventDateTime from a Str (pure): a YYYY-MM-DD date gives {date} (all day); anything else is an RFC 3339 {dateTime}, with timeZone when time-zone is given. A Map passes through.

::google::calendar::events/event-time("2026-11-03")                                   // {date: "2026-11-03"}
::google::calendar::events/event-time("2026-11-03T09:00:00-06:00", "America/Chicago")  // {dateTime, timeZone}

get-event

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

GET /calendars/{id}/events/{eventId} - one event. Options: timeZone, maxAttendees, alwaysIncludeEmail. Scope: calendar.events.readonly.

list-all-events

fn (calendar-id: Str, opts: Map): Vec
fn (calendar-id: Str, opts: Map, limit: Int?): Vec

Follow nextPageToken and return every matching event, or at most limit. Same options as list-events; uses maxResults: 2500 (or limit when smaller) unless set. Scope: calendar.events.readonly.

today ::google::calendar::events/list-all-events("primary", {
  timeMin: "2026-11-03T00:00:00-06:00", timeMax: "2026-11-04T00:00:00-06:00",
  singleEvents: true, orderBy: "startTime"
})

list-all-instances

fn (calendar-id: Str, event-id: Str, opts: Map): Vec
fn (calendar-id: Str, event-id: Str, opts: Map, limit: Int?): Vec

Every occurrence of a recurring event (all pages), or at most limit; bound it with timeMin/timeMax for endless series. Scope: calendar.events.readonly.

list-events

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

GET /calendars/{id}/events - one page of events: {items, nextPageToken?, nextSyncToken?, timeZone, updated, ...}.

Options (all of the API's): timeMin, timeMax (RFC 3339 with an offset), q (text search), singleEvents (expand recurring events into instances; required for orderBy: "startTime"), orderBy (startTime, updated), maxResults (default 250, max 2500), pageToken, showDeleted, showHiddenInvitations, updatedMin, iCalUID, eventTypes (a Vec, e.g. ["default", "outOfOffice"]), privateExtendedProperty / sharedExtendedProperty ("key=value", Vec for several), timeZone, maxAttendees, alwaysIncludeEmail, syncToken (see ::google::calendar::sync). Scope: calendar.events.readonly.

list-instances

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

GET /calendars/{id}/events/{eventId}/instances - one page of a recurring event's occurrences. Options: timeMin, timeMax, originalStart, showDeleted, maxResults, pageToken, timeZone, maxAttendees. Scope: calendar.events.readonly.

fn (event: Map): Str?

The Google Meet URL of an event: hangoutLink, else the first video entry point; null when there is none (or the conference is still pending).

meet-request

fn (): Map
fn (request-id: Str): Map

conferenceData asking Google to create a Google Meet link (pure): {createRequest: {requestId, conferenceSolutionKey: {type: "hangoutsMeet"}}}. request-id makes retries idempotent (default a new UUID). Needs conferenceDataVersion=1, which create-event, update-event and patch-event add when they see conferenceData. The link appears as hangoutLink once the request succeeds.

move-event

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

POST /calendars/{id}/events/{eventId}/move - move an event to the calendar destination (changes its organizer; only default events can move). Options: sendUpdates. Scope: calendar.events.

notify-params

fn (opts: Map): Map

The query parameters of a delete, quick-add or move (pure): your options, with sendUpdates checked.

patch-event

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

PATCH /calendars/{id}/events/{eventId} - change only the given fields (a Vec such as attendees is replaced whole). Scope: calendar.events.

quick-add

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

POST /calendars/{id}/events/quickAdd - create an event from text, e.g. "Lunch with Sam tomorrow at noon" (parsed in the calendar's time zone; English works best). Options: sendUpdates. Scope: calendar.events.

update-event

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

PUT /calendars/{id}/events/{eventId} - replace an event: fields you leave out are cleared, so start from get-event. Prefer patch-event to change a few fields. Scope: calendar.events.

with-meet

fn (event: Map): Map
fn (event: Map, request-id: Str): Map

An event body with a Meet conferenceData request added (pure).

write

fn (method: Str, path: Str, event: Map, opts: Map): Map

write-params

fn (event: Map, opts: Map): Map

The query parameters a create/update/patch sends for event (pure): conferenceDataVersion: 1 when the body has conferenceData, supportsAttachments: true when it has attachments, then your options (sendUpdates, conferenceDataVersion, supportsAttachments, maxAttendees, ...). Unset options are omitted. An unknown sendUpdates value is an Err.