Most scheduling tools support Google and Microsoft, and stop. If your calendar lives in iCloud, Fastmail, Nextcloud, Zimbra or a server you run yourself, you are usually told to export an ICS file and give up on two-way sync.
CalDAV is the answer to that, and it has been a published standard since 2007. It is a protocol, not a product, so a single CalDAV integration reaches every server that implements it. That breadth is the point.
It is also weaker than the Google and Microsoft APIs in one specific way that you should understand before you rely on it: there is no dependable push notification, so sync is polled. Everything else is roughly comparable. This article covers the protocol, connecting iCloud with an app-specific password, how calendar URLs are found, and the limits.
What CalDAV Is
CalDAV is defined in RFC 4791. It builds on WebDAV, which itself extends HTTP with the idea that a URL can be a collection you can list, add to and lock. CalDAV adds calendar semantics on top: a calendar is a collection, and each event in it is a resource whose body is iCalendar data, the same ICS format used by email invitations.
The operations map onto that model directly:
PROPFINDasks for properties of a collection or resource: its display name, its type, what components it supports, what privileges you have on it.REPORTruns queries, for example "give me every event between these two dates" or "give me these specific resources by URL".PUTcreates or replaces an event at a URL. Creating a booking is aPUTof an ICS body.DELETEremoves an event. Cancelling a booking is aDELETE.
Every resource carries an ETag, and a well behaved client sends the ETag it last saw when it updates something. If the event changed underneath it, the server refuses the write instead of silently overwriting the other change. That is a genuinely good concurrency model, better than what several proprietary APIs offer.
Why An Open Standard Matters For Calendar Sync
The practical argument is coverage. One implementation gives you:
| Service | Typical server address | Credential |
|---|---|---|
| iCloud | caldav.icloud.com | Apple ID plus an app-specific password |
| Fastmail | caldav.fastmail.com/dav/ | Account name plus an app password |
| Nextcloud | https://your-server/remote.php/dav/ | Username plus an app password from Security settings |
| SOGo | https://your-server/SOGo/dav/ | Account password |
| Zimbra | https://your-server/dav/ | Account password |
| Radicale, Baikal, self-hosted | Whatever you configured | Account password |
The second argument is portability. A calendar you can reach over CalDAV is a calendar you can move. If you leave a provider, the protocol does not change, only the hostname. That is not true of an integration built on one vendor API.
The third is self-hosting. Organisations that will not put staff calendars in a public cloud can still get two-way booking sync, because the server is theirs.
How A CalDAV Client Finds Your Calendars
You give a client an address and credentials, and it works out the rest. RFC 6764 describes the discovery sequence, and it is worth knowing because when a connection fails, it usually fails at a specific step.
- Find the server. From an email address, the client can look up a service record in DNS, or request
/.well-known/caldavon the domain and follow the redirect. From a URL you typed, it starts there. - Find your principal. A
PROPFINDasking forcurrent-user-principalreturns the URL representing you as a user. On iCloud this comes back as a numeric path, which is why the URL you end up with looks nothing like the one you typed. - Find your calendar home. A
PROPFINDon the principal asking forcalendar-home-setreturns the collection that contains your calendars. - List the calendars. A depth-one
PROPFINDon the home set returns every child collection. The client keeps the ones whose resource type includes calendar and whose supported component set includesVEVENT, and discards task lists and address books. - Check what you can do. The
current-user-privilege-setproperty says whether you may only read the calendar or may also write to it. This is how a good client knows in advance that a subscribed read-only calendar cannot receive bookings, instead of failing later.
The whole exchange looks like this in outline:
PROPFIND /.well-known/caldav
<d:current-user-principal/>
-> /1234567890/principal/
PROPFIND /1234567890/principal/
<c:calendar-home-set/>
-> /1234567890/calendars/
PROPFIND /1234567890/calendars/ (Depth: 1)
<d:resourcetype/> <d:displayname/>
<c:supported-calendar-component-set/>
<cs:getctag/>
-> Work, Home, Bookings, Reminders (VTODO, ignored)
Connecting iCloud: App Specific Passwords
Your Apple ID password will not work, and this is the single most common iCloud connection failure. Apple requires two-factor authentication on Apple IDs, and third-party applications that cannot present a second factor must use an app-specific password instead.
To generate one, sign in at the Apple Account website, find the section for app-specific passwords under sign-in and security, create one, and give it a name you will recognise later such as "appntmnts booking sync". Apple shows the password once, in four groups of four lowercase letters. Copy it immediately.
Then, in the scheduling tool, enter your Apple ID email address as the username and that generated password as the password. Some clients want the password with the hyphens and some without, so if the first attempt is rejected, try the other form before assuming anything else is wrong.
Things to know about app-specific passwords:
- They are per-application. Revoking one stops that integration and leaves everything else working, which makes offboarding clean.
- They are invalidated when you change your Apple ID password. Every app-specific password on the account dies at once, so a password reset means reconnecting every integration.
- They cannot be viewed again after creation. If you lose it, revoke and generate a new one.
- They are not scoped to calendar. This is the honest downside, and it is covered below.
Fastmail and Nextcloud work the same way, with app passwords generated in their own settings, and Nextcloud app passwords can be revoked individually from the list of connected devices and sessions.
How Changes Are Detected Without Push
Google and Microsoft can call your server when something changes. CalDAV, in practice, cannot. There is a proprietary Apple push mechanism that Apple clients use, and an emerging push extension, but neither is something you can count on across servers. So CalDAV sync is polled.
Polling does not have to be expensive, because the protocol gives two cheap ways to ask "has anything changed?":
- A collection tag on the calendar, which changes whenever any event in it changes. One small request per calendar per poll tells the client whether to bother fetching anything.
- Collection synchronisation, defined in RFC 6578, where the server issues a sync token and a later request with that token returns only what has changed or been deleted since. This is the better mechanism where the server supports it, and support is common but not universal.
With either, a poll every few minutes costs very little. What you do not get is sub-second propagation. If you block out an hour in Apple Calendar on your phone and immediately reload your booking page, the slot may still be there for a few minutes. Plan around that: keep a minimum notice period so the nearest bookable slot is never within one polling interval, and make sure the tool rechecks availability at the moment of confirmation rather than trusting a cached view.
Where CalDAV Is Weaker Than Google And Microsoft
An honest comparison, because pretending otherwise leads to bad decisions.
| Google Calendar API | Microsoft Graph | CalDAV | |
|---|---|---|---|
| Credential | OAuth token, scoped | OAuth token, scoped | Password or app password |
| Change notification | Push, with polling fallback | Push subscriptions | Polling, with a change tag |
| Free/busy without event contents | Yes, a dedicated scope | Yes, availability query | Uneven server support |
| Revoke access for one app | Yes, in account settings | Yes, in account settings | Only where app passwords exist |
| Rooms and resources | Workspace resources | Room mailboxes and room lists | Not standardised |
| Works with any provider | No | No | Yes |
Beyond the table, three quieter differences:
Free/busy queries are inconsistent. The standard defines a free/busy report, but server support varies and many implementations expect you to read the events instead. In practice a CalDAV integration usually holds full event data, so the privacy-preserving option available on Google Calendar is not reliably available here.
Recurrence handling varies. Recurring events with modified single instances are represented consistently on paper, but servers differ in how they store and return the overrides. Test a recurring series before assuming it round-trips cleanly.
Rate limits are undocumented. Large providers throttle aggressive clients without telling you what the limit is. A sensible integration backs off rather than hammering.
Security: A Password Is Not A Scoped Token
With OAuth, you grant a narrow permission that you can revoke from your account settings, and the application never sees a password. With CalDAV, you hand over credentials that the application must store and replay on every request.
App-specific passwords narrow the blast radius considerably, and they are the reason iCloud, Fastmail and Nextcloud connections are acceptable in practice. If a server offers only your main account password, weigh that carefully, particularly if the same password also opens your email.
Whatever you connect, treat it like any other credential: use an app password if one is available, name it after the integration so you know what you are revoking, and revoke it the day you stop using the tool.
Setting It Up In appntmnts
appntmnts supports CalDAV as a first-class connection alongside Google and Microsoft 365, which means iCloud, Fastmail, Nextcloud and self-hosted servers get the same two-way behaviour: confirmed bookings are written to a calendar you choose, and existing events remove those times from your booking page. You enter a server address and credentials, appntmnts runs the discovery sequence, and you tick which of the discovered calendars count as busy.
Start on the integrations page for the current list of tested servers. If a connection refuses to authenticate, the app-specific password is the first thing to check, and the rest of the diagnostic order is in why calendar sync fails.