Calendar

Every mailbox is a calendar. Calendar endpoints identify the calendar by its full mailbox email address, passed as the mailbox field. The address must belong to a mailbox in your organization that the API key can access. Availability is computed from that single mailbox’s own calendar; there is no cross-teammate free/busy lookup.

Last updated

The calendar event object

{ "object": "calendar_event", "id": "evt_abc123", "mailbox": "hello@yourdomain.com", "calendar_id": "cal_default", "uid": "…", "title": "Intro call", "description": null, "location": null, "video_url": null, "all_day": false, "start": "2026-08-01T12:00:00.000Z", "end": "2026-08-01T12:30:00.000Z", "timezone": "Europe/Paris", "duration": "PT30M", "status": "confirmed", "free_busy_status": "busy", "privacy": null, "color": null, "recurrence": null, "recurrence_id": null, "reminders": [], "organizer": { "email": "hello@yourdomain.com", "name": "Hello" }, "attendees": [{ "email": "guest@example.com", "name": "Guest", "status": "accepted" }], "created_at": null, "updated_at": null }
FieldTypeDescription
idstringUnique event ID.
mailboxstringThe mailbox (calendar owner) address.
calendar_idstring | nullThe calendar the event lives on.
titlestring | nullEvent title.
descriptionstring | nullLong description.
locationstring | nullPhysical location.
video_urlstring | nullVideo or conference join URL.
all_daybooleanWhether the event is all-day.
startstringUTC instant for timed events; a YYYY-MM-DD date for all-day events.
endstringUTC instant for timed events; the exclusive end date for all-day events.
timezonestring | nullThe event's own IANA zone. Null for all-day or floating events.
durationstring | nullISO 8601 duration (e.g. PT1H).
statusstring | nullconfirmed, tentative, or cancelled.
free_busy_statusstring | nullfree or busy.
privacystring | nullpublic, private, or secret.
colorstring | nullEvent color.
recurrenceobject | null{ frequency, interval?, count?, until?, by_day? }.
recurrence_idstring | nullSet on an expanded recurrence instance.
remindersarrayEmail reminders as [{ minutes_before }].
organizerobject | nullOrganizer email and display name.
attendeesarrayAttendee email, display name, and RSVP status.
created_atstring | nullISO 8601 timestamp, when available.
updated_atstring | nullISO 8601 timestamp, when available.

List events

GET /v1/calendar/events

Scope: calendar:read. Required query params: mailbox, from and to (UTC instants). Optional: expand (return recurring events as individual instances), calendar_id, cursor, and limit (1–250, default 100). Returns a cursor-paginated list.

Create an event

POST /v1/calendar/events

Scope: calendar:write. start is a local date-time whose zone is given by timezone.

{ "mailbox": "hello@yourdomain.com", "title": "Intro call", "start": "2026-08-01T14:00:00", "timezone": "Europe/Paris", "duration": "PT30M", "reminders": [{ "minutes_before": 10 }], "attendees": [{ "email": "guest@example.com", "name": "Guest" }] }

Adding attendees sends calendar invitations. Event responses include the organizer and each attendee’s current RSVP status.

Get, update, or delete an event

GET /v1/calendar/events/:id?mailbox=hello@yourdomain.com PATCH /v1/calendar/events/:id DELETE /v1/calendar/events/:id?mailbox=hello@yourdomain.com

GET and DELETE require the mailbox query param. PATCH takes mailbox plus any fields to change in the body; omitted fields are unchanged, and a null value clears the description, timezone, location, video_url, recurrence, or reminders. Set attendees to the desired complete attendee list to send new invitations or cancellations. DELETE returns 204.

Get availability

GET /v1/calendar/availability

Scope: calendar:read. Returns open meeting slots for one mailbox, computed from its own calendar. Required: mailbox, from, and to. Optional: duration (minutes, default 30), interval, timezone, days (comma-separated 0–6, 0 is Sunday), window_start and window_end (minutes from midnight), buffer, and minimum_notice.

{ "object": "calendar_availability", "mailbox": "hello@yourdomain.com", "from": "2026-08-03T00:00:00.000Z", "to": "2026-08-04T00:00:00.000Z", "duration_minutes": 30, "timezone": "America/New_York", "slots": [ { "start": "2026-08-03T13:00:00.000Z", "end": "2026-08-03T13:30:00.000Z" } ] }