Google Calendar API Reference
Authentication
All requests use OAuth Bearer token: Authorization: Bearer PLACEHOLDER_TOKEN. Pipedream handles token refresh.
Base URL: https://www.googleapis.com/calendar/v3/
Core Methods
calendars.get
Get calendar metadata including timezone.
GET /calendars/primaryResponse:
{
"id": "user@example.com",
"summary": "user@example.com",
"timeZone": "America/New_York"
}calendarList.list
List calendars the user has access to.
GET /users/me/calendarListReturns items[] with calendar metadata. Primary calendar has primary: true.
events.list
Fetch events from a calendar.
GET /calendars/primary/events?timeMin=2024-01-01T00:00:00Z&timeMax=2024-04-01T00:00:00Z&singleEvents=true&orderBy=startTimeKey parameters:
timeMin,timeMax— ISO8601 datetime bounds (required for bounded queries)singleEvents=true— Expand recurring events into instancesorderBy=startTime— Sort by start (requires singleEvents=true)maxResults— Max events per page (default 250, max 2500)pageToken— For pagination
Response includes items[] with event data and nextPageToken for pagination.
events.get
Get a single event by ID.
GET /calendars/primary/events/{eventId}Event Object Structure
{
"id": "abc123",
"status": "confirmed",
"summary": "Team Standup",
"description": "Daily sync",
"location": "Conference Room A",
"start": {
"dateTime": "2024-03-15T09:00:00-05:00",
"timeZone": "America/New_York"
},
"end": {
"dateTime": "2024-03-15T09:30:00-05:00",
"timeZone": "America/New_York"
},
"attendees": [
{
"email": "user@example.com",
"displayName": "User Name",
"responseStatus": "accepted",
"self": true
},
{
"email": "other@example.com",
"responseStatus": "needsAction"
}
],
"organizer": {
"email": "organizer@example.com",
"displayName": "Organizer Name",
"self": false
},
"conferenceData": {
"entryPoints": [
{
"entryPointType": "video",
"uri": "https://meet.google.com/abc-defg-hij"
}
]
},
"recurringEventId": "originalEventId",
"created": "2024-03-01T10:00:00.000Z",
"updated": "2024-03-14T15:30:00.000Z"
}All-Day Events
All-day events use date instead of dateTime:
{
"start": { "date": "2024-03-15" },
"end": { "date": "2024-03-16" }
}Note: End date is exclusive (March 15 all-day ends on March 16).
Response Status Values
needsAction— Not yet respondeddeclined— Declinedtentative— Maybeaccepted— Accepted
Event Status Values
confirmed— Normal eventtentative— Tentative eventcancelled— Deleted (only returned with showDeleted=true)
Recurring Events
When singleEvents=false (default), recurring events return once with recurrence array.
When singleEvents=true, each instance is returned separately with recurringEventId pointing to the parent.
Rate Limits
Google Calendar API uses per-user quotas:
- 1,000,000 queries per day
- Read operations: ~100 requests/100 seconds per user
In practice, pagination handles most use cases without hitting limits.
Common Errors
| Error | Meaning |
|---|---|
| 401 Unauthorized | Token expired or invalid |
| 403 Forbidden | Calendar not accessible |
| 404 Not Found | Event or calendar doesn't exist |
| 410 Gone | Event was deleted |
| 429 Too Many Requests | Rate limited, retry with backoff |
Useful Patterns
Get Events for Today (user's timezone)
const tz = userTimezone; // e.g., "America/New_York"
const today = new Date().toLocaleDateString('en-CA', { timeZone: tz }); // YYYY-MM-DD
const tomorrow = new Date(Date.now() + 86400000).toLocaleDateString('en-CA', { timeZone: tz });
const params = new URLSearchParams({
timeMin: `${today}T00:00:00`,
timeMax: `${tomorrow}T00:00:00`,
timeZone: tz,
singleEvents: 'true',
orderBy: 'startTime',
});Identify Meeting Type
const hasAttendees = (event.attendees?.length || 0) > 1;
const isAllDay = !event.start?.dateTime;
const hasVideo = !!event.conferenceData || !!event.hangoutLink;
const duration = /* calculate from start/end */;
const isMeeting = hasAttendees && !isAllDay && duration >= 15;