Calendar
The core keeps everyone's calendars, so the Calendar app, phones, Mail and your app all see the same events. Your back end reaches them through the core's calendar API, acting for the person using the app.
Grants
calendar.readlets your app makeGETrequests.calendar.writelets it make everything else.
Call with your token and the person in X-Solel-Person, as Acting for a person describes. An app installed for one person always acts for them, so it can leave the header out. Your app sees and changes only what that person could: their own calendars and those shared with them. See Calendars and who sees them.
An event
{
"id": "…", "calendarId": "…", "uid": "…", "etag": "…",
"title": "Swimming", "start": "2026-10-24T09:00:00+11:00", "end": "2026-10-24T10:00:00+11:00",
"allDay": false, "timeZone": "Australia/Melbourne", "location": "Fitzroy pool", "notes": "",
"repeat": { "freq": "weekly", "days": ["SA"], "until": "2026-12-19" },
"reminders": [30],
"occurrence": "2026-10-31T09:00:00+11:00", "moved": false
}
- Times.
startandendare RFC 3339 times. For an all-day event they're dates, andendis the day after it finishes. AtimeZonekeeps an event at the same local time across daylight saving changes; without one, it's stored in UTC. - Repeats.
freqisdaily,weekly,monthlyoryearly, with an optionalinterval,days(MOtoSU), and eitheruntilorcount. A repeat another app wrote that says more than this comes back with itsruleas written, and is kept unless you change it. - One time of a repeat. Listed events give each time a repeat happens as its own entry, with
occurrence, when that time was due. Pass?occurrence=with that value to change or remove just that time. - Reminders are minutes before the start, up to five.
- Invitations carry an
organizerandattendees, and are read-only here. - Conflicts. Send
If-Matchwith the event'setagwhen you change or remove it. If someone changed it in the meantime, the answer is412.
Each event is kept as the iCalendar object a phone sends, so nothing your app writes is lost.
Endpoints
| Request | What it does |
|---|---|
GET /api/calendar/calendars |
The person's calendars, then those shared with them, each with its access: owner, change or see |
POST /api/calendar/calendars |
Makes one: {"name", "colour"}, with colour flare, ink or umber |
PATCH /api/calendar/calendars/{id} |
Renames it or changes its colour |
DELETE /api/calendar/calendars/{id} |
Deletes one of theirs, or stops showing one shared with them |
PUT /api/calendar/calendars/{id}/shares |
{"shares": [{"personId", "access": "see" or "change"}]}. Each new person gets a notification |
GET /api/calendar/people |
Who a calendar can be shared with |
GET /api/calendar/events?from=&to=&calendar= |
Every time something happens between from and to, up to 400 days at once |
POST /api/calendar/calendars/{id}/events |
Adds an event. It needs a title and a start, and lasts an hour unless you say otherwise |
GET /api/calendar/events/{id} |
One event |
PATCH /api/calendar/events/{id}?occurrence= |
Changes any of its fields. Moving the start keeps the length |
DELETE /api/calendar/events/{id}?occurrence= |
Removes it, or just that time of it |
POST /api/calendar/events/{id}/move |
Moves it to another calendar: {"calendarId"} |
POST /api/calendar/calendars/{id}/import |
Brings in an .ics file of up to 32 MiB, sent as text/calendar. Answers {"added", "had", "skipped"} |
GET /api/calendar/calendars/{id}/export |
The whole calendar as an .ics file |
POST /api/calendar/subscriptions |
Subscribes to a calendar on the internet: {"url", "name", "colour"} |
POST /api/calendar/calendars/{id}/refresh |
Fetches a subscription again now. Send {} |
GET /api/calendar/holidays, PUT /api/calendar/holidays |
Where the person's public holidays come from, and {"country", "region"} to choose |