iCloud API

This documentation covers use of Reincubate’s legacy iCloud API. All of the same functionality is available through the latest release of ricloud.

Note

Whilst the legacy API is deprecated, it is still supported through an emulation layer which transforms output from the latest version into the older method calls and responses. This allows for clients running earlier integrations to continue to enjoy the old API whilst getting some of the benefits of the newer version.

Warning

Unless there is a specific reason to implement against the legacy iCloud API emulation layer, clients exploring a future integration would do well to examine the latest documentation.

Overview

The API – and in particular, the feeds – provide a number of substantial benefits:

  • Ease of integration. The API is easy for development teams at any level to work with, and they remove the need for clients to have any highly specialist knowledge about either iCloud / CloudKit storage, or about any third-party apps.

    This benefit is not easily overstated: the complexity of developing and maintaining an interface to the iCloud is substantial, and layered on top of that is the need to support multiple data formats for core iOS data and app files. Not only does iOS use different data formats, but each app (for instance, WhatsApp), uses a set of data formats and structures which can change week-to-week with app updates.

    The API supports all the “difficult” features: iOS 9, iOS 10, CloudKit, iCloud 8 + 9 merging, 2SV/2FA, partial snapshots, tokenisation, A9 & A9X.

  • Future proofing. Reincubate is committed to maintaining support for contemporary and past iCloud and iOS data formats, and has a solid track record in this space:

    • 1st to support iOS data access (2008)
    • 1st to support encrypted iOS data access (2009)
    • 1st to support iCloud data extraction (2011)
    • 1st & only with an API to support iCloud / CloudKit iOS 9 data access (2015)
  • Support & access to unrivalled expertise. As a consequence of the company’s focus and positioning as the app data company, Reincubate’s team have unrivalled experience and knowledge in the field. This experience is particularly valuable for clients exploring new apps and use-cases.

    Users of the JSON feeds are able to take advantage of Reincubate’s proprietary techniques in extraction and undeletion of app data, such that the resultant data is more accurate.

  • Out of the box app support. Aside from the core iOS datatypes – all of which are supported across all iOS versions on all devices – the API has modules to support dozens of third-party apps. Some of the more popular supported apps include WhatsApp, Viber, Kik, WeChat, Line, SnapChat, Facebook Messenger and Skype.

  • Out of the box developer platform support. The API has open source client implementations available in a number of languages, including Python, .NET / C# and JavaScript.

  • Speed & scalability. The Reincubate iCloud API platform is built to scale, and the JSON feed system faster and scales better than raw file access.

  • Rich feed customisation options. The feed platform is readily customisable for partner deployments. Examples include protobuf format feeds and aggregation of messaging app attachments.

  • Trust. Reincubate are trusted by security, LEA and government users around the world. The company is subject to stringent UK data protection legislation, and is compliant with EU and US Safe Harbor regulations.

Getting started

Interested parties can contact the enterprise team for access to an API key. However, a test key is provided in all of the sample client implementations.

Note

The test key user value is 120455 and the key value is 1413537101. This key will only permit access to listing installed apps, and is rate-limited.

Installing the sample Python client

The Python iCloud library can be installed with a single command. In order to get the legacy library, the latest 1.* version must be installed.

$ pip install ricloud==1.*

Source for this client can be found on GitHub under ricloud-py.

Installing the sample JavaScript client

The JavaScript iCloud library can be installed with a single command. In order to get the legacy library, the latest 1.* version must be installed.

$ npm install ricloud==1.*

Source for this client can be found on GitHub under ricloud-js.

Installing the sample .NET / C# client

The C# iCloud library can be installed with a single command. In order to get the legacy library, the latest 1.* version must be installed.

$ nuget install ricloud==1.*

Source for this client can be found on GitHub under ricloud-csharp.

Configuration

Each client implementation comes with its own set of bundled documentation, and a sample script which shows how it can be used. Configuration is usually limited to specifying a user and key value for authentication against the API.

Working with the API

Note

