http://sabre.io/dav/building-a-caldav-client/ 0. Discovery PROPFIND / HTTP/1.1 Depth: 0 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 Success: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 / /principals/users/johndoe/ HTTP/1.1 200 OK Get calendar home: PROPFIND /principals/users/johndoe/ HTTP/1.1 Depth: 0 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 Success: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 /principals/users/johndoe/ /calendars/johndoe/ HTTP/1.1 200 OK Get all calendars: PROPFIND /calendars/johndoe/ HTTP/1.1 Depth: 1 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 Success: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 /calendars/johndoe/ HTTP/1.1 200 OK /calendars/johndoe/home/ Home calendar 3145 HTTP/1.1 200 OK /calendars/johndoe/tasks/ My TODO list 3345 HTTP/1.1 200 OK 1. Get display name and ctag PROPFIND /calendars/johndoe/home/ HTTP/1.1 Depth: 0 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 Success: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 /calendars/johndoe/home/ Home calendar 3145 HTTP/1.1 200 OK Failure: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 /calendars/johndoe/home/ HTTP/1.1 403 Forbidden 2. Save display name and ctag (if ctag changes the calendar has changes) 3. Download objects REPORT /calendars/johndoe/home/ HTTP/1.1 Depth: 1 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 Success: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 /calendars/johndoe/home/132456762153245.ics "2134-314" BEGIN:VCALENDAR VERSION:2.0 CALSCALE:GREGORIAN BEGIN:VTODO UID:132456762153245 SUMMARY:Do the dishes DUE:20121028T115600Z END:VTODO END:VCALENDAR HTTP/1.1 200 OK /calendars/johndoe/home/132456-34365.ics "5467-323" BEGIN:VCALENDAR VERSION:2.0 CALSCALE:GREGORIAN BEGIN:VEVENT UID:132456-34365 SUMMARY:Weekly meeting DTSTART:20120101T120000 DURATION:PT1H RRULE:FREQ=WEEKLY END:VEVENT END:VCALENDAR HTTP/1.1 200 OK For each object get: - Calendar data - url - etag 4. Check for changes - Fetch ctag -> see 1. - If ctag is changes fetch all etags REPORT /calendars/johndoe/home/ HTTP/1.1 Depth: 1 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 Success: HTTP/1.1 207 Multi-status Content-Type: application/xml; charset=utf-8 /calendars/johndoe/home/132456762153245.ics "xxxx-xxx" HTTP/1.1 200 OK /calendars/johndoe/home/fancy-caldav-client-1234253678.ics "5-12" HTTP/1.1 200 OK Compare local url's to request: if match compare etag. if etag compares continue else update. delete each local url not found fetch every url not found local update/fetch: REPORT /calendars/johndoe/home/ HTTP/1.1 Depth: 1 Prefer: return-minimal Content-Type: application/xml; charset=utf-8 /calendars/johndoe/home/132456762153245.ics /calendars/johndoe/home/fancy-caldav-client-1234253678.ics 5. Updating objects If-Match contains etag to update and You must not change the UID of the original object PUT /calendars/johndoe/home/132456762153245.ics HTTP/1.1 Content-Type: text/calendar; charset=utf-8 If-Match: "2134-314" BEGIN:VCALENDAR .... END:VCALENDAR Success: HTTP/1.1 204 No Content ETag: "2134-315" If no etag is returned make an immediate GET to get etag 6. Create an object PUT /calendars/johndoe/home/somerandomstring.ics HTTP/1.1 Content-Type: text/calendar; charset=utf-8 BEGIN:VCALENDAR .... END:VCALENDAR Success: HTTP/1.1 201 Created ETag: "21345-324" 7. Deleting an object DELETE /calendars/johndoe/home/132456762153245.ics HTTP/1.1 If-Match: "2134-314"