> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oximail.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# Calendar

> The JMAP Calendars surface (draft-ietf-jmap-calendars): Calendar, CalendarEvent, notifications, participant identities, availability — plus recurrence, time-zone, and scheduling behaviours.

Calendars implement the JMAP Calendars draft (`urn:ietf:params:jmap:calendars`), with events as JSCalendar objects ([RFC 8984](https://www.rfc-editor.org/rfc/rfc8984)). The same data is served over [CalDAV](../operator/legacy-protocols) — one store, two protocols.

## Objects and methods

| Object                      | Methods                                          | Notes                                                                                     |
| --------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| `Calendar`                  | `get`, `set`, `query`, `changes`                 | Collections, colors, `shareWith` grants, `includeInAvailability`, per-viewer `isVisible`. |
| `CalendarEvent`             | `get`, `set`, `query`, `queryChanges`, `changes` | JSCalendar events; see the behaviours below.                                              |
| `CalendarEventNotification` | `get`, `set`                                     | Change notifications for shared calendars and inbound scheduling.                         |
| `ParticipantIdentity`       | `get`, `set`                                     | The addresses under which the account participates in scheduling.                         |
| `Principal/getAvailability` | —                                                | Free-busy composition; see below.                                                         |

`CalendarEvent/counter` is an OxiMail addition for occurrence counting.

## Recurrence

* The property is **`recurrenceRules`** (plural, RFC 8984) — always.
* Recurring events expand through **one occurrence-enumeration authority**, shared by JMAP queries, CalDAV `time-range` filters, free-busy, and alarms — an occurrence exists identically everywhere, across DST boundaries (expansion is anchored to the event's local zone).
* Per-occurrence overrides are keyed by civil-local time; overrides created in one protocol are honored (and protected by content-hash ETags) in the other.
* An imported `RRULE` the model cannot represent is kept verbatim and flagged `hasUnmodeledRecurrence` on read — never a half-converted rule.

## Time zones

`start` is a LocalDateTime; the zone lives in `timeZone` (a UTC instant is stored as local time + `Etc/UTC`, never a `Z`-suffixed `start`). All-day events use `showWithoutTime`. A floating event resolves through the fallback chain event zone → user zone → organization default → UTC ([groupware](../operator/groupware#time-zones)).

## Scheduling (iTIP)

Creating an event with participants triggers invitation mail — under two hard rules: only when the **organizer resolves to a local account** (RFC 5546: only the organizer's server sends), and only **after the transaction commits** (a `stateMismatch` emits nothing). REPLY/CANCEL follow the same discipline; inbound invitations and replies are processed at ingestion and produce `CalendarEventNotification` objects. A grantee's edit on a shared calendar notifies the owner the same way.

## Availability

`Principal/getAvailability` composes busy time from the subject's subscribed calendars whose `includeInAvailability` is `all` or `attending`, returning `BusyPeriod` objects. Privacy is layered: `secret` events hide their busy time entirely, `private` events contribute time but never details, and event details populate only under `showDetails` **and** real read access. A caller with free-busy rights on none of the subject's calendars gets a per-id `forbidden`, not an empty answer.

## Alerts

`alerts` supports both offset triggers (`relativeTo: "start"`/`"end"`) and absolute ones (`when`). They fire server-side (push / notification), once per occurrence. VALARMs round-trip with CalDAV clients; public ICS feed exports deliberately carry none.

Strictness rules (unknown ids in `notFound`, `invalidProperties` over coercion, `stateMismatch` on `ifInState`) are identical to the [mail surface](./jmap-mail).
