Fork me on GitHub

JMAP Calendars

This document specifies a data model for synchronising calendar data with a server using JMAP.

Introduction

JMAP is a generic protocol for synchronising data, such as mail, calendars or contacts, between a client and a server. It is optimised for mobile and web environments, and aims to provide a consistent interface to different data types.

This specification defines a data model for synchronising calendar data between a client and a server using JMAP.

Notational Conventions

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [@!RFC2119].

The underlying format used for this specification is JSON. Consequently, the terms “object” and “array” as well as the four primitive types (strings, numbers, booleans, and null) are to be interpreted as described in Section 1 of [@!RFC7159].

Some examples in this document contain “partial” JSON documents used for illustrative purposes. In these examples, three periods “…” are used to indicate a portion of the document that has been removed for compactness.

Types signatures are given for all JSON objects in this document. The following conventions are used:

LocalDate

Where the API specifies LocalDate as a type, it means a string in the same format as Date, but with the Z omitted from the end. The interpretation in absolute time depends upon the time zone for the event, which MAY NOT be a fixed offset (for example when daylight saving time occurs).

Terminology

The same terminology is used in this document as in the core JMAP specification.

Addition to the capabilities object

The capabilities object is returned as part of the standard JMAP authentication response; see the JMAP spec. Servers supporting this specification MUST add a property called {TODO: URI for this spec} to the capabilities object. The value of this is an empty object.

Calendars

A Calendar is a named collection of events. All events are associated with one, and only one, calendar.

A Calendar object has the following properties:

getCalendars

Calendars can either be fetched explicitly by id, or all of them at once. To fetch calendars, make a call to getCalendars. It takes the following arguments:

The response to getCalendars is called calendars. It has the following arguments:

The following errors may be returned instead of the calendars response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

invalidArguments: Returned if one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

getCalendarUpdates

The getCalendarUpdates call allows a client to efficiently update the state of its cached calendars to match the new state on the server. It takes the following arguments:

The response to getCalendarUpdates is called calendarUpdates. It has the following arguments:

If a calendar has been modified AND deleted since the oldState, the server should just return the id in the removed array, but MAY return it in the changed array as well. If a calendar has been created AND deleted since the oldState, the server SHOULD remove the calendar id from the response entirely, but MAY include it in the removed array.

The following errors may be returned instead of the calendarUpdates response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

requestTooLarge: Returned if the number of ids requested by the client exceeds the maximum number the server is willing to process in a single method call.

invalidArguments: Returned if the request does not include one of the required arguments, or one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

cannotCalculateChanges: Returned if the server cannot calculate the changes from the state string given by the client. Usually due to the client’s state being too old. The client MUST invalidate its Calendar cache.

setCalendars

Modifying the state of Calendar objects on the server is done via the setCalendars method. This encompasses creating, updating and destroying Calendar records.

The setCalendars method takes the following arguments:

Each create, update or destroy is considered an atomic unit. It is permissible for the server to commit some of the changes but not others, however it is not permissible to only commit part of an update to a single calendar (e.g. update the name property but not the isVisible property if both are supplied in the update object).

If a create, update or destroy is rejected, the appropriate error MUST be added to the notCreated/notUpdated/notDestroyed property of the response and the server MUST continue to the next create/update/destroy. It does not terminate the method.

If an id given cannot be found, the update or destroy MUST be rejected with a notFound set error.

The mayXXX properties are optional when creating a calendar. All default to true. If present, they MUST all be set to true. These properties are read-only to the client and may not be modified in an update call. Restrictions may only be set by the server, or when sharing calendars with other accounts (setting up sharing is not yet defined in this spec).

A calendar MAY be deleted that is currently associated with one or more events. In this case, the events belonging to this calendar MUST also be deleted. Conceptually, this MUST happen prior to the calendar itself being deleted, and MUST generate a push event that modifies the state of the CalendarEvent type for the account, and has a clientId of null, to indicate that a change has been made to the event data not explicitly requested by the client.

The response to setCalendars is called calendarsSet. It has the following arguments:

A SetError object has the following properties:

If any of the properties in a create or update are invalid (immutable and different to the current server value, wrong type, invalid value for the property – like a zero-length name), the server MUST reject the create/update with a SetError of type invalidProperties. The SetError object SHOULD contain a property called properties of type String[] that lists all the properties that were invalid. The object MAY also contain a description property of type String with a user-friendly description of the problems.

The following errors may be returned instead of the calendarEventsSet response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

accountReadOnly: Returned if the account has isReadOnly == true.

requestTooLarge: Returned if the total number of objects to create, update or destroy exceeds the maximum number the server is willing to process in a single method call.

invalidArguments: Returned if one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

stateMismatch: Returned if an ifInState argument was supplied and it does not match the current state.

CalendarEventLists

A CalendarEventList is a query on the set of events in a user’s calendars. The client can optionally also fetch the events.

getCalendarEventList

To fetch a calendar event list, make a call to getCalendarEventList. It takes the following arguments:

Filtering

A FilterOperator object has the following properties:

A FilterCondition object has the following properties:

If zero properties are specified on the FilterCondition, the condition MUST always evaluate to true. If multiple properties are specified, ALL must apply for the condition to be true (it is equivalent to splitting the object into one-property conditions and making them all the child of an AND filter operator).

The exact semantics for matching String fields is deliberately not defined to allow for flexibility in indexing implementation, subject to the following:

Sorting

Results MUST be sorted in a stable order so the client can load the full list in sections. The exact ordering to use is server dependent.