Note that the sample client implementations handle much of the complexity shown below, without the developer needing to get involved. The curl methods below are shown for developers who wish to dig into the fundamentals of the API, or to build their own native clients.

There are three core operations that a user may need to perform with the API.

  • Authentication and enumeration: sign-in, perform-2fa-challenge, submit-2fa-challenge
  • Feed data access: download-data
  • Raw file access: download-file

Note

Some clients may have access to additional methods and endpoints as part of their deployment.

Examples in this section are given in curl format.

On all requests made to the API, curl must be told to follow redirects with the -L parameter. The user’s API credentials must also be set with --user "USER:KEY", as must the custom API version header, --header "Accept: application/vnd.icloud-api.v1". So all curl calls in these examples must start with:

curl -L
     -v
     -X POST
     --user "USER:KEY"
     --header "Accept: application/vnd.icloud-api.v1"

Note that the -X POST option is also specified, as all the requests are made through POST. As this call isn’t going to change, it is referred to below as CURL_CALL.

Note

Depending on the nature of a client’s API implementation, it may be necessary to respect a concurrency limit across different types of requests to the API.

As a general guideline, all requests (except errors) return a session_key field which identifies the current session. If it isn’t sent, a sign-in request should be used to generate a new session. session_key values should be used consistently.

Note

Once a session_key has been obtained, it will be reliably valid for at least 30 minutes between calls.

1. Authentication, 2FA/2SV and retrieval of device & data list

In order to sign in as a user with two-factor authentication or two step verification enabled on his account, the sign-in method must be used.

CURL_CALL --data-urlencode "email=ICLOUD_EMAIL"
          --data-urlencode "password=ICLOUD_PASSWORD"
          https://api.icloudextractor.com/c/sign-in/

The email and password of the iCloud account to access are passed as parameters, using --data-urlencode to ensure that control characters such as @ are escaped.

Signing in with an invalid API keypair

If a user makes a request of the API with an invalid keypair, it will return no data beyond a 403.

HTTP/1.1 403 FORBIDDEN

Signing in to an account where the end-user has not accepted iCloud T&Cs

If the user attempts to sign in to an iCloud account for which an updated set of iCloud terms and conditions haven’t been accepted.

HTTP/1.1 400 BAD REQUEST
{
 "error": "terms-of-service-update",
 "message": "User hasn't agreed to Apple's Terms of Service."
}

Signing in with bad iCloud credentials

If a user attempts to sign in with bad iCloud credentials, a 403 will be returned along with an error message.

HTTP/1.1 403 FORBIDDEN
{"message": "Unsuccessful login attempt: renate@reincubate.com",
 "error": "unable-to-login"}

Signing in to an account which the end-user has not validated

If the user attempts to sign in to an iCloud account for which the primary email hasn’t been validated by the user.

HTTP/1.1 400 BAD REQUEST
{
 "error": "unverified-account",
 "message": "User's primary email hasn't been verified."
}

Signing in without 2FA/2SV

Signing in on a non-2FA account can be done with a single request.

HTTP/1.1 200 OK
{"devices":
 {"7c7fba66680ef796b916b067077cc246adacf01d": {
    "ios_version":   "9.0.1",
    "colour":        "#e4e7e8",
    "device_name":   "Renate's iPhone",
    "latest-backup": "2015-11-17 16:46:39.000000",
    "model":         "N71mAP",
    "serial":        "D56DF63DYTBG",
    "name":          "iPhone 6s"},
 "8e281be6657d4523710d96341b6f86ba89b56df7": {
    "ios_version":   "9.1",
    "colour":        "#e1e4e3",
    "device_name":    "Renate's iPad",
    "latest-backup": "2015-11-13 19:35:52.000000",
    "model":         "J98aAP",
    "serial":        "E32VR64AFXVF",
    "name":          "iPad Pro"},
 },
 "key": "b3d11d6c-52c0-4754-a971-8f305047a0f6",
 "auth_token": "N28GZaKvTXAGrhBIx3UgRGml47oPVCCq4tqM5huyCKo2r7h2HfMtyBsZVc3SS2sh5h3I"}
}

