The Google Calendar connector lets you interact with Google Calendar. It uses OAuth for authentication, so you connect your Google account once and Major handles token management.
For full API details, see the Google Calendar API documentation.
Setup
- Go to Organization Settings > Connectors
- Click Add Connector and select Google Calendar
- Choose the access scope:
- Read only — Can list and read calendar events
- Read and write — Can list, read, and create calendar events
- Choose the authentication mode:
- Shared — Use a single shared account (the person configuring the resource provides credentials)
- Per-user — Each app user connects their own account
- Click Connect to Google to authorize access
- Select the calendar you want to connect (or skip if using per-user auth — users will select their own)
Attach the resource to your app via major resource manage (CLI) or the web editor. Major generates a client in src/clients/.
Per-User Authentication
When you configure a Google Calendar resource for per-user authentication, end-users authenticate with their own Google accounts instead of using shared credentials.
User Flow
- User accesses a deployed app that uses a per-user Google Calendar resource
- If they haven’t connected their account, Major redirects them to the
/connect page
- User clicks Connect Google Calendar and authorizes access to their own calendar
- User is returned to the app and can now use Google Calendar features
Managing Connections
Users can view and manage their connected OAuth accounts by clicking their profile photo in the bottom left and selecting Connected Accounts. From there, they can disconnect individual OAuth credentials or reconnect if access expires.
Once disconnected, users must re-authorize via the /connect page if they want to use apps that require that connection.
Usage
Import the generated client and use the helper methods:
import { googlecalendarClient } from './clients';
Listing calendars
const result = await googlecalendarClient.googlecalendar_list_calendars(
'list-calendars'
);
if (result.ok) {
const calendars = result.result.items;
calendars.forEach(cal => {
console.log(cal.id, cal.summary);
});
}
Parameters:
operationName — A name for logging and debugging
Returns:
items — Array of calendar objects with id, summary, description, and other metadata
Listing events
const result = await googlecalendarClient.googlecalendar_list_events(
'list-events',
{
calendarId: 'primary',
maxResults: 10,
orderBy: 'startTime',
singleEvents: true,
timeMin: '2024-01-01T00:00:00Z',
timeMax: '2024-12-31T23:59:59Z'
}
);
if (result.ok) {
const events = result.result.items;
events.forEach(event => {
console.log(event.summary, event.start.dateTime);
});
}
Parameters:
operationName — A name for logging and debugging
options — Query options:
calendarId — Calendar identifier (default: primary)
maxResults — Maximum events to return (1–250)
orderBy — Sort order: startTime or updated
singleEvents — Expand recurring events into instances (default: false)
timeMin — Lower bound (RFC 3339 format)
timeMax — Upper bound (RFC 3339 format)
q — Search query term
Returns:
items — Array of event objects with id, summary, start, end, and other metadata
Creating events
const result = await googlecalendarClient.googlecalendar_create_event(
'create-event',
{
calendarId: 'primary',
summary: 'Team Meeting',
description: 'Quarterly planning session',
start: {
dateTime: '2024-02-15T14:00:00',
timeZone: 'America/New_York'
},
end: {
dateTime: '2024-02-15T15:00:00',
timeZone: 'America/New_York'
},
attendees: [
{ email: 'alice@example.com' },
{ email: 'bob@example.com' }
]
}
);
if (result.ok) {
console.log('Event created:', result.result.id);
}
Parameters:
operationName — A name for logging and debugging
eventBody — Event object with:
summary — Event title (required)
description — Event description
start — Start time with dateTime and optional timeZone
end — End time with dateTime and optional timeZone
attendees — Array of attendee objects with email
location — Event location
recurrence — Recurrence rules (RFC 5545 format)
Returns:
id — The created event’s ID
htmlLink — Link to the event in Google Calendar
- Full event object with all details
Low-level API
For operations not covered by helper methods, use invoke() directly:
const result = await googlecalendarClient.googlecalendar_invoke(
'GET',
'/calendars/primary/events',
'list-events',
{
query: { maxResults: 10 }
}
);
Supported API paths
| Method | Path | Description |
|---|
| GET | /users/me/calendarList | List calendars |
| GET | /calendars/{calendarId}/events | List events |
| POST | /calendars/{calendarId}/events | Create event |
| GET | /calendars/{calendarId}/events/{eventId} | Get event details |
| PUT | /calendars/{calendarId}/events/{eventId} | Update event |
| DELETE | /calendars/{calendarId}/events/{eventId} | Delete event |
The calendar ID is configured in the resource and does not need to be included in all API paths, though you can specify a different calendar by passing calendarId in options or the URL.
Error handling
import { ResourceInvokeError } from '@major-tech/resource-client';
try {
const result = await googlecalendarClient.googlecalendar_list_events(
'list-events',
{ calendarId: 'primary' }
);
if (!result.ok) {
// Resource returned an error (e.g., calendar not found)
console.error('Calendar error:', result.error.message);
return;
}
// Success
console.log(result.result.items);
} catch (e) {
if (e instanceof ResourceInvokeError) {
// Client-level error (e.g., OAuth not completed)
console.error('Invocation error:', e.message);
}
}
Common errors
| Error | Cause |
|---|
| 401 Unauthorized | OAuth not completed—reconnect the resource |
| 403 Forbidden | Write operation on a read-only resource |
| 404 Not Found | Calendar or event not found |
| 400 Bad Request | Invalid event data or query parameters |
Scope and permissions
When creating the resource, you choose between:
- Read only —
GET requests only
- Read and write — Full read/write access including event creation and deletion
The scope is enforced at the API level. If you try to create an event with a read-only resource, you’ll get a 403 error.
Major uses the most restrictive Google OAuth scope, which only grants access to the specific calendar you selected—not your entire Google Calendar.