Apple iCloud service
The API supports retrieval of a variety of data and files from Apple's iCloud services.
Sessions
Setting up a session for the iCloud services on the API is as straightforward as a login into an iCloud account. The process can require multiple attempts at creating the session if the account has enabled multi-factor authentication, like 2FA or 2SV.
Creating a session for an account without 2FA/2SV
The session payload to create a session for an account without 2FA/2SV enabled contains the following parameters.
name | type | description |
---|---|---|
password |
string | The iCloud account password. |
Using cURL
curl https://ricloud-api.reincubate.com/sessions \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "source": { "user": "1", "type": "icloud.account", "identifier": "<iCloud account username>" }, "payload": { "password": "<iCloud account password>" } }'
Response
{ "id": "<session ID>", "resource": "session", ... "state": "succeeded", "error": null, ... }
Creating a session for an account with 2FA
Creating a session for a 2FA enabled account is a two step process:
- Attempt to create a session using just the iCloud account password. This will trigger the 2FA process, which sends an authentication code to iOS and macOS devices associated with the account. The session creation attempt will fail with
error="code-required"
. - Use the iCloud account password and the authentication code received in (1) to create a session. If the code is accepted, the session will be successfully created.
Step 1: create session
name | type | description |
---|---|---|
password |
string | The iCloud account password. |
Using cURL
curl https://ricloud-api.reincubate.com/sessions \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "source": { "user": "1", "type": "icloud.account", "identifier": "<iCloud account username>" }, "payload": { "password": "<iCloud account password>" } }'
Response
If the 2FA process is triggered as expected, the session should fail to be created with the error: code-required
.
{ "id": "<session ID>", "resource": "session", ... "state": "failed", "error": "code-required", ... }
Step 2: create session with code
name | type | description |
---|---|---|
password |
string | The iCloud account password. |
code |
string | The authentication code. |
Using cURL
curl https://ricloud-api.reincubate.com/sessions \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "source": { "user": "1", "type": "icloud.account", "identifier": "<iCloud account username>" }, "payload": { "password": "<iCloud account password>", "code": "<authentication code>" } }'
Response
{ "id": "<session ID>", "resource": "session", ... "state": "succeeded", "error": null, ... }
Creating a session for an account with 2SV
The process to create a session for a 2SV enabled account has three steps:
- Attempt to create a session using the iCloud account password. As 2SV is required, this will fail with
error="choice-required"
anderror_info={"choices": [<2SV enabled devices>]}
. - Attempt to create a session again using the iCloud account password and a choice from the
error_info["choices"]
list. This time, the attempt will trigger the 2SV process which sends an authentication code to the chosen device. The attempt will fail witherror="code-required"
. - Use the iCloud account password and the authentication code received in (2) to create a session. If the code is accepted, the session will be successfully created.
This will trigger the 2SV process, which sends an authentication code to iOS and macOS devices associated with the account. The session creation attempt will fail with error="code-required"
.
Step 1: create session
name | type | description |
---|---|---|
password |
string | The iCloud account password. |
Using cURL
curl https://ricloud-api.reincubate.com/sessions \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "source": { "user": "1", "type": "icloud.account", "identifier": "<iCloud account username>" }, "payload": { "password": "<iCloud account password>" } }'
Response
If 2SV is enabled on the account, the session creation attempt will fail with error choice-required
.
{ "id": "<session ID>", "resource": "session", ... "state": "failed", "error": "choice-required", "error_info": { "choices": [ "********02 - SMS to Phone Number" ] } ... }
Step 2: create session with choice
name | type | description |
---|---|---|
password |
string | The iCloud account password. |
choice |
string | The chosen device to send an authentication code to. |
Using cURL
curl https://ricloud-api.reincubate.com/sessions \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "source": { "user": "1", "type": "icloud.account", "identifier": "<iCloud account username>" }, "payload": { "password": "<iCloud account password>", "choice": "********02 - SMS to Phone Number" } }'
Response
If the 2FA process is triggered as expected, the session should fail to be created with the error: code-required
.
{ "id": "<session ID>", "resource": "session", ... "state": "failed", "error": "code-required", ... }
Step 3: create session with code
name | type | description |
---|---|---|
password |
string | The iCloud account password. |
code |
string | The authentication code. |
Using cURL
curl https://ricloud-api.reincubate.com/sessions \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "source": { "user": "1", "type": "icloud.account", "identifier": "<iCloud account username>" }, "payload": { "password": "<iCloud account password>", "code": "<authentication code>" } }'
Response
{ "id": "<session ID>", "resource": "session", ... "state": "succeeded", "error": null, ... }
Source types
identifier | description |
---|---|
icloud.account |
primary source Corresponds to an iCloud account. |
Polls
The iCloud service supports all the poll payload schema attributes.
Retrieving source info
This poll type retrieves information on the targeted source. The results are published in JSON format.
Using cURL
curl https://ricloud-api.reincubate.com/polls \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "session": "<session ID>", "payload": { "info_types": ["*"] } }'
Using *ricloud-py*
import ricloud # The ID of a session we made earlier. session_id = "<session ID>" poll = ricloud.Poll.create( session=session_id, payload={ "info_types": ["*"] } )
Retrieving data
This poll type retrieves and processes data from the targeted session. The results are published in JSON format.
See the list of available data types for more information on specific data types.
Using cURL
curl https://ricloud-api.reincubate.com/polls \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "session": "<session ID>", "payload": { "data_types": ["icpl.photos"] } }'
Using *ricloud-py*
import ricloud # The ID of a session we made earlier. session_id = "<session ID>" poll_payload = { "data_types": ["icpl.photos"] } poll = ricloud.Poll.create( session=session_id, payload=poll_payload, )
Retrieving files
The files
poll payload attribute is used to request the retrieval of binary files from the targeted source.
The IDs will typically be retrieved from a previous poll for data types that include direct file references, like iCloud Photo Library, or that include attachments, like message data types.
Using cURL
curl https://ricloud-api.reincubate.com/polls \ -X POST \ -H 'Authorization: Token <your key_token>' \ -H 'Content-Type: application/json' \ -d '{ "session": "<session ID>", "payload": { "files": [ "icpl://ATnrIxddlwbCEjN33NBq8zXQwYgE", "icpl://AbfMRXQ55H4WfS5YguuUWxir4hq6" ] } }'
Using *ricloud-py*
import ricloud # The ID of a session we made earlier. session_id = "<session ID>" poll_payload = { 'files': [ 'icpl://ATnrIxddlwbCEjN33NBq8zXQwYgE', 'icpl://AbfMRXQ55H4WfS5YguuUWxir4hq6', ] } poll = ricloud.Poll.create( session=session_id, payload=poll_payload, )
Data types
iCloud data types
identifier | description |
---|---|
icpl.photos |
Retrieves iCloud Photo Library assets. |
mme_contacts.contacts |
Retrieves iCloud stored iOS Contacts data. |
mme_calendar.events |
Retrieves iCloud stored iOS Calendar data. |
mme_notes.notes |
Retrieves iCloud stored iOS Notes data. |
callkit.calls |
Retrieves CallKit synced iOS Phone data. |
cloudkit_safari.history |
Retrieve iCloud stored Safari browser history data. |
fmip.devices |
Retrieve Find My iPhone device and locations data. |
iCloud Photo Library
Photos, videos and other media
Retrieves information on photos, videos and other media stored in iCloud Photo Library (ICPL).
This module requires that iCloud Photo Library is enabled on the user's iCloud account.
Data type ID | icpl.photos |
Associated setting | Settings > [username] > iCloud > Photos > iCloud Photo Library |
Data attributes
name | type | description |
---|---|---|
id |
string | An identifier for the data item. Useful for deduplicating data across multiple polls. |
filename |
string | The name of the file as it is stored in ICPL. |
files |
list of image , video , audio items |
Files associated with this ICPL asset. The original file, Live Photos, thumbnails will be included in this list. |
date_created |
datetime | When the file was originally created. In the case of photos or videos taken on an iOS device, this will be the date when they were taken. In the case of existing assets imported to ICPL, this will be the original import date. |
date_uploaded |
datetime | When the file was last uploaded to ICPL. This will correspond to when the file was first retrievable via the ricloud API. |
local_date_created |
optional datetime | When the asset was originally created, in local time. This attribute is only populated if sufficient metadata is stored with the asset in ICPL, and is currently supported for parsing by the API. The value of this attribute can vary by a few seconds from that of date_created , as the two are determined from different sources. |
Data filters
name | type | description |
---|---|---|
since |
datetime | Only includes items with a date_uploaded later than the provided value. |
until |
datetime | Only includes items with a date_uploaded earlier than the provided value. |
Sample data
[ { "id": "7f1384f5038255f5", "data_type": "icpl.asset", "filename": "IMG_0002.HEIC", "files": [ { "id": "icpl://AWo/lDeN8fEExAUJajRHzVx2j605", "data_type": "image", "extension": "heic", "size": 905818, "width": 4032, "height": 3024 }, { "id": "icpl://ASDPdJ/LvFWjsBy4YOOp7B5c+XOi", "data_type": "video", "extension": "mov", "size": 2456163, "width": 980, "height": 1308 }, { "id": "icpl://ASAwWOvwrvAUuO71uXcU6mm+nMU4", "data_type": "image", "extension": "jpg", "size": 595624, "width": 1536, "height": 2048 }, { "id": "icpl://ATy/qmemCas1jzYWuhR4mQywhpzz", "data_type": "image", "extension": "jpg", "size": 65407, "width": 360, "height": 480 } ], "date_created": "2020-09-18T12:32:17Z", "date_uploaded": "2020-09-18T12:41:19Z", "local_date_created": "2020-09-18T13:32:17+01:00" } ]
MobileMe Contacts
Contacts
Retrieves iOS Contacts data stored in iCloud.
Data type ID | mme_contacts.contacts |
Associated setting | Settings > [username] > iCloud > Contacts |
Data attributes
The mme_contacts.contact
data type inherits most attributes from the base contact
data type. The table below outlines additional or differing attributes.
name | type | description |
---|---|---|
id |
string | An identifier for the data item. Useful for deduplicating data across multiple polls. |
data_type |
string, always mme_contacts.contact |
The data type of the item. |
uid |
string | A unique identifier that can be used to deduplicate across different sources of iOS Contacts data. |
image |
nested image item, optional |
Profile image for the contact. |
Sample data
[ { "id": "2cf6a837304d6614", "data_type": "mme_contacts.contact", "uid": "NzNlNjkxYjctOTBmYi00MTYxLWI5YzYtZTk0ZDlhZjljMmE5", "first_name": "John", "middle_name": "'Gala'", "last_name": "Appleseed", "prefix": "Mr.", "suffix": "Jr.", "nickname": "John'o", "records": [ { "type": "Phone", "name": "MAIN", "value": "1-800-MY-APPLE" }, { "type": "Phone", "name": "UK", "value": "0800 039 1010" }, { "type": "URL", "name": "HOMEPAGE", "value": "http://www.apple.com" }, { "type": "URL", "name": "HOMEPAGE", "value": "http://www.apple.com/uk/" }, { "City": "Cupertino", "State": "CA", "ZIP": "95014", "name": "WORK", "CountryCode": "US", "Country": "United States", "Street": "1 Infinite Loop", "type": "Address", "SubLocality": null, "Municipality": null } ], "organisation": "Apple Inc.", "department": "Marketing", "jobtitle": "VP Coring", "birthday": "1976-04-01", "image": { "id": "mme_contact_image://2cf6a837304d6614", "data_type": "image", "extension": "jpg" } } ]
MobileMe Calendar events mme_calendar.events
Retrieves iCloud stored iOS Calendar data.
MobileMe Notes notes mme_notes.notes
Retrieves iCloud stored iOS Notes data.
CallKit
Calls from CallKit callkit.calls
Retrieves call logs synced with the CallKit service.
Errors
callkit-uninitialised
Indicates that the CallKit service has not been setup for this account. The iCloud account owner can resolve this error using an iOS device associated with the iCloud account via the following steps:
- Make sure the device is connected to Wi-Fi.
- Navigate to Settings > [username] > iCloud
.
- Turn off iCloud Drive, waiting for 30 to 60 seconds for the change to take effect.
- Turn on iCloud Drive once the previous change has completed. This should trigger initialisation.
If the error persists after performing this process, please contact support.
callkit-sync-disabled
In this case, the CallKit service has been initialised but the conditions necessary for devices to start syncing call history to the iCloud have not been met. The API will remotely resolve this via the iCloud, but device associated with the iCloud account may not re-evaluate their sync state as this is cached.
The iCloud account owner can trigger a device to re-check call history sync conditions via the following steps:
- Navigate to
Settings > [username] > iCloud
. - Turn off iCloud Drive, waiting for 30 to 60 seconds for the change to take effect.
- Turn on iCloud Drive once the previous change has completed. This should trigger initialisation.
Troubleshooting
- Recent call history is not getting returned in poll results.
This is typically caused by the device not having synced its latest call history records with the iCloud. The CallKit service is an internal iOS service and cannot be turned on or off in the settings or triggered to sync manually. This can make it difficult to debug missing data as it unclear what the device has or has not synced to the iCloud.
This issue is more common for accounts which do not have much data to sync (less than ~3 calls), which can often be the case for testing accounts.
Recommendations:
- Make sure the device has more than a handful of call history records to sync. Our testing has shown that a device with only a couple of call history records will not trigger the iCloud syncing process.
- Wait for the device to perform a periodic sync. This can take up to 12 hours depending on how the device is being used, its connectivity state and its charge state.
-
Plug the device into power. The device is more likely to trigger a sync when in this state.
-
Old call history is not getting returned in poll results.
The CallKit service is designed for syncing call history records between devices and not for storing these records indefinitely. Typically, call history records will be retrievable from CallKit for about 3 months, but this may vary between accounts depending on internal cleanup processes in the iCloud.
CloudKit
Browser history from iCloud cloudkit_safari.history
Retrieve Safari browser history data stored in the iCloud sync service.
Find My and Find My iPhone
Device locations
Retrieve Find My device and location data.
Note that this data type may require multiple polls, with the second coming ~10-30 seconds after the first, in order to return complete data. This is due to how Find My operates: the first poll will trigger Find My to request new data from reachable devices but the data will not be available for another 10-30 seconds.
Data type ID | fmip.devices |
Associated setting | Settings > [username] > Find My |
Data attributes
name | type | description |
---|---|---|
id |
string | An identifier for the data item. Useful for deduplicating data across multiple polls. |
data_type |
string, always fmip.devices |
The data type of the item. |
name |
string | The user set name for the device. |
model_name |
string | Apple's marketing name for the device model. |
model_identifier |
string | Apple's identifier for the device model. |
product_type |
string | The product category of the device. |
location |
optional nested location |
The last reported location for the device, if one is available. |
battery_status |
string | The current battery status of the device. |
battery_level |
float | If known, the percentage battery charge remaining. |
Sample data
[ { "id": "e7694d7a0d2ab6cf", "data_type": "fmip.device", "name": "John's iMac", "model_name": "iMac with Retina 5K display", "model_identifier": "iMac15,1", "product_type": "iMac", "location": null, "battery_status": "Unknown", "battery_level": 0.0 }, { "id": "4d86a6181808d152", "data_type": "fmip.device", "name": "John's iPhone 11", "model_name": "iPhone 11", "model_identifier": "iPhone6,2", "product_type": "iPhone", "location": { "data_type": "location", "latitude": 51.507452392689146, "longitude": -0.07398372304584414, "altitude": 0.0, "horizontal_accuracy": 65.0, "vertical_accuracy": 0.0, "positioning_type": "Wifi", "date_created": "2020-01-01T00:00:00.000000Z" }, "battery_status": "Unknown", "battery_level": 0.0 } ]
File types
identifier | description |
---|---|
icpl |
A file from iCloud Photo Library. |
mme_contact_image |
An mme_contacts.contacts contact profile image. |