Signing in with 2SV/2FA

If the account was secured with two-factor authentication, the sign-in the request will return a error message stating that two-factor authentication is enabled on this account, the session_key and, in the case of 2SV, also a list of trustedDevices.

  • 2SV
HTTP/1.1 409 CONFLICT
{"message": "This account has Two Step Verification enabled, please select a device to challenge.",
 "data": {
  "trustedDevices": ["********12", "Renate's iPhone - iPhone 6s"],
  "key": "b3d11d6c-52c0-4726-a971-8f305047a0f6"
 },
 "error": "2fa-required"
}

For 2SV, The next step is to issue a 2SV challenge code to one of the trustedDevices. To do this a request is made to perform-2fa-challenge.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "challenge=DEVICE_TO_CHALLENGE"
          https://api.icloudextractor.com/c/perform-2fa-challenge/

The parameters that sent are challenge, which must contain on the items listed on trustedDevices, and the session_key, which will be the same as the sign-in request returned.

  • 2FA

In the case of 2FA, the difference is that the request will return an empty trustedDevices list.

HTTP/1.1 409 CONFLICT
{"message": "This account has Two Factor authentication enabled, all devices will be challenged.",
 "data": {
  "trustedDevices": ["Challenge all 2FA devices"],
  "key": "b3d11d6c-52c0-4726-a971-8f305047a0f6"
 },
 "error": "2fa-required"
}

For 2FA, we don’t get to choose which device is challenged, as every trusted device will automatically be challenged. To do this a request is made to perform-2fa-challenge, without the challenge argument.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode
          https://api.icloudextractor.com/c/perform-2fa-challenge/

Therefore, for 2FA the only parameters that is sent is the session_key, which will be the same as the sign-in request returned.

Challenging with a bad device (2FA/2SV)

If a user makes a request of the API with an invalid device, it will return no data beyond a 500.

HTTP/1.1 500 INTERNAL SERVER ERROR

Challenging with a bad key (2FA/2SV)

If a user makes a request of the API with an invalid key, it will return a 403 with a validation message.

HTTP/1.1 400 BAD REQUEST
{"message": "Your iCloud session has expired. To continue, please sign in again.",
 "error": "key-invalid"}

Challenging successfully (2FA/2SV)

HTTP/1.1 200 OK
{"message": "Challenge has been submitted."}

Once the challenge has been sent to the user’s device, the data sent must be relayed back to the API using submit-2fa-challenge.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "code=2FA_CODE"
          https://api.icloudextractor.com/c/submit-2fa-challenge/

Submitting a bad challenge response (2FA/2SV)

HTTP/1.1 403 FORBIDDEN
{"message": "Incorrect code supplied for Two Factor Authentication.",
 "error": "invalid-2fa-code"}

Submitting the right challenge response (2FA/2SV)

HTTP/1.1 200 OK
{"message": "Challenge has been submitted."}

With this request, the user will be fully authenticated and the API session will be active.

To complete the login process and retrieve the device list, submit a final request to sign-in using the same email and password as the first request and using the same key used through the 2FA/2SV authentication process.

Note, the response will only contain the auth_token entry if your API key has tokenisation enabled. In this case we recommend you submit the final request to refresh-session as outlined in Section 4 below, instead of submitting it to sign-in. Using the auth_token is more robust as it is an indicator of an already established session on Apple’s systems.

On the new API backend adaptor you should expect to see a different response. This is due to optimisations in the flow of the 2FA/2SV process.

HTTP/1.1 200 OK
{"key": "b3d11d6c-52c0-4726-a971-8f305047a0f6",
"message": "Log-in successful",
"auth_token": "N28GZaKvTXAGrhBIx3UgRGml47oPVCCq4tqM5huyCKo2r7h2HfMtyBsZVc3SS2sh5h3I"
}

2. Retrieval of feed data: download-data

