Google Calendar stores repeating meetings as a parent event plus generated instances. The parent carries the recurrence rule, while moved or cancelled occurrences become exceptions. That model is powerful, but the native Google Calendar API exposes several concepts you have to stitch together: recurrence, recurringEventId, originalStartTime, cancelled instances, and expanded date windows.
Nylas keeps the same calendar semantics but gives you one Events API shape across Google, Microsoft, iCloud, and Exchange. This recipe shows the Google behavior you need to understand, then maps it to the Nylas request pattern.
Create a recurring Google Calendar event
Section titled “Create a recurring Google Calendar event”Create a recurring event by sending a Create Event request with a recurrence array. The array usually has one recurrence rule string. The when object sets the first occurrence and the time zone that anchors the whole series.
curl --request POST \ --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/events?calendar_id=primary' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "title": "Weekly product review", "busy": true, "when": { "start_time": 1782918000, "end_time": 1782921600, "start_timezone": "America/New_York", "end_timezone": "America/New_York" }, "participants": [ { "email": "[email protected]", "name": "Maya Patel" } ], "recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=12"] }'const event = await nylas.events.create({ identifier: grantId, queryParams: { calendarId: "primary" }, requestBody: { title: "Weekly product review", busy: true, when: { startTime: 1782918000, endTime: 1782921600, startTimezone: "America/New_York", endTimezone: "America/New_York", }, recurrence: ["RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=12"], },});event = nylas.events.create( identifier=grant_id, query_params={"calendar_id": "primary"}, request_body={ "title": "Weekly product review", "busy": True, "when": { "start_time": 1782918000, "end_time": 1782921600, "start_timezone": "America/New_York", "end_timezone": "America/New_York", }, "recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=12"], },)Use calendar_id=primary for the connected user’s default Google Calendar, or pass a specific calendar ID from the List Calendars endpoint.
Write the recurrence rule
Section titled “Write the recurrence rule”Google Calendar follows the recurrence rule format used by major calendar providers. Nylas passes the recurrence string through the unified Events API, so the same rule works on other providers when they support the pattern.
| Schedule | Recurrence rule |
|---|---|
| Every Tuesday | RRULE:FREQ=WEEKLY;BYDAY=TU |
| Every weekday | RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR |
| Every other week on Tuesday | RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU |
| First Monday of each month | RRULE:FREQ=MONTHLY;BYDAY=1MO |
| Stop after 12 meetings | RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=12 |
| Stop on a date | RRULE:FREQ=WEEKLY;BYDAY=TU;UNTIL=20261231T235959Z |
To skip one occurrence when you create the series, include an EXDATE entry in the same array:
{ "recurrence": [ "RRULE:FREQ=WEEKLY;BYDAY=TU;COUNT=12", "EXDATE:20260707T150000Z" ]}For the full recurrence reference, including provider differences, see Recurring events and recurrence rules.
List recurring Google Calendar instances
Section titled “List recurring Google Calendar instances”When you list events without a date range, Google returns the parent recurring event and its recurrence rule. When you pass start and end, Nylas expands the series into the instances inside that window.
curl --request GET \ --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/events?calendar_id=primary&start=1782892800&end=1785571200' \ --header 'Authorization: Bearer <NYLAS_API_KEY>'Expanded instances share a master_event_id that points back to the parent series. Store both IDs in your app. The instance id lets you move or cancel one meeting, while the parent id lets you edit the whole series.
Update one instance or the whole series
Section titled “Update one instance or the whole series”To update one Google Calendar occurrence, send an Update Event request using the occurrence ID from the expanded list. Nylas updates only that instance, and the response includes original_start_time so you can tell which generated occurrence changed.
curl --request PUT \ --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/events/<INSTANCE_EVENT_ID>?calendar_id=primary' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "when": { "start_time": 1783008000, "end_time": 1783011600, "start_timezone": "America/New_York", "end_timezone": "America/New_York" } }'To update every future instance, update the parent series instead. Google keeps existing overrides that still fit the new rule. Microsoft can remove overrides when a recurrence pattern changes. If you support more than Google, test against the stricter Microsoft behavior before exposing broad recurrence editing in your UI.
Cancel one occurrence
Section titled “Cancel one occurrence”Delete one expanded instance to cancel that date:
curl --request DELETE \ --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/events/<INSTANCE_EVENT_ID>?calendar_id=primary' \ --header 'Authorization: Bearer <NYLAS_API_KEY>'Google often represents a deleted occurrence as a cancelled event instead of only adding an EXDATE to the parent. Treat cancelled instances as tombstones in your sync table, not as events to show on the calendar.
Things to know about Google recurrence
Section titled “Things to know about Google recurrence”Always pass a time zone. Without start_timezone and end_timezone, the series falls back to Coordinated Universal Time. A weekly 9:00 AM meeting can appear to drift around daylight saving time if you omit the time zone.
Bound every list request. Open-ended recurrence can generate years of instances. Pass start and end when you need expanded occurrences, and keep the window close to what your UI or sync job needs.
Invites can fan out. Updating a parent event sends participant updates for the whole series. Use instance-level updates when only one meeting changed.
Use webhooks for follow-up sync. Subscribe to event.created, event.updated, and event.deleted so moved or cancelled Google occurrences reach your app without polling. See Google Calendar webhooks.
What’s next
Section titled “What’s next”- Create Google calendar events for single events, participants, Google Meet, and write scopes
- Recurring events and recurrence rules for the full recurrence behavior
- Google Calendar API pagination and sync for
nextPageToken, sync windows, and incremental sync concepts - Sync calendar events with webhooks for the unified webhook setup