HeadSpin Documentation
Documentation

Android Device API

HeadSpin provides a convenient REST API interface for the Android Debug Bridge (ADB) to perform actions on your Android devices in HeadSpin from your client machine or CI/CD server. ADB is a CLI tool created by Google for interacting and managing Android devices. HeadSpin allows you to run ADB commands through an API interface so you can easily target and perform actions on your Android devices.

The prerequisite to using the HeadSpin APIs is an API Token. You can create an API token from your Settings.

Base URL

All URLs referenced in the API documentation have the following base URL structure:


https://api-dev.headspin.io/v0/adb/

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/adb/{android-device-id}/screenshot?timeout=60 -o ./my-screenshot.png

Where your API token is passed in 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 = "{android-device-serial}" # Replace this with the serial for your target device 

def get_android_device_app_list(api_token, device_serial):
    headers = {
        "Authorization": "Bearer {}".format(api_token)
    }

    request_url = "https://api-dev.headspin.io/v0/adb/devices".format(device_serial)
    r = requests.get(request_url, headers=headers)
    data = r.json()

    return data

To ensure data privacy, our REST APIs are served over HTTPS. For On-Premise Deployments your Base URL may vary based on your environment. Please reach out to your HeadSpin contact 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 including an API token, we use the -H option as such:


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/devices

API Guide

This section will introduce how to use the HeadSpin Android Device API through several examples:

The examples cover popular use cases and explain how to use the APIs. The subsequent section will be a full reference of available Android APIs.

Take a screenshot

API

You can take a screenshot of an Android device by sending a GET request to the Android 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/adb/{device-id}/screenshot -o {path-on-your-local-filesystem} 

For example:


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/screenshot -o ./my-screenshot.png 

Retrieve the Android Logcat

API

Logcat is an ADB command for retrieving the log file data from an Android device. It allows you to view & filter through your app’s logs and system events, such as Garbage collection or Radio states. Since there can be numerous log events on a given device, HeadSpin provides a convenience query string parameter to retrieve a certain number of lines.


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{device-id}/logcat?n={number-of-lines} 

For example:


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/logcat?n=50 

Install an app

API

Using our App Management API, you can install an app on a device using either an app ID or a designated metadata selector. Metadata selectors are descriptors of unique app builds compiled by the HeadSpin system and the user, which can be used to query and filter builds for various actions. For more information and additional API command sets, including how to use metadata selectors for installation, please review the App Management API documentation. The App Management API is consistent across all platforms, so this command will work for XAPK as well as APK and IPA files.

For example, installing a previously uploaded app by app ID:


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v1/app/{app_id}/install/{android-device-id} 

Pull a File From An Android Device

To pull a file from an Android Device you will specify the file path to the resource in the request.


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{device-id}/pull?remote={path-on-android-device} -o {path-on-your-local-filesystem} 

For example:


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/pull?remote=/sdcard/screen.png -o ./screen.png 

Send ADB Commands through the API

You can send ADB commands directly through an Android Device by passing in the ADB command or shell script in the POST body of the request.


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{device-id}/shell -d '{adb-command}' 

or

curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{device-id}/shell --data-binary "@path/to/your/script.sh" 

For example:


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/shell -d "pm list packages" 

API Reference

List all Android devices

Upload a file to a device

List apps installed on a device

Download a file from a device

Execute a script on a device

Install an app on a device by app ID

Uninstall an app from a device by app ID

Lock a device

Unlock a device

Reboot a device

Retrieve a device's logcat

Take a device's screenshot

Save a screenshot to the cloud

Using Pintap to solve PIN entry screen

List all Android devices

Route Method
/v0/adb/devices GET

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/devices 

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>.


{
    "FA6A40303055@proxy-us-sea-1.headspin.io": {
    "status": "device",
    "product": "sailfish",
    "host": "proxy-us-sea-1.headspin.io",
    "model": "Pixel",
    "os": "android",
    "serial": "FA6A40303055",
    "device_id": "{android-device-id}"
  },
  "TA38500QWW@proxy-in-dlh-0.headspin.io": {
    "status": "device",
    "product": "surnia_retasia_ds",
    "host": "proxy-in-dlh-0.headspin.io",
    "model": "MotoE2(4G-LTE)",
    "os": "android",
    "serial": "TA38500QWW",
    "device_id": "355463061323821"
  }
}

