Skip to Content
Developer APICalendar & Contacts

Calendar & Contacts

EUnifyer supports both standards-based protocols (CalDAV, CardDAV) and a REST API for calendar and contacts access. For external integrations, the standards-based path is recommended — it works with any compatible client out of the box.


Which path to use

Use caseRecommended
Connect Apple Calendar, Thunderbird, GNOME CalendarCalDAV
Connect Apple Contacts, Thunderbird, GNOME ContactsCardDAV
Build a server-side integration or sync jobCalDAV / CardDAV or REST
Mobile app syncing calendars/contactsCalDAV / CardDAV
REST programmatic access (events, contacts)REST API

CalDAV (Calendar)

Endpoint base: https://api.eunifyer.com/caldav/
Standard: RFC 4791 (CalDAV) + RFC 6638 (scheduling extensions)
Auth: HTTP Basic (username:password) or Authorization: Bearer <token>
Service discovery: https://api.eunifyer.com/.well-known/caldav (RFC 6764)

Connect a calendar client

Give users this URL for calendar client setup:

https://api.eunifyer.com/caldav/

Most clients (Apple Calendar, Thunderbird, GNOME Calendar) auto-configure from the well-known URL. After discovery, the client reads user calendars via PROPFIND and syncs events via REPORT.

Programmatic CalDAV access

Read events in a date range:

curl -X REPORT "https://api.eunifyer.com/caldav/{username}/{calendar-uid}/" \ -u "username:password" \ -H "Content-Type: application/xml; charset=utf-8" \ -H "Depth: 1" \ -d '<?xml version="1.0" encoding="utf-8"?> <C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"> <D:prop><D:getetag/><C:calendar-data/></D:prop> <C:filter> <C:comp-filter name="VCALENDAR"> <C:comp-filter name="VEVENT"> <C:time-range start="20260401T000000Z" end="20260430T235959Z"/> </C:comp-filter> </C:comp-filter> </C:filter> </C:calendar-query>'

Create or update an event:

curl -X PUT "https://api.eunifyer.com/caldav/{username}/{calendar-uid}/{event-uid}.ics" \ -u "username:password" \ -H "Content-Type: text/calendar; charset=utf-8" \ -d 'BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Example//EN BEGIN:VEVENT UID:event-uid@example.com DTSTART:20260420T100000Z DTEND:20260420T110000Z SUMMARY:Team standup END:VEVENT END:VCALENDAR'

Delete an event:

curl -X DELETE "https://api.eunifyer.com/caldav/{username}/{calendar-uid}/{event-uid}.ics" \ -u "username:password"

REST Calendar API

Base path: /api/v1/calendar/
Auth: Bearer token (PAT, Keycloak JWT)
Scopes: calendar:read (read), calendar:write (create/update/delete)

Endpoints

GET /api/v1/calendar/calendars → list of CalendarInfo GET /api/v1/calendar/events?start=…&end=… → events across all calendars GET /api/v1/calendar/calendars/{cal_id}/events → events in one calendar GET /api/v1/calendar/calendars/{cal_id}/events/{uid} → single event POST /api/v1/calendar/calendars/{cal_id}/events → create event PUT /api/v1/calendar/calendars/{cal_id}/events/{uid} → replace event DELETE /api/v1/calendar/calendars/{cal_id}/events/{uid} → delete event POST /api/v1/calendar/freebusy → free/busy query POST /api/v1/calendar/calendars/{cal_id}/import → import ICS file GET /api/v1/calendar/calendars/{cal_id}/export.ics → export calendar as ICS

Example — list upcoming events

curl "https://api.eunifyer.com/api/v1/calendar/events?start=2026-04-01T00:00:00Z&end=2026-04-30T23:59:59Z" \ -H "Authorization: Bearer $TOKEN"

Example — create an event

curl -X POST https://api.eunifyer.com/api/v1/calendar/calendars/$CAL_ID/events \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "Quarterly review", "start": "2026-04-20T09:00:00Z", "end": "2026-04-20T10:00:00Z", "description": "Q1 results discussion", "attendees": ["alice@example.com", "bob@example.com"] }'

Import and export

# Import ICS file curl -X POST https://api.eunifyer.com/api/v1/calendar/calendars/$CAL_ID/import \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: text/calendar" \ --data-binary @events.ics # Export as ICS curl https://api.eunifyer.com/api/v1/calendar/calendars/$CAL_ID/export.ics \ -H "Authorization: Bearer $TOKEN" \ -o calendar.ics

CardDAV (Contacts)

Endpoint base: https://api.eunifyer.com/carddav/
Standard: RFC 6352 (CardDAV)
Auth: HTTP Basic or Authorization: Bearer <token>
Service discovery: https://api.eunifyer.com/.well-known/carddav
ETag support: Active — use If-Match for safe updates

Connect a contacts client

Give users this URL for contacts client setup:

https://api.eunifyer.com/carddav/

Clients (Apple Contacts, Thunderbird, GNOME Contacts) auto-configure from the well-known URL.

Programmatic CardDAV access

List contacts in an address book:

curl -X REPORT "https://api.eunifyer.com/carddav/{username}/{book-uid}/" \ -u "username:password" \ -H "Content-Type: application/xml; charset=utf-8" \ -H "Depth: 1" \ -d '<?xml version="1.0" encoding="utf-8"?> <C:addressbook-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav"> <D:prop><D:getetag/><C:address-data/></D:prop> </C:addressbook-query>'

Create or update a contact (VCard):

curl -X PUT "https://api.eunifyer.com/carddav/{username}/{book-uid}/{contact-uid}.vcf" \ -u "username:password" \ -H "Content-Type: text/vcard; charset=utf-8" \ -d 'BEGIN:VCARD VERSION:3.0 UID:contact-uid@example.com FN:Alice Chen N:Chen;Alice;;; EMAIL:alice@example.com TEL:+1-555-0100 END:VCARD'

REST Contacts API

Base path: /api/v1/contacts/
Auth: Bearer token
Scopes: contacts:read / contacts:write

Endpoints

GET /api/v1/contacts/books → list of AddressBook GET /api/v1/contacts/books/{book_id} → list of ContactSummary GET /api/v1/contacts/books/{book_id}/{contact_id} → ContactDetail POST /api/v1/contacts/books/{book_id} → create contact PUT /api/v1/contacts/books/{book_id}/{contact_id} → replace contact DELETE /api/v1/contacts/books/{book_id}/{contact_id} → delete contact GET /api/v1/contacts/search?q=… → search contacts GET /api/v1/contacts/directory → organisation directory

Example — search contacts

curl "https://api.eunifyer.com/api/v1/contacts/search?q=alice" \ -H "Authorization: Bearer $TOKEN"

Webhook events

EventFires when
calendar.event.createdA calendar event is created
calendar.event.updatedA calendar event (or single occurrence) is updated

Subscribe via the Webhooks API to receive real-time notifications.