Clojure wrapper for the Google Calendar API (v3).
Provides idiomatic Clojure functions for managing events, calendars, calendar list entries, access control, free/busy queries, colors, and settings in Google Calendar.
Auth: use csl/scoped-delegated-credentials or csl/user-credentials with the appropriate scope:
All list functions return {:data [...] :next-page-token "..."}. :next-page-token is absent when there are no further pages.
Update semantics: functions named update-* use PATCH (partial update); functions named replace-* use PUT (full replacement). Both return the updated resource.
All functions return {:data ...} on success or {:error ...} on failure.
Clojure wrapper for the Google Calendar API (v3).
Provides idiomatic Clojure functions for managing events, calendars,
calendar list entries, access control, free/busy queries, colors,
and settings in Google Calendar.
Auth: use csl/scoped-delegated-credentials or csl/user-credentials with
the appropriate scope:
- CalendarScopes/CALENDAR (full read/write)
- CalendarScopes/CALENDAR_READONLY (read-only)
- CalendarScopes/CALENDAR_EVENTS (events read/write)
- CalendarScopes/CALENDAR_EVENTS_READONLY (events read-only)
- CalendarScopes/CALENDAR_SETTINGS_READONLY (settings read-only)
All list functions return {:data [...] :next-page-token "..."}.
:next-page-token is absent when there are no further pages.
Update semantics: functions named update-* use PATCH (partial update);
functions named replace-* use PUT (full replacement). Both return
the updated resource.
All functions return {:data ...} on success or {:error ...} on failure.(calendar-client credentials)(calendar-client credentials opts)Build an authenticated Calendar v3 REST client.
credentials —a com.google.auth.oauth2.GoogleCredentials instance, typically from csl/scoped-delegated-credentials or csl/user-credentials.
opts (optional):
Per-request opts on individual call sites override the client-level defaults.
Build an authenticated Calendar v3 REST client. credentials —a com.google.auth.oauth2.GoogleCredentials instance, typically from csl/scoped-delegated-credentials or csl/user-credentials. opts (optional): - :read-timeout-ms per-client default read timeout (default 120000 / 120s) - :connect-timeout-ms per-client default connect timeout (default 30000 / 30s) Per-request opts on individual call sites override the client-level defaults.
(clear-calendar client calendar-id)Clear all events from a primary calendar. The calendar itself is not deleted.
Clear all events from a primary calendar. The calendar itself is not deleted.
(create-acl-rule client calendar-id rule & [opts])Create an ACL rule on a calendar (grant access).
rule —map with kebab-case keys: :role —"reader", "writer", "owner", or "freeBusyReader" :scope —{:type "user" :value "email@example.com"}
opts:
Create an ACL rule on a calendar (grant access).
rule —map with kebab-case keys:
:role —"reader", "writer", "owner", or "freeBusyReader"
:scope —{:type "user" :value "email@example.com"}
opts:
- :send-notifications —boolean (whether to notify the grantee)
- :fields —partial response field mask string(create-calendar client calendar-data & [opts])Create a new secondary calendar.
calendar-data —map with kebab-case keys: :summary —calendar name :description —calendar description :time-zone —IANA time zone (e.g. "America/New_York")
opts:
Create a new secondary calendar. calendar-data —map with kebab-case keys: :summary —calendar name :description —calendar description :time-zone —IANA time zone (e.g. "America/New_York") opts: - :fields —partial response field mask string
(create-event client calendar-id event & [opts])Create a new event on a calendar.
event —map with kebab-case keys describing the event: :summary —event title :start —{:date-time "..." :time-zone "..."} or {:date "YYYY-MM-DD"} :end —same format as :start :attendees —[{:email "..."}] :description —event description :location —event location
opts:
Create a new event on a calendar.
event —map with kebab-case keys describing the event:
:summary —event title
:start —{:date-time "..." :time-zone "..."} or {:date "YYYY-MM-DD"}
:end —same format as :start
:attendees —[{:email "..."}]
:description —event description
:location —event location
opts:
- :send-updates —:all, :external-only, or :none (keyword or string)
- :fields —partial response field mask string(delete-acl-rule client calendar-id rule-id & [opts])Delete an ACL rule from a calendar (revoke access).
opts:
Delete an ACL rule from a calendar (revoke access). opts: - :if-match —etag precondition (see update-acl-rule); 412 on a live etag mismatch, so a revocation adjudicated against a stale rule refuses instead of deleting a rule someone has since changed.
(delete-calendar client calendar-id & [opts])Permanently delete a secondary calendar. Primary calendars cannot be deleted; use clear-calendar to remove all events from a primary calendar.
Permanently delete a secondary calendar. Primary calendars cannot be deleted; use clear-calendar to remove all events from a primary calendar.
(delete-calendar-entry client calendar-id & [opts])Remove a calendar from the user's calendar list. This unsubscribes the user; it does not delete the calendar itself.
Remove a calendar from the user's calendar list. This unsubscribes the user; it does not delete the calendar itself.
(delete-event client calendar-id event-id & [opts])Delete an event.
opts:
Delete an event. opts: - :send-updates —:all, :external-only, or :none
(get-acl-rule client calendar-id rule-id & [opts])Get an ACL rule by ID.
opts:
Get an ACL rule by ID. opts: - :fields —partial response field mask string
(get-calendar client calendar-id & [opts])Get a calendar's metadata by ID.
opts:
Get a calendar's metadata by ID. opts: - :fields —partial response field mask string
(get-calendar-entry client calendar-id & [opts])Get a calendar list entry by calendar ID. Returns user-specific metadata (color, visibility, notification settings) for a calendar in the user's list.
opts:
Get a calendar list entry by calendar ID. Returns user-specific metadata (color, visibility, notification settings) for a calendar in the user's list. opts: - :fields —partial response field mask string
(get-colors client & [opts])Get the color definitions for calendars and events.
Get the color definitions for calendars and events.
(get-event client calendar-id event-id & [opts])Get an event by ID.
opts:
Get an event by ID. opts: - :fields —partial response field mask string - :time-zone —time zone for expanding recurring events
(get-setting client setting-id & [opts])Get a single user setting by ID (e.g. "timezone", "locale", "format24HourTime").
Get a single user setting by ID (e.g. "timezone", "locale", "format24HourTime").
(import-event client calendar-id event & [opts])Import an event (e.g. from iCalendar data). The event's iCalUID must be set. Unlike create-event, imported events do not send invitations.
Pass the dedupe key as :i-cal-uid. Google's reference promises only 'adds a private copy' — neither update-on-collision nor retry idempotency is a documented contract. MEASURED behavior (Google Tern's five-leg wire gate, 2026-09-02, client v3-rev20260708): an exact repeat is idempotent (same id, content unchanged), a changed-body repeat UPDATES IN PLACE, and — the caveat — an import whose iCalUID matches an event that already exists on the target calendar (however it got there, e.g. a natively received copy of the same meeting) silently OVERWRITES that event in place, with no preimage. Callers migrating onto calendars that may already hold events must verify emptiness or accept that collision semantics themselves; measure on your own tenant before relying on the upsert.
opts:
Import an event (e.g. from iCalendar data). The event's iCalUID must be set. Unlike create-event, imported events do not send invitations. Pass the dedupe key as :i-cal-uid. Google's reference promises only 'adds a private copy' — neither update-on-collision nor retry idempotency is a documented contract. MEASURED behavior (Google Tern's five-leg wire gate, 2026-09-02, client v3-rev20260708): an exact repeat is idempotent (same id, content unchanged), a changed-body repeat UPDATES IN PLACE, and — the caveat — an import whose iCalUID matches an event that already exists on the target calendar (however it got there, e.g. a natively received copy of the same meeting) silently OVERWRITES that event in place, with no preimage. Callers migrating onto calendars that may already hold events must verify emptiness or accept that collision semantics themselves; measure on your own tenant before relying on the upsert. opts: - :fields — partial response field mask string
(insert-calendar-entry client entry & [opts])Add an existing calendar to the user's calendar list. This subscribes the user to the calendar; it does not create a new calendar.
entry —map with kebab-case keys. Required: :id —the calendar ID to add
opts:
Add an existing calendar to the user's calendar list. This subscribes the user to the calendar; it does not create a new calendar. entry —map with kebab-case keys. Required: :id —the calendar ID to add opts: - :fields —partial response field mask string
(list-acl-rules client calendar-id & [opts])List ACL rules for a calendar.
opts:
List ACL rules for a calendar. opts: - :page-token —token from a previous response - :page-size —max rules per page - :show-deleted —boolean - :fields —partial response field mask string
(list-calendar-entries client & [opts])List all calendars in the authenticated user's calendar list.
opts:
List all calendars in the authenticated user's calendar list. opts: - :min-access-role —minimum access role: :free-busy-reader, :reader, :writer, :owner - :show-deleted —boolean - :show-hidden —boolean - :page-token —token from a previous response - :page-size —max entries per page - :fields —partial response field mask string
(list-event-instances client calendar-id event-id & [opts])List individual occurrences of a recurring event.
opts:
List individual occurrences of a recurring event. opts: - :time-min —lower bound for instance start time, RFC 3339 string - :time-max —upper bound for instance start time, RFC 3339 string - :page-token —token from a previous response - :page-size —max instances per page - :fields —partial response field mask string
(list-events client calendar-id & [opts])List events on a calendar.
opts:
List events on a calendar. opts: - :time-min —lower bound (exclusive) for event end time, RFC 3339 string - :time-max —upper bound (exclusive) for event start time, RFC 3339 string - :q —free text search terms - :order-by —:start-time or :updated (keyword or string) - :single-events —boolean; when true, expands recurring events into instances - :page-token —token from a previous response - :page-size —max events per page - :show-deleted —boolean - :updated-min —lower bound on last-modification time, RFC 3339 string - :fields —partial response field mask string
(list-settings client & [opts])List all user settings.
opts:
List all user settings. opts: - :page-token —token from a previous response - :fields —partial response field mask string
(move-event client calendar-id event-id destination-calendar-id & [opts])Move an event to another calendar.
opts:
Move an event to another calendar. opts: - :send-updates —:all, :external-only, or :none
(query-freebusy client query-data & [opts])Query free/busy information for a set of calendars.
query-data —map with kebab-case keys: :time-min —start of the interval, RFC 3339 string :time-max —end of the interval, RFC 3339 string :time-zone —IANA time zone (optional) :items —[{:id "calendar-id@example.com"}]
Query free/busy information for a set of calendars.
query-data —map with kebab-case keys:
:time-min —start of the interval, RFC 3339 string
:time-max —end of the interval, RFC 3339 string
:time-zone —IANA time zone (optional)
:items —[{:id "calendar-id@example.com"}](quick-add-event client calendar-id text & [opts])Create an event from a text string (e.g. "Lunch with Dave tomorrow at noon").
opts:
Create an event from a text string (e.g. "Lunch with Dave tomorrow at noon"). opts: - :send-updates —:all, :external-only, or :none
(replace-acl-rule client calendar-id rule-id rule & [opts])Fully replace an ACL rule (PUT semantics).
opts:
Fully replace an ACL rule (PUT semantics). opts: - :send-notifications —boolean - :fields —partial response field mask string - :if-match —etag precondition (see update-acl-rule); 412 on a live etag mismatch
(replace-calendar client calendar-id calendar-data & [opts])Fully replace a calendar's metadata (PUT semantics).
opts:
Fully replace a calendar's metadata (PUT semantics). opts: - :fields —partial response field mask string
(replace-calendar-entry client calendar-id entry & [opts])Fully replace a calendar list entry (PUT semantics).
opts:
Fully replace a calendar list entry (PUT semantics). opts: - :fields —partial response field mask string
(replace-event client calendar-id event-id event & [opts])Fully replace an event (PUT semantics). The entire event resource is replaced with the provided data; omitted fields are cleared.
opts:
Fully replace an event (PUT semantics). The entire event resource is replaced with the provided data; omitted fields are cleared. opts: - :send-updates —:all, :external-only, or :none - :fields —partial response field mask string
(transfer-calendar-ownership client calendar-id new-data-owner & [opts])Transfer a secondary calendar's DATA OWNERSHIP to another user in the same tenant (calendars.transferOwnership). The data owner is the single immutable owning principal every secondary calendar carries under the 2025-10-27 regime; ACL role changes cannot move it — only this call can.
The success response body is EMPTY (Void): an accepted transfer proves nothing about the resulting state. Confirm each direction with a live dataOwner read (get-calendar with :fields "id,dataOwner").
Failures carry csl's structured error map — :code (HTTP status) and :reason (e.g. "userRateLimitExceeded") ride along for classification.
opts:
Transfer a secondary calendar's DATA OWNERSHIP to another user in the same tenant (calendars.transferOwnership). The data owner is the single immutable owning principal every secondary calendar carries under the 2025-10-27 regime; ACL role changes cannot move it — only this call can. The success response body is EMPTY (Void): an accepted transfer proves nothing about the resulting state. Confirm each direction with a live dataOwner read (get-calendar with :fields "id,dataOwner"). Failures carry csl's structured error map — :code (HTTP status) and :reason (e.g. "userRateLimitExceeded") ride along for classification. opts: - :use-admin-access —boolean; true runs the call with Manage-Calendars admin privilege (required whenever the caller is not the current data owner). Defaults to false. - :read-timeout-ms —per-request read-timeout override (ms) - :connect-timeout-ms —per-request connect-timeout override (ms)
(update-acl-rule client calendar-id rule-id rule & [opts])Partially update an ACL rule (PATCH semantics).
opts:
Partially update an ACL rule (PATCH semantics). opts: - :send-notifications —boolean - :fields —partial response field mask string - :if-match —etag precondition: the rule's etag as returned by get/list. The PATCH is refused with 412 Precondition Failed when the live rule's etag differs, so an adjudicated mutation cannot overwrite a concurrent change it never saw.
(update-calendar client calendar-id calendar-data & [opts])Partially update a calendar's metadata (PATCH semantics).
opts:
Partially update a calendar's metadata (PATCH semantics). opts: - :fields —partial response field mask string
(update-calendar-entry client calendar-id entry & [opts])Partially update a calendar list entry (PATCH semantics).
entry —map with kebab-case keys for fields to update (e.g. {:color-id "11" :hidden false})
opts:
Partially update a calendar list entry (PATCH semantics).
entry —map with kebab-case keys for fields to update
(e.g. {:color-id "11" :hidden false})
opts:
- :fields —partial response field mask string(update-event client calendar-id event-id event & [opts])Partially update an event (PATCH semantics). Only the fields present in the event map are modified; unspecified fields are left unchanged.
opts:
Partially update an event (PATCH semantics). Only the fields present in the event map are modified; unspecified fields are left unchanged. opts: - :send-updates —:all, :external-only, or :none - :fields —partial response field mask string
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |