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>"
device_serial = "{ios-device-id}"
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 {the iOS device's UDID (Unique Device Identifier)}@{host}
.
{
"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
/{device_id}/info?json
: get the results in JSON/{device_id}/info?flags=--xml
: 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 ?json
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 ?flags=--xml
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>
<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 .mobileprovision
file. To include the binary in your curl
request, use the --data-binary
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
HTTP response: 400, missing mobile provision data
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
{device_id}/installer/list?json
: get the results in JSON/{device_id}/installer/list?flags=--xml
: 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 ?json
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 ?flags=--xml
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
/v1/app/{app_id}/install/{device_id}?sign=false
: 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
{device_id}/syslog?n={lines back}
: Instead of streaming, retrieve only the last 'n' lines from the device's syslog. For example, /syslog?n=30
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 text/plain
. 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
> {local path}/{filename}.png
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 image/png
object.
Save a screenshot to the cloud
Similar to the .../screenshot
route explained above, the .../screenshot_url
route will take a screenshot in PNG format, but additionally the screenshot will be uploaded to the HeadSpin services. The result of the .../screenshot_url
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.
{"status": 0, "returncode": 0, "stdout": "Restarting device.\n", "summary": "ok"}
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
{device_id}/lock/?timeout={timeout seconds}
: If the locking attempt fails, the server will keep retrying until the timeout seconds
have elapsed. If there's no ?timeout
parameter, or timeout seconds
is 0
, then this returns immediately after the first attempt to lock.{device_id}/lock/?idleTimeout={timeout seconds}
: Unlock automatically if the device is inactive for timeout seconds
.
Response
JSON object:
{"status": 0, "message": " locked."}
if the lock attempt was successful.{"status": 1, "message": "Did not lock."}
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
/v0/devices/
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:
{"status": 0, "message": " unlocked."}
if the unlock attempt was successful.{"status": 1, "message": "Did not unlock."}
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
{"status": 0, "message": "Poptap success", "value": {"success": true}}
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.
HTTP 200
when Pintap finishes execution.HTTP 400
if there was a problem with the request.HTTP 404
if no eligible device matches the requested device address.HTTP 500
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"
}
}