Overview
HeadSpin provides a convenient REST API interface for idevice, a tool to natively communicate with iOS devices. HeadSpin allows you to run idevice commands through an API interface so you can easily target and perform actions on your iOS devices.
The prerequisite to using the HeadSpin API is an API token. You can create an API token from your user settings.
Base URL
All URLs referenced in the API documentation have the following base URL structure:
https://api-dev.headspin.io/v0/idevice/
Available parameters:
- timeout: wait for devices until they come back online or timeout is reached (unit: second / default: 0.0)
Example:
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/screenshot?timeout=60 -o ./my-screenshot.png
Your API token is passed in the request header as the Authorization Bearer. Here's an example of this expressed in Python, which you can use as a reference to adapt to your language of choice:
import requests
api_token = "<your_api_token>" # We pre-filled your API Token here
device_serial = "{ios-device-id}" # Replace this with the UDID for your target device
def get_ios_device_app_list(api_token, udid):
headers = {
"Authorization": "Bearer {}".format(api_token)
}
request_url = "https://api-dev.headspin.io/v0/idevice/{}/installer/list?json".format(udid)
r = requests.get(request_url, headers=headers)
data = r.json()
return data
To ensure data privacy, our REST API are served over HTTPS. For on-premise deployments your Base URL may vary based on your environment. Please reach out to your HeadSpin contact or support@headspin.io for your exact Base URL details.
Note: The examples in this guide will be expressed as cURL commands to make it easy to follow cross-platform and independent of programming language. For cURL commands we can use a convenient base URL syntax, where your API token is placed in the Base URL as such:
-H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/id
API Guide
This section will introduce how to use the HeadSpin iOS Device API through several examples:
- Take a screenshot
- Retrieve the iOS syslog
- Install a provisioning profile
- Install or uninstall an iOS app
- Get a list of installed apps on a device
The examples cover popular use cases and explain how to use the API. The subsequent section will be a full reference of available iOS API.
Take a screenshot
API
You can take a screenshot of an iOS device by sending a GET request to the iOS Screenshot API. You can also specify an output path where the image can be stored on your client machine.
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{device-udid}/screenshot
For example:
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/screenshot -o ./my-screenshot.png
Retrieve the iOS syslog
API
Syslog is the iOS system logger that contains all of the log file data from an iOS device. Since there can be numerous syslog events on a given device, HeadSpin provides a convenient query string parameter to retrieve a certain number of lines.
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{device-udid}/syslog?n={number-of-lines}
For example:
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/syslog?n=50
Install a provisioning profile
API
Development builds of iOS apps have to be signed by Apple first before they can be installed on a given device. The first step is to install your provisioning profile on the device. A provisioning profile acts as a link between the device and the developer account. In your Apple Developer Account, you can select which devices can run your app with your provisioning profile. A provisioning profile must be installed on each device on which you wish to run your application code. HeadSpin provides API for installing your provisioning profile. As a prerequiste to using this API, download your iOS provisioning profile from your Apple Developer Account.
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{device-udid}/provision/install --data-binary "@{your-provisioning-profile}"
For example:
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/provision/install --data-binary "@/Users/example/myexample.mobileprovision"
Install or uninstall an iOS app
Install
API
To install a previously uploaded iOS app on a device, make a POST request with the app id.
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v1/app/{app_id}/install/{ios-device-id}
Uninstall
API
To uninstall a previously uploaded iOS app on a device, make a POST request with the app id.
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v1/app/{app_id}/uninstall/{ios-device-id}
Get a list of installed apps on a device
You can retrieve a list of installed apps on a given device using the following endpoint. Furthermore, there is a query string parameter to specify if you would like the response in JSON or in the native plist XML format.
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/installer/list?{json-or-xml}
For example:
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/installer/list?json
API Reference
List all iOS devices
Get a device's information
Install a provisioning profile
List all apps on a device
Install an app on a device by app ID
Uninstall an app from a device by app ID
Installing dSYMs with App Management
View a device's syslog
Get a screenshot from a device
Save a screenshot to the cloud
Restart a device
Lock a device
Unlock a device
Dismiss popups on a device
Using Pintap to solve PIN entry screen
List all iOS devices
Route |
Method |
/v0/idevice/id |
GET |
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/id
Response
JSON object, each key is the address of a device. The address is in the form of <code class="dcode">{the iOS device's UDID (Unique Device Identifier)}@{host}</code>.
{
"d138cc4ef3109179902444f33e5229ad68883db9@staging-us-mv-0-proxy-2.headspin.io": {
"status": "device",
"serial": "DNPQ2JDTG5MP",
"os": "ios",
"host": "staging-us-mv-0-proxy-2.headspin.io",
"device_id": "d138cc4ef3109179902444f33e5229ad68883db9"
},
"ef472902906914b6edccff300852b92175c13622@staging-us-mv-0-proxy-3.headspin.io": {
"status": "device",
"serial": "F2LWK0B7JCLF",
"os": "ios",
"host": "staging-us-mv-0-proxy-3.headspin.io",
"device_id": "ef472902906914b6edccff300852b92175c13622"
}
}
Get a device's information
Route |
Method |
/v0/idevice/{device_id}/info |
GET |
Optional parameters
- <code class="dcode">/{device_id}/info?json</code>: get the results in JSON
- <code class="dcode">/{device_id}/info?flags=--xml</code>: get the results in XML
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/info
Response
By default, the response is in plaintext.
If the optional <code class="dcode">?json</code> parameter is used, the response is a JSON object that looks like the following:
{
"BasebandVersion": "6.30.04",
"EthernetAddress": "d0:25:98:31:1a:87",
"UniqueDeviceID": "{ios-device-id}",
"CPUArchitecture": "arm64",
"PkHash": "5OQIGNymupBn16zMKPujMp3562XDnNFkULy+gshbERM=",
"ChipID": 28672,
"BasebandMasterKeyHash": "8CB15EE4C8002199070D9500BB8FB183B02713A5CA2A6B92DB5E75CE15536182",
"SoftwareBehavior": "AQAAAAAAAAAAAAAAAAAAAA==",
"ProximitySensorCalibration": "T00EAA0LODgQA7wCsATMALwC/AACAMoQ9gMCALqr+gLuAl8AKQKnASvI/xoAAAAA4QCVAAQCAADrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"SIMStatus": "kCTSIMSupportSIMStatusNotInserted",
"ModelNumber": "MG4H2",
"DeviceColor": "#e1e4e3",
"ProductType": "iPhone7,2",
"TimeZone": "Asia/Jakarta",
"BasebandKeyHashInformation": {
"SKeyHash": "u+/tcCwvaQ+1Y9t40I4yegCEmB28mALlaROhaIVGBWo=",
"SKeyStatus": 0,
"AKeyStatus": 2
},
"FirstFreePairExpired": true,
"BluetoothAddress": "d0:25:98:31:1a:86",
"BrickState": false,
"DeviceName": "Proxy Box’s iPhone",
"kCTPostponementStatus": "kCTPostponementStatusActivated",
"TrustedHostAttached": true,
"HasSiDP": true,
"TimeZoneOffsetFromUTC": 25200,
"UseRaptorCerts": true,
"CarrierBundleInfoArray": [],
"MobileSubscriberNetworkCode": "",
"HardwarePlatform": "t7000",
"RegionInfo": "PA/A",
"SBLockdownEverRegisteredKey": true,
"BasebandChipID": 8343777,
"kCTPostponementInfoServiceProvisioningState": false,
"MLBSerialNumber": "C07519507F3FQJYF",
"HardwareModel": "N61AP",
"BasebandRegionSKU": "BQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"BasebandActivationTicketVersion": "V2",
"FirmwareVersion": "iBoot-4076.30.43",
"DeviceClass": "iPhone",
"kCTPostponementInfoPRLName": 0,
"PasswordProtected": false,
"SerialNumber": "C39PP04BG5MT",
"UniqueChipID": 599087876023334,
"TelephonyCapability": true,
"BoardId": 6,
"ProtocolVersion": "2",
"FusingStatus": 3,
"BasebandCertId": 3840149528,
"ActivationState": "Activated",
"WiFiAddress": "d0:25:98:31:1a:85",
"ChipSerialNo": "FC4T9A==",
"ProductVersion": "11.2",
"BasebandStatus": "BBInfoAvailable",
"kCTPostponementInfoPRIVersion": "0.0.0",
"ProductionSOC": true,
"ActivationStateAcknowledged": true,
"MobileEquipmentIdentifier": "35928606708121",
"BasebandSerialNumber": "FC4T9A==",
"HostAttached": true,
"CertID": 3840149528,
"SoftwareBundleVersion": "",
"TimeIntervalSince1970": 1553106896.753065,
"SIMTrayStatus": "kCTSIMSupportSIMTrayInsertedNoSIM",
"ProductName": "iPhone OS",
"BuildVersion": "15C114",
"SupportedDeviceFamilies": [
1
],
"InternationalMobileEquipmentIdentity": "359286067081218",
"WirelessBoardSerialNumber": "F417CE336DC",
"Uses24HourClock": false,
"DieID": 599087876023334,
"MobileSubscriberCountryCode": "",
"PartitionType": "GUID_partition_scheme",
"NonVolatileRAM": {
"com.apple.System.tz0-size": "MHhDMDAwMDA=",
"auto-boot": "dHJ1ZQ==",
"backlight-level": "MTU0MA==",
"boot-args": ""
}
}
If the optional <code class="dcode">?flags=--xml</code> parameter is used, the response is instead an XML object that looks like the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActivationState</key>
<string>Activated</string>
<key>ActivationStateAcknowledged</key>
<true/>
<key>BasebandActivationTicketVersion</key>
<string>V2</string>
<key>BasebandCertId</key>
<integer>3840149528</integer>
<key>BasebandChipID</key>
<integer>8343777</integer>
<key>BasebandKeyHashInformation</key>
<dict>
<key>AKeyStatus</key>
<integer>2</integer>
<key>SKeyHash</key>
<data>
u+/tcCwvaQ+1Y9t40I4yegCEmB28mALlaROhaIVGBWo=
</data>
<key>SKeyStatus</key>
<integer>0</integer>
</dict>
<key>BasebandMasterKeyHash</key>
<string>8CB15EE4C8002199070D9500BB8FB183B02713A5CA2A6B92DB5E75CE15536182</string>
<key>BasebandRegionSKU</key>
<data>
BQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAA==
</data>
<key>BasebandSerialNumber</key>
<data>
FC4T9A==
</data>
<key>BasebandStatus</key>
<string>BBInfoAvailable</string>
<key>BasebandVersion</key>
<string>6.30.04</string>
<key>BluetoothAddress</key>
<string>d0:25:98:31:1a:86</string>
<key>BoardId</key>
<integer>6</integer>
<key>BrickState</key>
<false/>
<key>BuildVersion</key>
<string>15C114</string>
<key>CPUArchitecture</key>
<string>arm64</string>
<key>CarrierBundleInfoArray</key>
<array>
</array>
<key>CertID</key>
<integer>3840149528</integer>
<key>ChipID</key>
<integer>28672</integer>
<key>ChipSerialNo</key>
<data>
FC4T9A==
</data>
<key>DeviceClass</key>
<string>iPhone</string>
<key>DeviceColor</key>
<string>#e1e4e3</string>
<key>DeviceName</key>
<string>Proxy Box’s iPhone</string>
<key>DieID</key>
<integer>599087876023334</integer>
<key>EthernetAddress</key>
<string>d0:25:98:31:1a:87</string>
<key>FirmwareVersion</key>
<string>iBoot-4076.30.43</string>
<key>FirstFreePairExpired</key>
<true/>
<key>FusingStatus</key>
<integer>3</integer>
<key>HardwareModel</key>
<string>N61AP</string>
<key>HardwarePlatform</key>
<string>t7000</string>
<key>HasSiDP</key>
<true/>
<key>HostAttached</key>
<true/>
<key>InternationalMobileEquipmentIdentity</key>
<string>359286067081218</string>
<key>MLBSerialNumber</key>
<string>C07519507F3FQJYF</string>
<key>MobileEquipmentIdentifier</key>
<string>35928606708121</string>
<key>MobileSubscriberCountryCode</key>
<string></string>
<key>MobileSubscriberNetworkCode</key>
<string></string>
<key>ModelNumber</key>
<string>MG4H2</string>
<key>NonVolatileRAM</key>
<dict>
<key>auto-boot</key>
<data>
dHJ1ZQ==
</data>
<key>backlight-level</key>
<data>
MTU0MA==
</data>
<key>boot-args</key>
<string></string>
<key>com.apple.System.tz0-size</key>
<data>
MHhDMDAwMDA=
</data>
</dict>
<key>PartitionType</key>
<string>GUID_partition_scheme</string>
<key>PasswordProtected</key>
<false/>
<key>PkHash</key>
<data>
5OQIGNymupBn16zMKPujMp3562XDnNFkULy+gshbERM=
</data>
<key>ProductName</key>
<string>iPhone OS</string>
<key>ProductType</key>
<string>iPhone7,2</string>
<key>ProductVersion</key>
<string>11.2</string>
<key>ProductionSOC</key>
<true/>
<key>ProtocolVersion</key>
<string>2</string>
<key>ProximitySensorCalibration</key>
<data>
T00EAA0LODgQA7wCsATMALwC/AACAMoQ9gMCALqr+gLuAl8AKQKnASvI/xoAAAAA4QCV
AAQCAADrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
</data>
<key>RegionInfo</key>
<string>PA/A</string>
<key>SBLockdownEverRegisteredKey</key>
<true/>
<key>SIMStatus</key>
<string>kCTSIMSupportSIMStatusNotInserted</string>
<key>SIMTrayStatus</key>
<string>kCTSIMSupportSIMTrayInsertedNoSIM</string>
<key>SerialNumber</key>
<string>C39PP04BG5MT</string>
<key>SoftwareBehavior</key>
<data>
AQAAAAAAAAAAAAAAAAAAAA==
</data>
<key>SoftwareBundleVersion</key>
<string></string>
<key>SupportedDeviceFamilies</key>
<array>
<integer>1</integer>
</array>
<key>TelephonyCapability</key>
<true/>
<key>TimeIntervalSince1970</key>
<real>1553107066.929317</real>
<key>TimeZone</key>
<string>Asia/Jakarta</string>
<key>TimeZoneOffsetFromUTC</key>
<real>25200.000000</real>
<key>TrustedHostAttached</key>
<true/>
<key>UniqueChipID</key>
<integer>599087876023334</integer>
<key>UniqueDeviceID</key>
<string>{ios-device-id}</string>
<key>UseRaptorCerts</key>
<true/>
<key>Uses24HourClock</key>
<false/>
<key>WiFiAddress</key>
<string>d0:25:98:31:1a:85</string>
<key>WirelessBoardSerialNumber</key>
<string>F417CE336DC</string>
<key>kCTPostponementInfoPRIVersion</key>
<string>0.0.0</string>
<key>kCTPostponementInfoPRLName</key>
<integer>0</integer>
<key>kCTPostponementInfoServiceProvisioningState</key>
<false/>
<key>kCTPostponementStatus</key>
<string>kCTPostponementStatusActivated</string>
</dict>
</plist>
Install a provisioning profile
A provisioning profile ties your developer team to the devices your team uses for development and testing. If your app is not signed and distributed, you sometimes have to install your provisioning profile on a device before you can install your app on that device to test.
Route |
Method |
/v0/idevice/{device_id}/provision/install |
POST |
Request Body
The request's body should include the content of your <code class="dcode">.mobileprovision</code> file. To include the binary in your <code class="dcode">curl</code> request, use the <code class="dcode">--data-binary <file_name></code> flag.
See Apple's guide for more information on your provisioning profile.
Example
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/provision/install -H "Content-type: text/plain" --data-binary provisioning_profile
Response
- <code class="dcode">HTTP response: 400, missing mobile provision data</code> if the provisioning data is not included in the body.
List all apps on a device
Route |
Method |
/v0/idevice/{device_id}/installer/list |
GET |
Optional Parameters
- <code class="dcode">{device_id}/installer/list?json</code>: get the results in JSON
- <code class="dcode">/{device_id}/installer/list?flags=--xml</code>: get the results in XML
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/installer/list
Response
The response is a plaintext document in CSV format that looks like the following:
CFBundleIdentifier, CFBundleVersion, CFBundleDisplayName
com.apple.itunesu, "2488", "iTunes U"
com.apple.Pages, "6091", "Pages"
com.apple.Numbers, "6091", "Numbers"
com.apple.Keynote, "6091", "Keynote"
io.headspin.masterhand.app, "15", "masterhand"
com.apple.iMovie, "4147.7.82", "iMovie"
com.apple.test.WebDriverAgentRunner-Runner, "1", "WebDriverAgentRunner-Runner"
com.apple.mobilegarageband, "4878.17", "GarageBand"
If the optional <code class="dcode">?json</code> parameter is used, the response is a JSON object that looks like the following:
{
"data": [
{
"DTPlatformVersion": "12.1",
"UIRequiresFullScreen": true,
"CFBundleNumericVersion": 0,
"Container": "/private/var/mobile/Containers/Data/Application/42A0FFC4-973F-4692-902B-D42C23CF9B2B",
"ParallelPlaceholderPath": true,
"CFBundleIcons": {
"CFBundlePrimaryIcon": {
"CFBundleIconName": "AppIcon",
"CFBundleIconFiles": [
"AppIcon29x29",
"AppIcon40x40",
"AppIcon60x60"
]
}
},
"ApplicationDSID": 8434493456,
"CFBundleInfoDictionaryVersion": "6.0",
"UIBackgroundStyle": "UIBackgroundStyleTransparent",
"DTXcodeBuild": "10B61",
"EnvironmentVariables": {
"HOME": "/private/var/mobile/Containers/Data/Application/42A0FFC4-973F-4692-902B-D42C23CF9B2B",
"CFFIXED_USER_HOME": "/private/var/mobile/Containers/Data/Application/42A0FFC4-973F-4692-902B-D42C23CF9B2B",
"TMPDIR": "/private/var/mobile/Containers/Data/Application/42A0FFC4-973F-4692-902B-D42C23CF9B2B/tmp"
},
"CFBundleSupportedPlatforms": [
"iPhoneOS"
],
"CFBundleIdentifier": "com.apple.itunesu",
"CFBundleDocumentTypes": [
{
"CFBundleTypeIconFiles": [
"mat-thumb_ipad_pdf"
],
"CFBundleTypeName": "PDF",
"LSItemContentTypes": [
"com.adobe.pdf"
],
"LSHandlerRank": "Alternate"
},
{
"CFBundleTypeName": "Keynote",
"LSItemContentTypes": [
"com.apple.keynote.key",
"com.apple.iwork.keynote.key"
],
"LSHandlerRank": "Alternate"
},
{
"CFBundleTypeName": "Pages",
"LSItemContentTypes": [
"com.apple.pages.pages",
"com.apple.iwork.pages.pages"
],
"LSHandlerRank": "Alternate"
},
....
....
....
]
}
If the optional <code class="dcode">?flags=--xml</code> parameter is used, the response is an XML object with the same content.
Install an app on a device by app ID
Route |
Method |
/v1/app/{app_id}/install/{device_id} |
POST |
Note
This command is a part of our App Management API. For more information and additional API command sets, please navigate to the link above. App Management API is consistent across all platforms, so this command will work for XAPK as well as APK and IPA files.
Automated Signing
Your IPA will be signed by us to ensure that it can install on the target device. If you would like to manage signing yourself, register the device UDID in your Apple Developer Account and add the device to a provisioning profile. An IPA provisioned for the target device will disable automated signing but you can explicitly disable it with the optional ?sign=false parameter. Automated signing does not support app capabilities.
Apps provisioned with an Enterprise profile are not subject to deployment restrictions and therefore HeadSpin disables Automated Signing for these apps. If an app requires features that are only available with non-Enterprise profiles, please select an alternative distribution method in Xcode when exporting the IPA, such as Ad Hoc or Development. This will allow Automated Signing to manage signing as expected.
Optional Parameters
- <code class="dcode">/v1/app/{app_id}/install/{device_id}?sign=false</code>: disable Automated Signing. iOS only, see above for signing documentation.
Example
Install a previously uploaded app:
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v1/app/{app_id}/install/{ios-device-id}
Uninstall an app from a device by app ID
Route |
Method |
/v1/app/{app_id}/uninstall/{device_id} |
POST |
Note
This command is a part of our App Management API. For more information and additional API command sets, please navigate to the link above. App Management API is consistent across all platforms, so this command will work for XAPK as well as APK and IPA files.
Example
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v1/app/{app_id}/uninstall/{ios-device-id}
Installing dSYMs with App Management
In order to upload dSYMs, use the 'upload additional app file' method available in App Management.
Package your dSYMs
When you archive your app in Xcode to export an IPA, Xcode will generate Debug Symbol files (dSYMs) for that build. You should be able to find your archive in Xcode's Organizer (right-click it and select Show in Finder, then right-click the .xcarchive itself to Show Package Contents.) Right-click the dSYMs directory and select Compress "dSYMs" or do so via the command line with zip -r dSYMs.zip dSYMs. A debuggable IPA and matching debug symbols are required to generate a Function Call Timeline for a given app. If not using the Automated Signing feature, you must sign the app with an iOS App Development profile.
View a device's syslog
Streams the content of the connected device's syslog.
Route |
Method |
/v0/idevice/{device_id}/syslog |
GET |
Optional Parameters
- <code class="dcode">{device_id}/syslog?n={lines back}</code>: Instead of streaming, retrieve only the last 'n' lines from the device's syslog. For example, <code class="dcode">/syslog?n=30</code> retrieves the last 30 lines.
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/syslog
Response
The device's syslog is sent to the requesting user in <code class="dcode">text/plain</code>. The content is streamed and sent in chunks.
Get a screenshot from a device
Capture a screenshot of the device's current screen in PNG format.
Route |
Method |
/v0/idevice/{device_id}/screenshot |
GET |
Optional Parameters
- To save the captured screenshot as an image, append <code class="dcode">> {local path}/{filename}.png</code> to the end of the command.
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/screenshot > test.png
Response
An <code class="dcode">image/png</code> object.
Save a screenshot to the cloud
Similar to the <code class="dcode">.../screenshot</code> route explained above, the <code class="dcode">.../screenshot_url</code> route will take a screenshot in PNG format, but additionally the screenshot will be uploaded to the HeadSpin services. The result of the <code class="dcode">.../screenshot_url</code> route is another URL that can be used to retrieve the uploaded screenshot. Note that the URL returned from this API is only valid for 24 hours.
Route |
Method |
/v0/idevice/{device_id}/screenshot_url |
GET |
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/screenshot_url
https://another-url...
curl https://another-url... -o ./my-screenshot.png
Response
A URL.
Restart a device
Route |
Method |
/v0/idevice/{device_id}/diagnostics/restart |
POST |
Example
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/diagnostics/restart
Response
A JSON object.
- <code class="dcode">{"status": 0, "returncode": 0, "stdout": "Restarting device.\n", "summary": "ok"}</code> if the device is restarted successfully.
Lock a device
Route |
Method |
/v0/idevice/{device_id}/lock |
POST |
Example
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/lock
Optional Parameters
- <code class="dcode">{device_id}/lock/?timeout={timeout seconds}</code>: If the locking attempt fails, the server will keep retrying until the <code class="dcode">timeout seconds</code> have elapsed. If there's no <code class="dcode">?timeout</code> parameter, or <code class="dcode">timeout seconds</code> is <code class="dcode">0</code>, then this returns immediately after the first attempt to lock.
- <code class="dcode">{device_id}/lock/?idleTimeout={timeout seconds}</code>: Unlock automatically if the device is inactive for <code class="dcode">timeout seconds</code>.
Response
JSON object:
- <code class="dcode">{"status": 0, "message": "<device_address> locked."}</code> if the lock attempt was successful.
- <code class="dcode">{"status": 1, "message": "Did not lock."}</code> if the lock attempt was unsuccessful. The device might be locked by another user.
Notes
- This route is incompatible with the reservation system. If your company is using the reservation system, use the <code class="dcode">/v0/devices/</code> route instead.
Unlock a device
Unlocks a targeted device in the platform, if the lock is owned by the requesting user.
Route |
Method |
/v0/idevice/{device_id}/unlock |
POST |
Example
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/unlock
Response
JSON object:
- <code class="dcode">{"status": 0, "message": "<device_address> unlocked."}</code> if the unlock attempt was successful.
- <code class="dcode">{"status": 1, "message": "Did not unlock."}</code> if the unlock attempt was unsuccessful. The device might not be locked by the requesting user.
Dismiss pop-ups on a device
Dismiss pop-ups on the device. If there are no pop-ups, it does nothing.
If the device isn't already locked by the requesting user, calling this API route will lock the device. If the device is locked by someone else, this route will not work.
Note that some pop-ups prevent XCTest from starting on the device, resulting in xcodebuild waiting for the pop-up to be dismissed. Call this before running XCTest to ensure reliable startup.
Route |
Method |
/v0/idevice/{device_id}/poptap |
POST |
Example
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}/poptap
Response
- <code class="dcode">{"status": 0, "message": "Poptap success", "value": {"success": true}}</code> if existing pop-ups was dismissed successfully.
Using Pintap to solve PIN entry screen
Uses Pintap to enter a code to solve the PIN entry screen. This performs the same actions as Pintap in Remote Control UI.
Route |
Method |
/v0/idevice/{device_id}@{host}/pintap |
POST |
Optional Parameters
The PIN code can be specified by including a JSON object as the request body.
Key Name |
Description |
pin |
The PIN code to use with Pintap (optional). |
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}@{host}/pintap
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevice/{ios-device-id}@{host}/pintap -d '{"pin":"1234"}'
Response
The server will reply after Pintap has finished execution, which may take several seconds, or when there is an issue.
- <code class="dcode">HTTP 200</code> when Pintap finishes execution.
- <code class="dcode">HTTP 400</code> if there was a problem with the request.
- <code class="dcode">HTTP 404</code> if no eligible device matches the requested device address.
- <code class="dcode">HTTP 500</code> if Pintap encounters an error.
Multiple Device Access
A limited set of commands are available to run across multiple devices in parallel. The commands accept an address pattern called a selector, that follows the standard selector syntax used throughout the platform. The selector syntax runs on each device object and matches the fields in the device object.
Read more about selectors in the selectors doc.
The emtpy selector matches all devices.
API Reference
Get all devices matching a selector
Route |
Method |
/v0/idevicem/{selector}/id |
GET |
Example
curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/idevicem/os:ios/id
Response
A JSON object, with each key being a device address matching the selector.
{
"049456f85e142e8dfd7ada8aebc068480dcc47ac@proxy-us-nyc-6.headspin.io": {
"status": "device",
"host": "proxy-us-nyc-6.headspin.io",
"serial": "F2LW41BTHFM2",
"os": "ios",
"present": "True",
"device_id": "049456f85e142e8dfd7ada8aebc068480dcc47ac"
},
"d9e562b48b9388b4eb24d56ab88a8ab68c3202b9@proxy-gb-lhr-0.headspin.io": {
"status": "device",
"host": "proxy-gb-lhr-0.headspin.io",
"serial": "C39S20DVH2XK",
"os": "ios",
"present": "True",
"device_id": "d9e562b48b9388b4eb24d56ab88a8ab68c3202b9"
}
}