The download-data method is used to access feed data.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "device=DEVICE_ID"
          --data-urlencode "mask=DATA_MASK"
          --data-urlencode "since=MIN_DATE"
          https://api.icloudextractor.com/c/download-data/

The parameters needed for this request are the current session_key, the device_id of one of the devices from the login response, and the data_mask, which is an OR combination of all the feed module flags the user is interested in. You can also specify a since date from which to start looking for data.

Note

The API consistently uses dates in the ISO-8601 format, in the UTC timezone. For example, 24th December would be expressed as 2014-12-24 17:30:00.000000.

Assuming the client’s API key is valid for all of these modules, the method will return the requested data in JSON format.

Note

See the section below for documentation on and examples of the JSON formats.

Submitting a valid feed request

If the values passed to the method are valid, it will return the feed content in the HTTP response body.

HTTP/1.1 200 OK

Submitting a feed request with missing parameters

If one of the required parameters is missing, the method will return a bad request response code.

HTTP/1.1 400 BAD REQUEST
{"message": "mask missing from post.",
 "error": "invalid-request"
}

Submitting a feed request with invalid parameters

If an invalid or misformatted value is submitted for any parameter, the method will return a bad request response code.

HTTP/1.1 400 BAD REQUEST
{"message": "Invalid since.",
 "error": "invalid-parameter"
}

Sample feed module flags

The following module flags can be masked together for the mask parameter of the download-data method. This is not an exhaustive list.

  • 0000001 Messages
  • 0000002 Photos and videos
  • 0000004 Browser history
  • 0000008 Call history
  • 0000016 Contacts
  • 0000032 Installed apps
  • 0000064 Contacts (live)
  • 0000128 Photos and videos (live)
  • 0000256 Location (live)
  • 0000512 WhatsApp messages
  • 0001024 Skype messages
  • 0002048 Calendar
  • 0004096 Line messages
  • 0008192 Kik messages
  • 0016384 Viber messages
  • 0032768 Facebook messages
  • 0065536 WeChat messages
  • 0131072 Snapchat messages
  • 0262144 File list
  • 0524288 Browser history (live)
  • 1048576 WhatsApp call history
  • 2097152 Viber call history
  • 4194304 App usage
  • 8388608 Notes

Note

The feed modules marked as live above are real-time datasets. The other data is point-in-time from backup data. Access to the live feed modules can trigger an email being sent to the account’s owner.

For instance, to request a feed of messages, call history and browser history, the mask would be 1 + 4 + 8 = 13.

JSON feed formats

The JSON feeds are designed to be as simple to parse as possible. The feed will return all of the data types requested within a single response.

Each feed module specified in the module flag will have its own key in the top level JSON dictionary that is returned.

{
    "first_module_name": "Module's data",
    "second_module_name": "Module's data",
    "etc.": "etc."
}

Note

Further module documentation and sample JSON is available from Apple iCloud service actions.

3. Retrieval of raw files: download-file

The download-file method is available for downloading message attachments, or directly downloading more esoteric files from the iCloud.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "device=DEVICE_ID"
          --data-urlencode "file=FILE_ID"
          https://api.icloudextractor.com/c/download-file/
          -o PATH_TO_SAVE_FILE

The parameters needed are the session_key, the target device_id, and a file_id. The request above will download the file and store it the path specified to curl with the -o option.

file_ids are either stored files in iCloud, or identifiers for hosted files on the internet. In the former case, file_ids are built from SHA-1 hashes of a file’s AppDomain and filename. In the latter case we may process and decrypt the file before returning it.

file_ids may be previously known for static files, or can be obtained from message feeds, where they are used as identifiers by attachments.

Note

As noted above, it is invariably better to use the JSON feeds when working with app data. The JSON feeds provide faster and more accurate data access.

Submitting a valid file request

If the values passed to the method are valid, it will return the binary file content in the HTTP response body.

HTTP/1.1 200 OK

Submitting a file request for a non-existent file

If a file is not present on the iCloud, or we cannot retrieve it from the appropriate third-party, the method will still return successfully, however the message body will be empty.

HTTP/1.1 200 OK

