Calendar API compatibility
Reference for the Google Calendar API v3 methods, parameters, and event fields supported by Calendarpit, and what returns an explicit error.
Calendar API
Calendarpit serves the endpoints below. Access follows these rules:
- Every supported
/calendar/v3endpoint requires a Calendarpit bearer token. See Local OAuth for scopes. - Access is limited to calendars owned by the authorized test user.
primaryresolves to that user's primary calendar.- Unknown or unowned calendar IDs return
404(notFound). - Exception:
freebusy.queryreturns200and reports a per-calendarnotFounderror inside the response.
All paths in this table are relative to /calendar/v3.
| Method | Path | Behavior |
|---|---|---|
| GET | /users/me/calendarList | List owned calendars |
| POST | /users/me/calendarList | Restore an owned calendar to the list |
| GET, PUT, PATCH, DELETE | /users/me/calendarList/{calendarId} | Read, replace, patch, or remove a list entry |
| POST | /users/me/calendarList/watch | Subscribe to calendar-list changes |
| GET | /calendars/{calendarId} | Calendar metadata (id, summary, timeZone) |
| GET, POST | /calendars/{calendarId}/events | List or create events |
| GET, PUT, PATCH, DELETE | /calendars/{calendarId}/events/{eventId} | Read, replace, patch, or delete an event |
| GET | /calendars/{calendarId}/events/{eventId}/instances | Recurring instances and exceptions |
| POST | /freeBusy | Merged, clipped busy ranges, up to 50 calendars |
| POST | /calendars/{calendarId}/events/watch | Subscribe to event changes |
| POST | /channels/stop | Stop an event or calendar-list watch channel |
The calendarList.list query parameters are listed under Lists and paging below.
Method coverage
Unsupported methods return an explicit error:
| Request | Response |
|---|---|
| Unrouted endpoint | 501 (unsupportedFeature) |
calendars.update, calendars.patch, calendars.delete | Token, scope, and ownership checks first (401, 403, or 404), then 501 |
events.import | 404 (notFound) |
events.quickAdd with text | 400 (unsupportedFeature) |
events.quickAdd without text | 404 |
| Unsupported HTTP method on the events collection or an existing event | 405 (methodNotAllowed) |
events.import and events.quickAdd share the /events/{eventId} path. That is why they return these codes.
| Resource | Method | Supported | Notes |
|---|---|---|---|
| Acl | delete | ❌ | ACLs and shared-calendar access are not simulated |
| Acl | get | ❌ | |
| Acl | insert | ❌ | |
| Acl | list | ❌ | |
| Acl | patch | ❌ | |
| Acl | update | ❌ | |
| Acl | watch | ❌ | Event and calendar-list watches do not cover ACLs |
| CalendarList | list | ✅ | Owned calendars; minAccessRole, showDeleted, showHidden |
| CalendarList | delete | ✅ | Removes a non-primary calendar from the list only |
| CalendarList | get | ✅ | Same entry list returns for that calendar |
| CalendarList | insert | ✅ | Restores an owned calendar removed from the list |
| CalendarList | patch | ✅ | Preserves omitted writable fields |
| CalendarList | update | ✅ | PUT replaces writable fields |
| CalendarList | watch | ✅ | Caller's list changes; loopback callbacks by default |
| Calendars | get | ✅ | Metadata of a calendar the test user owns |
| Calendars | clear | ❌ | Delete the events, or reset to the startup fixture |
| Calendars | delete | ❌ | Use the admin UI or the management API |
| Calendars | insert | ❌ | |
| Calendars | patch | ❌ | |
| Calendars | transferOwnership | ❌ | One owner per calendar, with no sharing model |
| Calendars | update | ❌ | |
| Channels | stop | ✅ | Stops an event or calendar-list watch channel |
| Colors | get | ❌ | Event colors 1–11 and calendar colors 1–24 need no endpoint |
| Events | list | ✅ | Time bounds, paging, singleEvents, sync tokens, filters |
| Events | get | ✅ | Includes cancelled tombstones and recurring instance IDs |
| Events | insert | ✅ | Returns 200 with the stored event |
| Events | update | ✅ | PUT replaces writable fields |
| Events | patch | ✅ | Preserves omitted fields |
| Events | delete | ✅ | Keeps a cancelled record for synchronization |
| Events | instances | ✅ | Recurring instances, exceptions, and originalStart |
| Events | watch | ✅ | Loopback callbacks by default; retries and a delivery log |
| Events | import | ❌ | Create the event with insert |
| Events | move | ❌ | Delete and insert across calendars instead |
| Events | quickAdd | ❌ | No natural-language parsing |
| Freebusy | query | ✅ | Merged, clipped busy ranges, up to 50 calendars |
| Settings | get | ❌ | No per-user Google settings |
| Settings | list | ❌ | |
| Settings | watch | ❌ |
Events
Supported fields
id: matches[a-zA-Z0-9@._-]{1,128}.primaryis not allowed. Duplicate IDs return409(duplicate).summary,description, andlocationstartandendtransparency:opaqueortransparentstatus:confirmed,tentative, orcancelledvisibility:default,public,private, orconfidentialcolorId:"1"–"11"attendeesandattendeesOmittedguestsCanModify,guestsCanInviteOthers, andguestsCanSeeOtherGuestsremindersandrecurrenceconferenceData: requiresconferenceDataVersion=1hangoutLinkextendedProperties.privateandextendedProperties.shared: string maps
Write endpoints also accept:
sendUpdates:all,externalOnly, ornoneconferenceDataVersion:0or1
Server-managed fields
- Responses include
organizer,creator,iCalUID,sequence,created,updated, and a quotedetag. - Write requests also accept
kind,etag,created,updated,calendarId, andsequence. This lets you send a fetched event back unchanged. - In write requests,
calendarIdis the resolved calendar ID, notprimary. organizer,creator,iCalUID,recurringEventId, andoriginalStartTimeare read-only. Updates accept unchanged values.- On
events.insert, omit these read-only fields. Calendarpit sets them. sequenceincrements on each update.If-Matchis checked onGET,PUT,PATCH, andDELETEof stored events. A mismatch returns412(conditionNotMet).
PUT and PATCH
PUTreplaces writable fields. It resets omitted optional fields to defaults.PATCHpreserves omitted fields.- A supplied
startorendobject replaces the stored object. Its fields are not merged. extendedPropertiesmaps merge by key.nullremoves a key or a whole map.
- A supplied
- All-day inputs accept
dateTime: nullandtimeZone: null.
Deletion and tombstones
events.delete returns 204 and keeps a cancelled tombstone. If the event is already cancelled, it returns 410 (deleted).
| Method | Tombstones |
|---|---|
events.get | Returned |
freebusy.query | Excluded |
| Lists | Excluded unless showDeleted=true or updatedMin is set |
With singleEvents=false, cancelled exceptions of a series stay visible in lists.
For recurrence, invitations, reminders, synthetic Meet links, and time rules, see Events, recurrence and time.
Calendar list
Entry shape
- Calendar-list entries use
kind: "calendar#calendarListEntry". listandgetreturn the same entry shape.
Each owned calendar starts on its owner's list with these values:
accessRole: "owner"selected: truecolorId: "1"(backgroundColor: "#ac725e",foregroundColor: "#1d1d1d")defaultReminders: []primaryconferenceProperties.allowedConferenceSolutionTypes: ["hangoutsMeet"]
Some fields appear only in certain cases:
hiddenis omitted unlesstrue.summaryOverrideandnotificationSettingsare omitted when empty.deleted: trueappears only on removed or tombstoned entries.descriptionandlocationare omitted. Requests that include them are rejected with400(unsupportedFeature).
Writes and concurrency:
- Read-only fields are
kind,etag,id,summary,timeZone,accessRole,primary,deleted, andconferenceProperties. - Writes accept read-only fields only when unchanged. A mismatch returns
400(invalidParameter). idacceptsprimarywhen the path usesprimary.etagupdates when entry settings change. It also updates when the calendar'ssummary,timeZone, orprimaryflag changes.If-Matchis checked onPATCH,PUT, andDELETE. A mismatch returns412(conditionNotMet).
Writing settings (patch, update, insert)
Writable per-user settings are summaryOverride, colorId, backgroundColor, foregroundColor, hidden, selected, defaultReminders, and notificationSettings.
- They persist across SQLite restarts.
- They clear on reset or fixture load.
summaryOverriderequires a non-blank string of up to 10,000 characters.""returns400.
How each write treats omitted fields:
PATCHpreserves omitted writable fields.nullclearssummaryOverride,defaultReminders, andnotificationSettings.PUTandinsert(200) replace writable fields:- Omitted overrides, reminders, and notifications are cleared.
hiddenandselectedreset tofalse. Never-written entries stayselected: true.colorIdresets to"1"unless colors are supplied.
- Unchanged writes return
200. They do not change theetag, invalidate calendar-list page tokens, or notify watch channels.
Colors
colorIdaccepts palette IDs"1"–"24". The foreground is"#1d1d1d".- Unknown IDs, and inherited names like
"constructor", return400.
With colorRgbFormat=true:
- Every
insert,patch, orupdatemust include bothbackgroundColorandforegroundColor(#rrggbb). Otherwise it returns400. - Any supplied
colorIdis ignored and set to the nearest palette color.
Without colorRgbFormat=true:
- RGB fields may only repeat the displayed colors.
- On
PATCH, repeating the currentcolorIdand RGB keeps custom colors. PUTandinsertmust sendcolorRgbFormat=trueto keep custom RGB colors.- A different
colorIdclears custom RGB.
Reminders and notifications
defaultRemindersaccepts up to 5{method: "email" | "popup", minutes: 0–40320}items.notificationSettings.notificationsaccepts up to 5{method: "email", type}items.typeis one ofeventCreation,eventChange,eventCancellation,eventResponse, oragenda.typevalues must be unique. Duplicate types return400.
- Neither setting sends email.
PATCH {"notificationSettings": {}}keeps existing notifications.[],null, orPUTwithoutnotificationsclears them.
Two behaviors follow Google's reference docs and were not checked against live Google:
- Ignoring
colorIdwithcolorRgbFormat=true - Preserving notifications on
PATCH {"notificationSettings": {}}
Delete and insert
calendarList.delete (204) removes a non-primary calendar from the caller's list only.
- The primary calendar returns
403(cannotDeletePrimaryCalendar). - An already removed calendar returns
404. - The calendar and its events remain accessible to
calendars.get,events.*,freebusy.query, andevents.watch. calendarList.get,patch, andupdatereturn404for it.
calendarList.insert restores a removed owned calendar (200).
- It requires
id. A missingidreturns400. - It never creates a calendar.
- Already-listed calendars, including hidden ones and
primary, return409(duplicate). To unhide a calendar, usepatch.
Management API effects:
- Deleting a primary calendar promotes the first remaining listed calendar.
- If all calendars were removed from the list, it instead restores the first owned calendar to the list with its saved settings.
- Setting
primary: truealso restores a removed calendar to the list.
Watch
calendarList.watch shares the loopback allowlist, delivery log, and channels.stop endpoint with events.watch. See Watch notifications.
- It sends
syncon open. - It then sends
existswhen a list write changes stored settings. - It also sends
existswhen the management API creates, updates, or deletes the user's calendars. - Event writes do not trigger it.
- Other query parameters (including
syncToken) return400(unsupportedFeature). params(such asparams.ttl) also returns400(unsupportedFeature).
Lists and paging
calendarList.list
calendarList.list accepts these parameters:
maxResultsandpageTokenminAccessRole:freeBusyReader,reader,writer, orowner. All owned calendars have theownerrole, so every valid value matches them.showHidden: defaults tofalse. Thenlistomitshidden: trueentries, butgetstill returns them.showDeleted: see below.
The response includes a collection etag, but no nextSyncToken.
showDeleted=true includes deleted: true entries for:
- Calendars removed with
calendarList.delete: they keep their stored settings, even ifhidden: true. - Tombstones of calendars deleted through the management API: they use default list settings. They keep
primary: trueif the deleted calendar was primary.
events.list
events.list accepts these parameters:
timeMin,timeMax, andupdatedMin: RFC 3339 timestamps with an offset.maxResults: 1–2500, default 250.orderBy:startTimeorupdated.orderBy=startTimerequiressingleEvents=true.pageToken,singleEvents,timeZone,showDeleted,syncToken, andiCalUID.privateExtendedProperty=name=valueandsharedExtendedProperty=name=value: repeatable filters. All must match.
Matching and ordering:
- Time matching uses
start < timeMaxandend > timeMin. - Unordered lists sort by event ID.
If a calendar has an unbounded recurring series:
events.listrequirestimeMaxwheneversingleEvents=trueortimeMinis set.events.instanceson that series always requirestimeMax.
A missing timeMax returns 400 (unsupportedFeature).
Page tokens
- Event list pages freeze a snapshot on the first page. Writes between pages do not skip items.
- Event page tokens are bound to the query and the user.
- Event page tokens expire after 1 hour. They clear on restart, reset, or fixture load.
- Calendar-list page tokens invalidate on any data or calendar-list write. They are not persisted.
- Expired or stale tokens return
410(invalidPageToken).
For syncToken and nextSyncToken, see Incremental sync.
Explicit exclusions
These features are unsupported:
- ACLs, shared calendars, and delegation
- Calendar groups
- Color palettes (
colors.get) - User settings
- Calendar-list sync tokens
- ACL and settings watch
- Free-text search (
q) eventTypes- Attachments
- Real email delivery
- Real Google Meet creation
- Full OIDC
Request validation
- Unknown body fields return
400(unsupportedFeature). - Unknown query parameters, including
fields, return400(unsupportedFeature) on every/calendar/v3endpoint. - Exception:
channels.stopignores its query string. - Transport parameters (
alt=json,prettyPrint,quotaUser,key) are accepted. - API keys never replace OAuth bearer tokens.
- Calendarpit never proxies to or syncs with Google.
To manage calendars and reset data, see Test control API. To point a client at Calendarpit, see Connect your app.
Storage and restarts
Where Calendarpit stores data, how to choose between SQLite and in-memory mode, and what persists across restarts and resets.
Events, recurrence and time
How Calendarpit expands recurring events, simulates invitations and meetings locally, and handles time zones, DST, and free/busy intervals.