Google Calendar API
Manage calendars and events via Google's Calendar REST API.
Official docs: https://developers.google.com/workspace/calendar/api/v3/reference
When to Use
Use this skill when you need to:
- List and manage calendars
- Create, update, and delete calendar events
- Search and filter events by time range
- Manage event attendees and send invitations
- Set up event reminders
- Check free/busy availability
- Handle recurring events
- Quick-add events using natural language
Prerequisites
Go to vm0.ai Settings → Connectors and connect Google Calendar. vm0 will automatically inject the required GOOGLE_CALENDAR_TOKEN environment variable.
Placeholders: Values in
{curly-braces}like{event-id}are placeholders. Replace them with actual values when executing.
How to Use
Base URL: https://www.googleapis.com/calendar/v3
Calendar List
List All Calendars
Get all calendars the user has access to:
curl -s "https://www.googleapis.com/calendar/v3/users/me/calendarList" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.items[]? | {id, summary, primary, accessRole}'
Get Calendar Details
Get metadata for a specific calendar:
curl -s "https://www.googleapis.com/calendar/v3/calendars/{calendar-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '{id, summary, description, timeZone}'
For primary calendar, use primary as the calendar ID:
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '{id, summary, description, timeZone}'
Events
List Events
List upcoming events from the primary calendar:
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary/events?maxResults=10&orderBy=startTime&singleEvents=true&timeMin=$(date -u +%Y-%m-%dT%H:%M:%SZ)" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.items[]? | {id, summary, start, end}'
List Events with Time Filter
Get events within a specific date range:
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=2024-01-01T00:00:00Z&timeMax=2024-12-31T23:59:59Z&singleEvents=true&orderBy=startTime" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.items[]? | {id, summary, start, end}'
Search Events
Search events by query string:
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary/events?q=meeting&singleEvents=true" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.items[]? | {id, summary, start, end}'
Get Event Details
Get full details for a specific event:
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.'
Create Event
Create a new event. Write to /tmp/calendar_request.json:
{
"summary": "Team Meeting",
"description": "Weekly sync-up meeting",
"location": "Conference Room A",
"start": {
"dateTime": "2024-03-15T10:00:00",
"timeZone": "America/New_York"
},
"end": {
"dateTime": "2024-03-15T11:00:00",
"timeZone": "America/New_York"
},
"attendees": [
{
"email": "colleague@example.com"
}
],
"reminders": {
"useDefault": false,
"overrides": [
{
"method": "email",
"minutes": 30
},
{
"method": "popup",
"minutes": 10
}
]
}
}
Then run:
curl -s -X POST "https://www.googleapis.com/calendar/v3/calendars/primary/events" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, htmlLink}'
Create All-Day Event
Write to /tmp/calendar_request.json:
{
"summary": "Company Holiday",
"start": {
"date": "2024-07-04"
},
"end": {
"date": "2024-07-05"
}
}
Then run:
curl -s -X POST "https://www.googleapis.com/calendar/v3/calendars/primary/events" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, htmlLink}'
Quick Add Event
Create event from natural language text:
curl -s -X POST "https://www.googleapis.com/calendar/v3/calendars/primary/events/quickAdd?text=Lunch%20with%20Sarah%20tomorrow%20at%2012pm" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.error // {id, summary, start, end}'
Update Event
Update an existing event. Write to /tmp/calendar_request.json:
{
"summary": "Updated Team Meeting",
"description": "Updated description",
"start": {
"dateTime": "2024-03-15T14:00:00",
"timeZone": "America/New_York"
},
"end": {
"dateTime": "2024-03-15T15:00:00",
"timeZone": "America/New_York"
}
}
Then run:
curl -s -X PUT "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, updated}'
Patch Event
Partially update an event (only specified fields). Write to /tmp/calendar_request.json:
{
"summary": "Updated Title Only"
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, updated}'
Delete Event
Delete an event:
curl -s -X DELETE "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)"
Send deletion notifications to attendees:
curl -s -X DELETE "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}?sendUpdates=all" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)"
Attendees
Set Attendees on Event
Note: PATCH replaces the entire attendees array — always include all intended attendees in the list, not just the ones you're adding.
Write the full attendees list to /tmp/calendar_request.json:
{
"attendees": [
{
"email": "attendee1@example.com",
"optional": false
},
{
"email": "attendee2@example.com",
"optional": true
}
]
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}?sendUpdates=all" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, attendees}'
Remove Attendee from Event
Patch the event with the updated attendees list (omit the attendee you want to remove). Write to /tmp/calendar_request.json:
{
"attendees": [
{
"email": "remaining@example.com"
}
]
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}?sendUpdates=all" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, attendees}'
Reminders
Set Custom Reminders
Update event with custom reminders. Write to /tmp/calendar_request.json:
{
"reminders": {
"useDefault": false,
"overrides": [
{
"method": "email",
"minutes": 1440
},
{
"method": "popup",
"minutes": 30
}
]
}
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, reminders}'
Use Default Reminders
Write to /tmp/calendar_request.json:
{
"reminders": {
"useDefault": true
}
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, reminders}'
Recurring Events
Create Recurring Event
Create an event with recurrence rule. Write to /tmp/calendar_request.json:
{
"summary": "Weekly Team Standup",
"start": {
"dateTime": "2024-03-15T09:00:00",
"timeZone": "America/New_York"
},
"end": {
"dateTime": "2024-03-15T09:30:00",
"timeZone": "America/New_York"
},
"recurrence": [
"RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=20"
]
}
Then run:
curl -s -X POST "https://www.googleapis.com/calendar/v3/calendars/primary/events" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, recurrence, htmlLink}'
Common recurrence patterns:
- Daily:
RRULE:FREQ=DAILY - Weekly on specific days:
RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR - Monthly on same day:
RRULE:FREQ=MONTHLY;BYMONTHDAY=15 - Until specific date:
RRULE:FREQ=WEEKLY;UNTIL=20241231T235959Z - Limited occurrences:
RRULE:FREQ=DAILY;COUNT=10
List Recurring Event Instances
Get all instances of a recurring event:
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary/events/{recurring-event-id}/instances?timeMin=2024-01-01T00:00:00Z&timeMax=2024-12-31T23:59:59Z" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" | jq '.items[]? | {id, summary, start, end, recurringEventId}'
Free/Busy Information
Query Free/Busy
Check availability for one or more calendars. Write to /tmp/calendar_request.json:
{
"timeMin": "2024-03-15T00:00:00Z",
"timeMax": "2024-03-15T23:59:59Z",
"items": [
{
"id": "primary"
},
{
"id": "colleague@example.com"
}
]
}
Then run:
curl -s -X POST "https://www.googleapis.com/calendar/v3/freeBusy" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // .calendars'
Secondary Calendars
Create Secondary Calendar
Write to /tmp/calendar_request.json:
{
"summary": "Project Alpha Calendar",
"description": "Calendar for Project Alpha events",
"timeZone": "America/New_York"
}
Then run:
curl -s -X POST "https://www.googleapis.com/calendar/v3/calendars" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, description}'
Update Calendar Properties
Write to /tmp/calendar_request.json:
{
"summary": "Updated Calendar Name",
"description": "Updated description"
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/{calendar-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, description}'
Delete Secondary Calendar
curl -s -X DELETE "https://www.googleapis.com/calendar/v3/calendars/{calendar-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)"
Event Colors
Set Event Color
Update event color using colorId (1-11). Write to /tmp/calendar_request.json:
{
"colorId": "5"
}
Then run:
curl -s -X PATCH "https://www.googleapis.com/calendar/v3/calendars/primary/events/{event-id}" --header "Authorization: Bearer $(printenv GOOGLE_CALENDAR_TOKEN)" --header "Content-Type: application/json" -d @/tmp/calendar_request.json | jq '.error // {id, summary, colorId}'
Available color IDs:
- 1: Lavender
- 2: Sage
- 3: Grape
- 4: Flamingo
- 5: Banana
- 6: Tangerine
- 7: Peacock
- 8: Graphite
- 9: Blueberry
- 10: Basil
- 11: Tomato
Common Query Parameters
| Parameter | Type | Purpose |
|---|---|---|
timeMin | datetime | Lower bound for event end time (RFC3339) |
timeMax | datetime | Upper bound for event start time (RFC3339) |
maxResults | integer | Max events per page (default 250, max 2500) |
orderBy | string | Sort by startTime or updated |
singleEvents | boolean | Expand recurring events into instances |
q | string | Free text search query |
sendUpdates | string | Send notifications: all, externalOnly, none |
Guidelines
- Primary Calendar: Use
primaryas the calendar ID for the user's primary calendar - Date Format: Use RFC3339 format for dates (
2024-03-15T10:00:00Zor with timezone2024-03-15T10:00:00-04:00) - All-Day Events: Use
datefield instead ofdateTimefor all-day events - Notifications: Use
sendUpdatesparameter to control whether attendees receive email notifications - Patch vs Update: Use PATCH for partial updates (more efficient), PUT for full replacement. Note: PATCH on
attendeesreplaces the entire array — always include all intended attendees - Time Zones: Always specify time zones explicitly to avoid ambiguity
- Recurring Events: To modify all instances, update the recurring event master; to modify single instance, update the specific instance ID
API Reference
- REST Reference: https://developers.google.com/workspace/calendar/api/v3/reference
- Events Reference: https://developers.google.com/workspace/calendar/api/v3/reference/events
- OAuth Scopes: https://developers.google.com/workspace/calendar/api/auth
- OAuth Playground: https://developers.google.com/oauthplayground/
- Recurrence Rules: https://datatracker.ietf.org/doc/html/rfc5545#section-3.8.5