Submitting a file request after the session has expired

If the session has expired, clients will be served a bad request response code.

HTTP/1.1 400 BAD REQUEST
{"message": "Your iCloud session has expired. To continue, please sign in again.",
 "error": "key-invalid"}

Sample file_ids

Common hash keys associated with apps for direct file access include the following.

  • 3d0d7e5fb2ce288813306e4d4636395e047a3d28 SMS
  • 1b6b187a1b60b9ae8b720c79e2c67f472bab09c0 WhatsApp
  • 1c6a49018bcace96656e4fe8f08d572ce071b92c WhatsApp
  • 7c7fba66680ef796b916b067077cc246adacf01d WhatsApp
  • b39bac0d347adfaf172527f97c3a5fa3df726a3a Viber
  • 8e281be6657d4523710d96341b6f86ba89b56df7 Kik
  • ff1324e6b949111b2fb449ecddb50c89c3699a78 Calls
  • a49bfab36504be1bf563c1d1813b05efd6076717 Calls
  • 2b2b0084a1bc3a5ac8c27afdf14afb42c61a19ca Calls
  • 5a4935c78a5255723f707230a451d79c540d2741 Calls
  • 12b144c0bd44f2b3dffd9186d3f9c05b917cee25 Photos
  • adb8c77534444e97c31ff15924d50f3ed1fbd3b1 Contacts
  • 2041457d5fe04d39d0ab481178355df6781e6858 Appointments
  • 3ecf3efff3a55d6155efce2828579e8a3cd881c1 Browsing history
  • cd89f9e10d3497912bfc92e5dc674ca989cfdd44 Browsing history
  • 2d711a1f5613f5259730b98328a3f7e816698f88 Line

Some messenger applications – such as Skype, Facebook Messenger and WeChat – vary the file_id dependant on the conversation.

4. Refreshing an account login using authentication tokens

The auth_token is a login token with Apple. It lasts for at least a day, and is refreshed when a request is made to the refresh-session endpoint on the API. A daily poll to the refresh-session endpoint is all that is needed to persist this token.

As the refresh-session endpoint only needs the auth_token as input and returns the device list plus a new session key, it can be used to start a new session on the API without the need to login to the account again. This is especially useful for 2FA/2SV enabled accounts as the authentication process only needs to be completed for the initial sign-in request.

To use it, one must use the auth_token field retrieved during login. This must be sent to the refresh-session endpoint.

The auth_token parameter is return from the initial sign-in request, and must be used against the refresh-session endpoint.

CURL_CALL --data-urlencode "auth_token=AUTHENTICATION_TOKEN"
          https://api.icloudextractor.com/c/refresh-session/

Submitting an invalid authentication token

If the token is not valid, the endpoint will return a bad request code.

HTTP/1.1 400 BAD REQUEST
{"message": "Invalid auth_token.",
 "error": "invalid-parameter"}

Submitting a valid authentication token

The response will be similar to the login endpoint: a newly created session key and the updated list of devices with all the metadata needed to identify each. One can use the new session to continue pulling data.

HTTP/1.1 200 OK

5. Deletion of iCloud Photo Library files: delete-file

The delete-file method is available for deleting photos from the iCloud Photo Library. It accepts file, key and a permament flag as parameters.

CURL_CALL --data-urlencode "key=SESSION_KEY"
          --data-urlencode "file=FILE_ID"
          --data-urlencode "permanent=False"
          https://api.icloudextractor.com/c/delete-file/

The file parameter will contain the photo’s id (retrievable through the web_photos feed) and the permanent flag controls if the file is going to be soft or hard deleted. If it’s set to False, the request will cause the file to be moved to the “Recently deleted” photos album (known as soft delete). On the other hand, if it’s set to True, then the request will remove the file from the “Recently deleted” album, and will cause it to be deleted permanently (known as hard delete).

Successful soft delete

If the soft delete was successful, the photo will be moved to the “Recently deleted” album and it will return a success message.

HTTP/1.1 200 OK
{
  "message": "Success: File number: FILE_ID has been recycled."
}