Upload a file to a device

Route Method
/v0/adb/{device_id}/push?remote={path_to_destination} POST

Request Body

The request's body should include the binary of your file. To include the binary in your <code class="dcode">curl</code> request, use the <code class="dcode">--data-binary <file_name></code> flag, for example <code class="dcode">--data-binary image.jpg</code> or <code class="dcode">--data-binary "@/Users/headspin/Downloads/image.jpg"</code>

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/push?remote=/sdcard/Pictures/image.jpg --data-binary "@image.jpg" 

Response

A JSON object.

  • <code class="dcode">{ "_headspin_progress": ".", "status": 0, "returncode": 0, "stdout": "[100%] <remote_path_to_file>: 1 file pushed. 0.0 MB/s (11 bytes in 0.020s)\n", "summary": "ok"}</code> if the push is successful.
  • <code class="dcode">{ "_headspin_progress": ".", "status": 0, "returncode": 1, "stdout": "[100%] /storage/image.jpg\nadb: error: failed to copy 'image.jpg' to '/storage/image.jpg': remote couldn't create file: Permission denied\nimage.jpg: 0 files pushed. 0.0 MB/s (11 bytes in 0.006s)\n", "summary": "ok"}</code> if the push is not successful.

Download a file from a device

Route Method
/v0/adb/{device_id}/pull?remote={path_on_device} GET

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/pull?remote=/data/app/io.company.example/base.apk -o ./example.apk

Response

  • The response is the binary of the file. To save the response as a file on your local system, use the <code class="dcode">-o <filename></code> flag.

Execute a script on a device

Route Method
/v0/adb/{device_id}/shell POST

Request Body

The request's body should include your command or the binary of your script.

  • To include the shell command, use the <code class="dcode">-d <command></code> flag, for example <code class="dcode">-d "pm list packages"</code>.
  • To include a file to your script, use the <code class="dcode">--data-binary "@<path_to_your_script>"</code>, for example <code class="dcode">--data-binary "@/Users/username/script.sh"</code>.

Example

To send a single command:


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/shell -d 'pm list packages' 

To send a file to your script:


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/shell --data-binary "@/Users/username/Downloads/script.sh" 

Response

A JSON object, with <code class="dcode">status</code>, <code class="dcode">returncode</code>, <code class="dcode">stdout</code> and <code class="dcode">summary</code>. For example:


{
  "_headspin_progress": ".",
  "status": 0,
  "returncode": 0,
  "stdout": "package:com.google.android.inputmethod.latin\npackage:com.google.android.storagemanager\n",
  "summary": "ok"
}

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.

Optional Parameters

  • <code class="dcode">/v1/app/{app_id}/install/{device_id}?sign=false</code>: disable automated signing. iOS only, see idevice-api 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} 

List apps installed on a device

Route Method
/v0/adb/{device_id}/pm/list-packages GET

Example


curl -X GET -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/adb/{android_device_id}/pm/list-packages" 

Optional Parameters

  • <code class="dcode">format</code> can be specified to set the response format. accepts <code class="dcode">text</code>, <code class="dcode">json</code>, or <code class="dcode">xml</code>. defaults to <code class="dcode">text</code>.
  • <code class="dcode">owner</code> can be specified to filter which types of packages to return. accepts <code class="dcode">user</code>, <code class="dcode">system</code>, or <code class="dcode">all</code>. defaults to <code class="dcode">user</code>.

Example


curl -X GET -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/adb/{android_device_id}/pm/list-packages?owner=user&format=text" 

Response

The response is a plaintext document that looks like the following:


package:com.example.abc versionCode:12
package:com.sample.xyz versionCode:34

If the optional ?format=json parameter is used, the response is a JSON object that looks like the following:


{
  "data": {
      "packages": [
        {"name": "com.example.abc", "version_code": "12"},
        {"name": "com.sample.xyz", "version_code": "34"}]
  }
}

If the optional ?format=xml parameter is used, the response is instead an XML object that looks like the following:


<?xml version="1.0" encoding="utf-8"?>
<data>
  <packages>
    <package>
      <name>
        com.example.abc
      </name>
      <version_code>
        12
      </version_code>
    </package>
    <package>
      <name>
        com.sample.xyz
      </name>
      <version_code>
        34
      </version_code>
    </package>
  </packages>
</data>

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 https://<your_api_token>@api-dev.headspin.io/v1/app/{app_id}/uninstall/{ios-device-id}

Upgrade an app

Route Method
/v0/adb/{device-id}/install?flags=-r POST

Request Body

The request's body should include the binary of your app. To include the binary in your curl request, use the --data-binary flag, for example --data-binary "@App.apk" as shown below.

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/device-id/install?flags=-r --data-binary "@someapp.apk"

Uninstall an XAPK using its xapk_id

Route Method
/v0/adb/{device_id}/uninstall?xapk_id={xapk_id} POST

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/uninstall?xapk_id=7ad39a6a-8b7d-4a92-9cec-1b5ef3bc5e5f 

Response

A JSON object:

  • <code class="dcode">{ "_headspin_progress": ".", "status": 0, "returncode": 0, "stdout": "Success\n\n", "summary": "ok"}</code> if uninstall is successful.
  • <code class="dcode">{ "_headspin_progress": ".", "status": 0, "returncode": 0, "stdout": <error>, "summary": "failed to run"}</code> if uninstall is not successful.

Lock a device

Route Method
/v0/adb/{device_id}/lock POST

● Optional Parameters

<code class="dcode">/v0/adb/{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">/v0/adb/{device_id}/lock/?idleTimeout={timeout seconds}</code>: Unlock automatically if the device is inactive for <code class="dcode">timeout seconds</code>.

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/lock 

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.

Unlock a device

Unlocks the device in the platform, if the lock is owned by the requesting user.

Route Method
/v0/adb/{device_id}/unlock POST

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-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.

Reboot a device

Route Method
/v0/adb/{device_id}/reboot POST

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/reboot 

Response

A JSON object.

  • <code class="dcode">{ "_headspin_progress": ".", "status": 0, "returncode": 0, "stdout": "", "summary": "ok"}</code> if the device was restarted successfully.

Retrieve a device's logcat

Stream the content of the connected device's system log.

Route Method
/v0/adb/{device_id}/logcat GET

Optional Parameters

  • <code class="dcode">/v0/adb/{device_id}/logcat?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/adb/{android-device-id}/logcat 

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.

Take a device's screenshot

Stream the content of the connected device's system log.

Route Method
/v0/adb/{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/adb/{android-device-id}/screenshot > screenshot.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/adb/{device_id}/screenshot_url GET

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-device-id}/screenshot_url 
  https://another-url...

curl -H "Authorization: Bearer <your_api_token>" https://another-url... -o ./my-screenshot.png

Response

A URL

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/adb/{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/adb/{android-device-id}@{host}/pintap 

curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/adb/{android-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 Android Device Access

HeadSpin also provides a set of APIs that allow you to run ADB commands across multiple devices in parallel. These APIs accept an address pattern called a selector. The selector syntax runs on each device object and matches the fields in the device object.

The POST requests return 200 and a consistent JSON shape <code class="dcode">{devices}</code>, where the keys are the same as <code class="dcode">/adb/devices</code>, and each device has <code class="dcode">{returncode, summary, stdout}</code> . The output is frames per line as


{device_number}/{total_devices} {device_json}\n

For example:


1/3 {"T076000OH2@proxy-us-mvo-1.headspin.io": {"status": 0, "returncode": 0, "stdout": "1\n", "summary": "ok"}}
2/3 {"TA9611A4UJ@proxy-us-mvo-1.headspin.io": {"status": 0, "returncode": 0, "stdout": "1\n", "summary": "ok"}}
3/3 {"2ad32118@proxy-us-mvo-1.headspin.io": {"status": 0, "returncode": 0, "stdout": "1\n", "summary": "ok"}}

The emtpy selector matches all devices.

API Reference

ADB command Method Route Notes
adb devices /v0/adbm/devices GET Any keys matched in the selector are returned in the result object.