Google Calendar
Overview
This skill provides instructions for correctly working with Google Calendar operations using the Google Calendar v3 API. The base URL is https://www.googleapis.com/calendar/v3 and authentication uses OAuth 2.0 via the google_calendar connection, passing tokens in the Bearer PLACEHOLDER_TOKEN header.
Restrictions
Timezone Handling
Do NOT use new Date(), Date.now(), or .toISOString() directly when searching, creating, deleting, or updating events. The time returned by these methods will not be in the user's timezone and will cause incorrect behavior.
Instead:
- Fetch the user's timezone first using:
https://www.googleapis.com/calendar/v3/users/me/settings/timezone - Use the retrieved timezone for all datetime operations (searching, creating, updating, or deleting events)
- Only override the fetched timezone if the user explicitly provides a timezone or preference for a specific timezone to be used
Example of fetching user timezone:
const timezoneResponse = await fetch(
"https://www.googleapis.com/calendar/v3/users/me/settings/timezone",
{
headers: { Authorization: "Bearer GOOGLE_CALENDAR_TOKEN" },
}
);
const { value: userTimezone } = await timezoneResponse.json(); // e.g., "America/Los_Angeles"RFC3339 Timestamp Format Requirements
Critical: All datetime parameters MUST include a timezone offset (e.g., -08:00) or Z for UTC, otherwise Google Calendar will reject with 400 Bad Request.
Event Structure
Events use JSON with the following key fields:
id: Unique event identifiersummary: Event titledescription: Event detailsstartandend: Each containsdateTimeandtimeZonefor specific times, ordatefor all-day eventsattendees: Array of attendees withemailandresponseStatusfieldslocation: String for event locationconferenceData: Object for video calls (e.g., Google Meet)reminders: Configuration for event remindersattachments: Array for Google Drive file attachments
All-day events use just the date field with format "YYYY-MM-DD" (no time component).
Recurring Events
Create recurring events by adding a recurrence array with RRULE syntax like ["RRULE:FREQ=WEEKLY;COUNT=10"]. Common patterns include FREQ=DAILY for daily, FREQ=WEEKLY;BYDAY=MO,WE,FR for specific weekdays, FREQ=MONTHLY;BYMONTHDAY=15 for monthly on specific day, COUNT=10 to limit occurrences, and UNTIL=20241231T235959Z for end date.
Attendees and Invitations
Add attendees by including an attendees array in the event with objects containing email addresses. Send invitations by adding sendUpdates=all as a query parameter. Track responses through the responseStatus field which can be needsAction, accepted, declined, or tentative.
Google Meet Integration
Add video conferencing by including conferenceData with createRequest containing a unique requestId and conferenceSolutionKey type "hangoutsMeet", and include conferenceDataVersion=1 as a query parameter.
Operations
Creating Calendar Events
- Before creating an event, determine which calendar to use:
- If no calendar is specified by the user, use
'primary'as the calendar ID (the user's default calendar). - Use the calendar ID in the endpoint:
https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events
- If no calendar is specified by the user, use
- When creating events with specific dates and times stated by the user, construct datetime values in ISO 8601 format using the user's timezone fetched from the timezone endpoint (e.g.,
2025-11-12T20:00:00-08:00). - Always include the timezone offset in the datetime string to ensure correct interpretation.
Searching for Events (for Update/Delete Operations)
- When searching for events within specific time ranges stated by the user, construct datetime values for
timeMinandtimeMaxparameters using the user's timezone fetched from the timezone endpoint. - Use RFC3339 timestamp format with timezone offset (e.g.,
2025-11-12T00:00:00-08:00). - This ensures events are correctly identified before update or delete operations.
- Use
singleEvents=truewhen querying to expand recurring events into individual occurrences.
Checking Availability (Free/Busy Status)
- For details on querying free/busy status, see the reference documentation:
Free/Busy Status Reference
- Use the free/busy query to check availability before scheduling meetings, detect conflicts, or find available time slots
- The free/busy API returns busy time periods without exposing event details, respecting calendar privacy
- Supports checking multiple calendars simultaneously for comprehensive availability information
- Use this for requests like "check if I'm free tomorrow at 2pm", "find when both calendars are available", or "is there a conflict with this meeting time"
Workflows