Skip to content
Skip to main content

Apple Contacts API: CardDAV, Contacts framework, REST

Last updated:

Two different things answer to the name “Apple Contacts API,” and neither is a web API. One is the Contacts framework, a Swift and Objective-C library that runs inside apps on Apple devices. The other is CardDAV, the protocol iCloud uses to store and sync address books. A server-side service that needs a user’s iCloud contacts can only use the second. This page explains both and shows how the Nylas Contacts API puts JSON endpoints in front of iCloud CardDAV.

Apple has no public REST API for contacts. It offers the Contacts framework for apps running on iPhone, iPad, Mac, Apple Watch, and Vision Pro, and iCloud stores contacts on a CardDAV server defined by RFC 6352, published in August 2011. Server-side code reaches iCloud contacts through CardDAV or through a service that wraps it.

The split matters when you plan an integration. If your product is an iOS or macOS app, the framework reads contacts on the user’s device. If your product is a web app, CRM, or scheduled server job, the device isn’t involved, and you need a direct connection to the user’s iCloud address book. Apple’s own developer documentation confirms the storage model: the CNContainerType.cardDAV container type describes contacts stored on a CardDAV server, with iCloud as the example.

The Contacts framework is Apple’s native library for reading and formatting the user’s contacts from Swift or Objective-C. It runs on the user’s device and exposes no network endpoint, so a server can’t call it. It has been available since iOS 9.0 and macOS 10.11, when it replaced Apple’s older Address Book framework.

Apple describes the framework as optimized for thread-safe, read-only usage, since most apps only read contacts. Its central type, CNContact, is an immutable value object with properties such as name, image, and phone numbers. Contacts live in containers, and the CNContainerType enum has 4 cases: local, exchange, cardDAV (with iCloud as Apple’s example), and unassigned.

None of that helps server-side code. To sync iCloud contacts into a web app without shipping an Apple-platform client, you connect to the iCloud CardDAV server using the RFC 6352 protocol from 2011, either yourself or through an API that does it for you.

CardDAV is an extension of WebDAV that stores each contact as a vCard resource on an HTTP server. RFC 6352, published in August 2011, requires servers to support vCard 3.0 and defines the addressbook-query and addressbook-multiget REPORT methods for searching and batch-fetching contacts. Requests and responses are XML, and each contact body is vCard text.

A working CardDAV client for iCloud has to discover the user’s address book collections, issue PROPFIND and REPORT requests, parse vCard records, and use ETag values for conditional writes so it doesn’t overwrite a change made on the user’s iPhone. Groups are their own vCard records, separate from the address-book containers, and the combined All Contacts view isn’t a group at all.

Authentication uses an app-specific password. Apple’s instructions name mail, contacts, and calendars as the iCloud data that third-party apps sign in to reach. The user’s account needs two-factor authentication, and Apple allows up to 25 active app-specific passwords. Changing the main Apple Account password revokes every one of them.

The Nylas Contacts API handles CardDAV discovery, vCard parsing, and conditional writes for native iCloud grants, and returns the same contact object it returns for Google, Microsoft, Yahoo, and Exchange. The table compares that with a direct CardDAV client. The API rejects any single vCard larger than 1 MB and any inventory response larger than 8 MB instead of parsing unbounded data.

TaskiCloud CardDAV (direct)Nylas Contacts API
Data formatXML requests, vCard 3.0 bodiesJSON contact objects
Listing contactsPROPFIND and REPORT against each collectionGET /v3/grants/{grant_id}/contacts, up to 200 per page
Writing contactsPUT a vCard with an If-Match ETagPOST, PUT, and DELETE on the Contacts endpoints
GroupsGroup vCard records you parse yourselfGET /v3/grants/{grant_id}/contacts/groups
IDsServer href pathsOpaque IDs starting with carddav_v1_
Change detectionYou poll and diffcontact.updated and contact.deleted notifications
Other providersiCloud onlyGoogle, Microsoft, Yahoo, iCloud, and Exchange

The notifications are polled, not real-time, and the first successful scan creates a silent baseline. Duplicates are possible, so keep handlers idempotent. The list iCloud contacts recipe covers delivery behavior in detail.

Listing iCloud contacts through Nylas takes 1 GET request to /v3/grants/{grant_id}/contacts with a native iCloud grant. Omitting the source parameter selects the CardDAV address_book source. The default page size is 30 contacts and the maximum is 200, with next_cursor passed back as page_token for the next page.

The grant must come from the iCloud connector. A generic hosted IMAP grant for an iCloud address doesn’t provide CardDAV contacts, even though it reads the same mailbox. The request below is the same one you’d send for any other provider:

What can you do with iCloud contacts through Nylas?

Section titled “What can you do with iCloud contacts through Nylas?”

A native iCloud grant supports list, get, create, update, and delete on contacts in the user’s iCloud address book. You can list explicit contact groups, filter contacts by group, and change membership through the contact’s groups field. Filters for email, phone_number, and group work, and each list response holds at most 200 contacts.

A few iCloud-specific limits apply:

  • You assign groups but can’t manage them. The API doesn’t create, rename, or delete group resources. Group IDs start with carddav_group_v1_.
  • Some fields aren’t writable. You can’t write manager_name, office_location, or profile pictures, and profile_picture=true isn’t supported.
  • IDs can change. A contact moved inside iCloud can get a new ID, so store the latest ID from every response.
  • Pagination is cursor-only. Offset pagination isn’t supported.
  • One source per request. source=domain and compound values such as source=address_book,inbox return an invalid request error.

The Contacts API guide covers create, update, metadata, and the full error contract across providers.