Successful hard delete

If the hard delete was successful, the photo will be removed from associated devices when these devices next sync to iCloud. However, due to the technique used, hard deleted files will still be discoverable and downloadable from Reincubate’s iCloud Photo API for an indeterminate amount of time. This behaviour can be used to un-delete unlisted files.

Please note that, for a file to be hard deleted, it must have been soft deleted first.

HTTP/1.1 200 OK
{
  "message": "Success: File number: FILE_ID has been deleted permanently."
}

Failed soft or hard delete

If the request fails, it will return an error response.

HTTP/1.1 400 BAD REQUEST
{
  "message": "Failure: File number: FILE_ID was not deleted."
}

Accelerating downloads with native SDK

Note

The native SDK has been deprecated; use of asapi or asmaster is recommended instead. The rate of change of cloud data formats is too rapid for most clients to maintain local infrastructure, and the cloud API is faster to provide data and easier to scale than local components.

For highly parallelised file downloads, we offer a C++ SDK which allows clients to download and decrypt files locally, avoiding the overhead (but losing the convenience) of the download-file endpoint. This SDK is available for Linux (Ubuntu 12.04, Ubuntu 14.04, Debian Jessie), and Windows.

It is integrated with the rest of the API’s workflow.

Downloads

Users can load the current library and call DownloadFiles, the SDK entrypoint, which has the following signature:

int DownloadFiles(const wchar_t* clientID, const wchar_t* clientKey, const wchar_t* sessionKey,
                  const wchar_t* deviceID, const wchar_t** fileIDs, size_t fileIDs_count,
                  const wchar_t* targetDir, ProgressFunction progFunc, void* progParam,
                  GetWStringBuffer getErrorBuffer)

With these external callback definitions:

typedef wchar_t* (*GetWStringBuffer)(size_t size);
typedef bool(*ProgressFunction)(double percent, unsigned long long downloadedSize,
                                unsigned long long totalSize, void* param);

The parameters are:

  • clientID The API client ID.
  • clientKey The API client key.
  • sessionKey Current session key.
  • deviceID Target device ID.
  • fileIDs Array of required file_ids.
  • fileIDs_count Length of the fileIDs array.
  • targetDir Output directory where the files will be downloaded .
  • progFunc Progress callback function, which is called every time a progress update is made.
  • progParam Custom parameter that can be passed to the progFunc callback.
  • getErrorBuffer This callback function should return a buffer which will hold the errors occured during the download.

After the download finishes, the requested file ids will be in the folder designated by targetDir.

Older SDK versions

On older versions, the the DownloadFiles entrypoint had a slightly different signature:

int DownloadFiles(const wchar_t* clientID, const wchar_t* clientKey, const wchar_t* sessionKey,
                  const wchar_t* deviceID, const wchar_t** fileIDs, size_t fileIDs_count,
                  const wchar_t* targetDir, ProgressFunction progFunc, void* progParam,
                  GetWStringBuffer getReplyBuffer, GetWStringBuffer getErrorBuffer)

The additional parameter is:

  • getReplyBuffer Similar to getErrorBuffer, this callback function is responsible of returning a valid buffer where the DownloadFiles method can write. In this case, this buffer will contain the reply with a final status of the download.

Account and device deactivation and reactivation

Note

This is an additional method available to some clients. For access to this method contact the enterprise team.

The client-management method allows for clients to deactive or reactivate billing for account or device access. The methods for deactivation and reactivation have separate endpoints.

Account deactivation

CURL_CALL --data-urlencode "account=ACCOUNT_ID"
          https://api.icloudextractor.com/c/client-management/deactivation/

Account reactivation

CURL_CALL --data-urlencode "account=ACCOUNT_ID"
          https://api.icloudextractor.com/c/client-management/activation/

Device deactivation

CURL_CALL --data-urlencode "device=DEVICE_ID"
          https://api.icloudextractor.com/c/client-management/deactivation/

Device reactivation