Windowing

To paginate the results the client MAY supply a position argument: this is the 0-based index of the first result to return in the list of events after filtering and sorting. If the index is greater than or equal to the total number of events in the list, then there are no results to return, but this DOES NOT generate an error. If null, this defaults to 0.

Response

The response to a call to getCalendarEventList is called calendarEventList. It has the following arguments:

The following errors may be returned instead of the calendarEventList response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

invalidArguments: Returned if the request does not include one of the required arguments, or one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

Calendar Events

A CalendarEvent contains information about an event, or recurring series of events, that takes place at a particular time. The object is designed to be easily convertible to/from iCalendar format ([@!RFC5545]) for compatibility with existing calendaring systems.

A CalendarEvent object has the following properties:

When mapping from iCalendar, the LOCATION property should become a single location with just a name property. If the event has a different end time zone to start time zone, this should be added as a second location with just a timeZone property.

If isAllDay is true, then the following restrictions apply:

Any nullable array/object property MUST be null rather than an empty array or object.

getCalendarEvents

CalendarEvents can only be fetched explicitly by id. To fetch events, make a call to getCalendarEvents. It takes the following arguments:

The id property is always returned, regardless of whether it is in the list of requested properties. The possible values for properties can be found above in the description of the CalendarEvent object.

The response to getCalendarEvents is called calendarEvents. It has the following arguments:

The following errors may be returned instead of the events response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

requestTooLarge: Returned if the number of ids requested by the client exceeds the maximum number the server is willing to process in a single method call.

invalidArguments: Returned if the request does not include one of the required arguments, or one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

getCalendarEventUpdates

The getCalendarEventUpdates call allows a client to efficiently update the state of its cached calendar events to match the new state on the server. It takes the following arguments:

The response to getCalendarEventUpdates is called calendarEventUpdates. It has the following arguments:

If a maxChanges is supplied, or set automatically by the server, the server MUST ensure the number of ids returned across changed and removed does not exceed this limit. If there are more changes than this between the client’s state and the current server state, the update returned SHOULD generate an update to take the client to an intermediate state, from which the client can continue to call getCalendarEventUpdates until it is fully up to date. If it is unable to calculat an intermediate state, it MUST return a cannotCalculateChanges error response instead.

If an event has been modified AND deleted since the oldState, the server should just return the id in the removed array, but MAY return it in the changed array as well. If an event has been created AND deleted since the oldState, the server SHOULD remove the event id from the response entirely, but MAY include it in the removed array.

The following errors may be returned instead of the calendarEventUpdates response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

invalidArguments: Returned if the request does not include one of the required arguments, or one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

cannotCalculateChanges: Returned if the server cannot calculate the changes from the state string given by the client. Usually due to the client’s state being too old, or the server being unable to produce an update to an intermediate state when there are too many updates. The client MUST invalidate its CalendarEvent cache.

setCalendarEvents

Modifying the state of CalendarEvent objects on the server is done via the setCalendarEvents method. This encompasses creating, updating and destroying CalendarEvent records.

The setCalendarEvents method takes the following arguments:

Each create, update or destroy is considered an atomic unit. It is permissible for the server to commit some of the changes but not others, however it is not permissible to only commit part of an update to a single event (e.g. update the start property but not the timeZone property if both are supplied in the update object).

If a create, update or destroy is rejected, the appropriate error MUST be added to the notCreated/notUpdated/notDestroyed property of the response and the server MUST continue to the next create/update/destroy. It does not terminate the method.

If an id given cannot be found, the update or destroy MUST be rejected with a notFound set error.

CalendarEvents reference a Calendar object. When events are created or modified, they may reference a calendar being created in the same API request by using the creation id prefixed with a #. The order of the method calls in the request by the client MUST be such that the calendar being referenced is created in an earlier call. The server thus never has to look ahead. Instead, while processing a request (a series of method calls), the server MUST keep a simple map for the duration of the request of creation id to Calendar id for each newly created calendar, so it can substitute in the correct value if necessary in later method calls. Creation ids sent by the client SHOULD be unique within the single API request for a particular data type. If a creation id is reused, the server MUST map the creation id to the most recently created item with that id.

To add new attachments, the file must first be uploaded using the standard upload mechanism (see the File Uploads section of this spec). This will give the client a valid blobId/size/type to use.

When an event is created, updated or destroyed, the server MUST also ensure the following:

The response to setCalendarEvents is called calendarEventsSet. It has the following arguments:

A SetError object has the following properties:

If any of the properties in a create or update are invalid (immutable and different to the current server value, wrong type, invalid value for the property – like a calendarId for a non-existent calendar), the server MUST reject the create/update with a SetError of type invalidProperties. The SetError object SHOULD contain a property called properties of type String[] that lists all the properties that were invalid. The object MAY also contain a description property of type String with a user-friendly description of the problems.

The following errors may be returned instead of the calendarEventsSet response:

accountNotFound: Returned if an accountId was explicitly included with the request, but it does not correspond to a valid account.

accountNotSupportedByMethod: Returned if the accountId given corresponds to a valid account, but the account does not support this data type.

accountReadOnly: Returned if the account has isReadOnly == true.

requestTooLarge: Returned if the total number of objects to create, update or destroy exceeds the maximum number the server is willing to process in a single method call.

invalidArguments: Returned if one of the arguments is of the wrong type, or otherwise invalid. A description property MAY be present on the response object to help debug with an explanation of what the problem was.

stateMismatch: Returned if an ifInState argument was supplied and it does not match the current state.