CURL_CALL --data-urlencode "device=DEVICE_ID"
          https://api.icloudextractor.com/c/client-management/activation/

Submitting a valid request

If the values passed to the account deactivation method are valid, it will return a message in the HTTP response body.

HTTP/1.1 200 OK
{"message": "deactivation has been set to True for account: ACCOUNT_ID"}

In the event of a user requesting a device be deactivated, a similar message is returned in the HTTP response body:

HTTP/1.1 200 OK
{"message": "deactivation has been set to True for device: DEVICE_ID"}

Submitting a request with invalid credentials

If the user makes a request to deactivate or reactivate an account with an invalid account_id or invalid device_id, or if the account_id or device_id are not associated with the user, it will return an HTTP 400.

HTTP/1.1 400 BAD REQUEST
{"message": "no device with device ID: BAD_DEVICE_ID",
 "error": "bad-device"}

A similar error and message is returned for invalid account_id or an account_id which is not associted with the user.

HTTP/1.1 400 BAD REQUEST
{"message": "no account with account ID: ACCOUNT_ID",
 "error": "bad-account"}

Repeating a request

If a user requests a device or account to be deactivated or reactivated when it already exists in that state, a message will be returned in the HTTP response body, informing the user that the requested device_id or account_id is already in the requested state:

HTTP/1.1 200 OK
{"message": "deactivation is already set to True for account: ACCOUNT_ID "}

A similar message is shown in the event of a repeated request for device deactivation and reactivation and account reactivation.

Requesting data for a deactivated account or device

If a user requests data from an account or device which has been deactivated, it will an HTTP 403:

HTTP/1.1 403 FORBIDDEN
{"message": "The requested account has been deactivated",
 "error": "deactivated-account"}

Again, a similar message is given in the event of requesting data from a deactivated account.

Troubleshooting

Note

General troubleshooting and support information is available from support and service status.

The feed returns a message: “Contact enterprise@reincubate.com for access to this data”

This message will be returned when the demonstration key is used. Please contact us for a trial key with access to more data. If you already have a trial key, are you correctly specifying it in your client implementation?

I’m trying to pull an app’s database file by file_id but I’m not getting any data back

file_ids are derived from an SHA-1 hash of the file’s path and name, so they are constant for any given file. If the file’s attributes or content change, it won’t affect the hash.

However, sometimes app authors change the name of the file they store data in (and sometimes Apple do in new iOS releases). That’s why, for instance, there several different file_ids to examine when getting WhatsApp data. These file_ids could be changed any time an app is updated.

It is recommended users pull JSON feeds instead of working with files and manipulating them directly. Using the feeds, one needn’t worry over the efficacy of SQL, PList parsing or undeletion, and the feeds are quicker and much simpler to work with.

I am receiving rate-limiting errors from the server

The API rate-limits requests over a 15 minute window, and this limiting is configured per key. Most keys are rate-limited for security purposes.

API clients are returned data on their usage against limits in the HTTP header responses that they receive. These responses use the following headers:

  • X-Rate-Limit-Limit The number of requests permitted in a 15 minute window.
  • X-Rate-Limit-Remaining The number of requests remaining in the current window’s allocation.
  • X-Rate-Limit-Reset The time remaining until the current rate-limit window ends, in milliseconds.

Here’s an example set of live headers from a key on a 1,000 request rate-limit.

X-Rate-Limit-Remaining: 995
X-Rate-Limit-Limit: 1000
X-Rate-Limit-Reset: 3546.3297081

If the rate-limit is hit, the server will respond with:

HTTP/1.1 429 TOO MANY REQUESTS

The server will include the three rate-limit headers in this response.

The correct client behaviour is to wait for the duration specified by X-Rate-Limit-Reset to pass, at which point X-Rate-Limit-Remaining will be reset.

I’m received an email about remote access to the iCloud account I accessed

Polling the live feed modules (as noted above in the sample feed module flags section) can trigger an email being sent to the address associated with that iCloud account. Note that this only occurs for the live feed modules. Polling the point-in-time modules avoids the chance of email.