HTTP REST API v2#

The HTTP REST API allows you to control your Stb-tester Nodes programmatically using HTTP requests and JSON.

This API is intended for integrating stb-tester with external systems, such as a Continuous Integration system.

Authentication#

To allow your scripts to access this API without providing your password, you need to generate an access token: Log into the portal using your browser, click on the user menu in the top right corner, and select “Generate new access token”. You can revoke access tokens from the same menu.

_images/generate-new-access-token.png

You must specify the token in the Authorization HTTP header of every request. If the token is missing or invalid you will get a “403 Forbidden” response.

Example using curl:

curl -H "Authorization: token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9" \
     https://company.stb-tester.com/api/...

Example using Python requests:

import requests
requests.post("https://company.stb-tester.com/api/...",
              headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})

If you need to make multiple HTTP requests from a single script you can use requests.Session to set default values for every request:

import requests
session = requests.Session()
session.headers.update({"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
session.get("https://company.stb-tester.com/api/...")
session.post("https://company.stb-tester.com/api/...")

See also: User Access Control.

Rate limits#

Automated scripts that make many requests are subject to rate-limiting. If you are making requests in serial, you probably won’t even notice the rate-limiting, but if you send many requests at once in parallel, the requests may fail with the HTTP status code 429 Too Many Requests. If you receive a 429 response, your script should wait a few seconds before retrying.

The endpoints for downloading test-results artifacts have a generous “burst” rate, to allow batch scripts that download artifacts from a job with many test-runs.

Screenshots#

Grab screenshot#

GET /api/v2/nodes/(node_id)/screenshot.png#

Grab a screenshot from the device under test.

Example using curl:

Save a screenshot to screenshot.png:

curl -H "Authorization: token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9" \
    https://company.stb-tester.com/api/v2/nodes/stb-tester-abcdef123456/screenshot.png \
    > screenshot.png
Response Headers:
Status Codes:

Grab screenshot thumbnail#

GET /api/v2/nodes/(node_id)/thumbnail.jpg#

Grab a small thumbnail of the screenshot from the device under test.

Example using curl:

Save a screenshot to thumbnail.jpg:

curl -O -H "Authorization: token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9" \
    https://company.stb-tester.com/api/v2/nodes/stb-tester-abcdef123456/thumbnail.jpg
Response Headers:
Status Codes:

Running tests#

List testcases#

GET /api/v2/test_pack/<test_pack_revision>/test_case_names#

List testcases found at a particular revision (branch name or sha) of your test-pack. These names can be passed to /api/v2/run_tests.

Examples using Python requests:

List the testcases on the master branch:

import requests

tests = requests.get(
    "https://company.stb-tester.com/api/v2/test_pack/master/test_case_names",
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}
    ).json()
for test_name in tests:
    print test_name

List the testcases in your local git checkout:

import requests, subprocess

my_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
tests = requests.get(
    "https://company.stb-tester.com/api/v2/test_pack/%s/test_case_names" % my_sha,
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}
    ).json()
for test_name in tests:
    print test_name

Example output:

tests/menu.py::test_that_menu_appears_when_menu_key_is_pressed
tests/menu.py::test_that_close_button_closes_menu
tests/live_tv.py::test_that_pause_button_pauses_live_tv
Response Headers:
Status Codes:

Run tests#

POST /api/v2/run_tests#

Run the specified testcases from the given git commit. The parameters are encoded in the request body as a JSON object. Returns a job_uid that can be used to poll for job completion and test results.

Example using Python requests:

Start a test job with a single test:

response = requests.post(
    "https://company.stb-tester.com/api/v2/run_tests",
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"},
    data=json.dumps({
        "node_id": "stb-tester-abcdef123456",
        "test_pack_revision": "master",
        "test_cases": ["tests/menu.py::test_that_menu_appears_when_menu_key_is_pressed"],
        "remote_control": "roku",
        }))
print response.json()
{'job_uid': '/stb-tester-abcdef123456/0a23/972',
 'job_url': 'https://company.stb-tester.com/api/v2/jobs/stb-tester-abcdef123456/0a23/972',
 'status': 'running',
 'start_time': '2015-05-28T14:46:35.354791Z',
 'end_time': None,
 'result_counts': {'pass': 0, 'fail': 0, 'error': 0, 'total': 1},
}

To make it easier for you to integrate Stb-tester with a Continuous Integration system such as Jenkins, we provide a helper script called stbt_rig.py. See Continuous Integration for details.

Request JSON Object:
  • node_id (string) – (mandatory) Which Stb-tester device to run the tests on. This is the name of the device as shown in the portal and on the physical case of the device, for example stb-tester-abcdef123456.

  • test_pack_revision (string) – (mandatory) Git commit SHA in test-pack repository identifying the version of the tests to run. Can also be the name of a git tag or branch.

  • test_cases (array) –

    (mandatory) List of tests to run.

    Testcase names have the form (filename)::(function_name) where filename is given relative to the root of the test-pack repository and function_name identifies a function within that file; for example tests/my_test.py::test_that_blah_dee_blah.

    The list of all possible testcase names for a given revision can be retrieved using /api/v2/test_pack/(test_pack_revision)/test_case_names.

  • remote_control (string) –

    (usually mandatory) The remote control infrared configuration to use when running the tests.

    This should match the name of a remote control configuration file in your test-pack git repository. For example if your test-pack has config/remote-control/Sony_RM-ED022.lircd.conf, then you should specify "Sony_RM-ED022".

    If not specified in the HTTP request, you must specify test_pack.default_remote_control in your test-pack’s configuration files.

  • category (string) –

    (optional) Category to save the results in. Defaults to "default".

    When you are viewing test results you can filter by this string so that you don’t see results that you aren’t interested in. For example you might set this to “soak test of release x”.

    This must be a valid UTF-8 string and must not contain the characters /, newline (\n), colon (:), NUL (\0), $, or any control characters. It must not start with . or - and must not be empty. UTF-8 encoded Unicode characters are accepted.

  • soak (string) –

    (optional) Soak-testing mode. The allowed values are:

    • "run once" – this is the default mode; it runs each of the specified testcases once.

    • "run forever" – runs each of the testcases once, then repeats, forever. Use /api/v2/jobs/(job_uid)/stop to stop it.

  • shuffle (bool) –

    (optional) Randomise the order in which the tests are run. The allowed values are:

    • true – Randomise the order in which the testcases are run, weighting towards running the faster testcases more often. See Run forever in random order for more information.

    • false – Run the testcases in the order in which they appear in test_cases. This is the default if shuffle is omitted.

  • tags (object) – (optional) Map of name:value pairs, for example {"model": "T-1000"}. Tags are passed to the test script as an automatic configuration key and are recorded in the test-results. Tags set here can be retrived in Python during the test-run with stbt.get_config("result.tags", "tagname"). See also Tags.

Response JSON Object:
Request Headers:
Response Headers:
Status Codes:

Inspect a test job#

GET /api/v2/jobs/(job_uid)#

Find out the current status of the job started with /api/v2/run_tests.

Parameters:
  • job_uid – The desired job’s universal identifier, as returned from /api/v2/run_tests.

Response JSON Object:
  • job_uid (string) – Identifier that refers to this test job. This is unique across all Stb-tester devices in your test farm.

  • job_url (string) – The URL of this endpoint. This is included here for consistency with /api/v2/run_tests.

  • status (string) – Current status of the job. This can be either "running" or "exited".

  • start_time (string) – The time at which the job started as an ISO8601 formatted datetime (for example "2015-05-28T14:46:35.354791Z").

  • end_time (string) – The time at which the job finished as an ISO8601 formatted datetime, or null if the job is still running.

  • result_counts (object) –

    A summary of the test results. This is a dictionary with the following keys:

    • pass – number of tests that completed and passed.

    • fail – number of tests that completed but failed.

    • error – number of tests that couldn’t complete due to an error (see Exceptions in the Python API reference).

    • total – can be greater than pass+fail+error if the job is still running or was stopped prematurely.

Response Headers:
Status Codes:

Inspect a node’s current test job#

GET /api/v2/nodes/(node_id)/job#

Similar to /api/v2/jobs/(job_uid) but instead of specifying a job_uid, it retrieves the current job on the specified Stb-tester device (or the last job that ran on that device if there is no job currently in progress).

Wait for a job to finish#

GET /api/v2/jobs/(job_uid)/await_completion#

This is a “long poll” endpoint that will return when the job has finished running all its tests. It will return immediately if the job has already finished. To avoid timeouts from the HTTP client or any intermediate proxies, this will return “202 Accepted” after 55 seconds if the job still hasn’t finished. If you get a 202 response you should re-try the request.

Response JSON Object:
  • job_uid (string) – Identifier of the current or latest test-job.

Response Headers:
Status Codes:

Wait for a node’s current job to finish#

GET /api/v2/nodes/(node_id)/job/await_completion#

Similar to /api/v2/jobs/(job_uid)/await_completion but instead of specifying a job_uid it waits for the current job on the specified Stb-tester device (or it will return immediately with “200 OK” if there is no job currently in progress).

Stop a job in progress#

PUT /api/v2/jobs/(job_uid)/stop#

Stop a job started with /api/v2/run_tests.

By the time this endpoint returns a response, the job will be stopped. This makes it safe to use /api/v2/run_tests immediately after you receive the HTTP response from this endpoint.

This endpoint will respond with HTTP status 200 even if the job has already exited. This makes it safe to stop the same job any number of times (in other words, this endpoint is idempotent).

The HTTP methods PUT and POST are both valid for this endpoint and behave identically. PUT indicates that this endpoint is idempotent; POST is available for backward compatibility.

Parameters:
  • job_uid – The desired job’s universal identifier, as returned from /api/v2/run_tests.

Status Codes:
  • 200 OK – The job is now stopped

  • 202 Accepted – Timeout - the client should retry the request. If you receive this status code the job is stopping, but isn’t yet stopped. Typically this happens while waiting for the node to upload the artifacts from the job to the cloud. This status code can be avoided by putting the node on a sufficiently fast network.

  • 403 Forbidden – Invalid access token

  • 404 Not Found – Unknown job_uid

  • 429 Too Many RequestsRate limits exceeded

Stop a node’s current job#

POST /api/v2/nodes/(node_id)/job/stop#

Similar to /api/v2/jobs/(job_uid)/stop but instead of specifying a job_uid, it stops the job that is currently running on the specified Stb-tester device.

Test results#

Get list of test results#

GET /api/v2/results#

Retrieve test results for each test run, optionally filtered by a search expression.

Notes:

  • The response will not include a test-run that is currently in progress.

  • The response only includes the first 2,000 matching test-runs. Use the filter and sort parameters to retrieve older results (for example, sort by date, then make a second request using a filter to exclude results newer than the last result in the first response).

Example using Python requests:

response = requests.get(
    "https://company.stb-tester.com/api/v2/results",
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"},
    params={"filter": "job:/stb-tester-abcdef123456/0a23/972"})
print response.json()
[{'result_id': '/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34'
  'job_uid': '/stb-tester-abcdef123456/0a23/972',
  'result_url': 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34',
  'triage_url': 'https://company.stb-tester.com/app/#/result//stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34',
  'start_time': '2015-05-28T14:46:35.354791Z',
  'end_time': '2015-05-28T14:46:42.325432Z',
  'test_pack_sha': 'c2c82cad08114f973e2c36f0bbfbfb0a78dad911',
  'test_case': 'tests/epg.py::test_that_epg_is_populated',
  'result': 'fail',
  'failure_reason': 'EPG is empty'
 },
 {'result_id': '/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44'
  'job_uid': '/stb-tester-abcdef123456/0a23/972',
  'result_url': 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44',
  'triage_url': 'https://company.stb-tester.com/app/#/result//stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44',
  'start_time': '2015-05-28T14:46:45.431553Z',
  'end_time': '2015-05-28T14:46:49.334224Z',
  'test_pack_sha': 'c2c82cad08114f973e2c36f0bbfbfb0a78dad911',
  'test_case': 'tests/epg.py::test_that_epg_is_populated',
  'result': 'pass',
  'failure_reason': None
 }
]
Query Parameters:
  • filter – A search expression in the same format as the interactive search box in the test-results web interface, documented here. If not specified it will return all results (up to a limit of 2,000 results).

  • sort – “<fieldname>:asc” or “<fieldname>:desc”. Sort results by the specified field in ascending or descending order. <fieldname> can be “category”, “date”, “duration”, “job”, “testcase”, or “result”. Defaults to “date:desc”.

  • tz – A name like “America/Denver” from the Olson timezone database. This is the default timezone used for any dates specified in the filter parameter if the timezone isn’t explicit in those dates. Defaults to “UTC”.

The response consists of a JSON array of JSON objects. Each object corresponds to a test run. Each object contains a subset of the fields from /api/v2/results/(result_id):

Response JSON Object:
  • result_id (string) – Identifier that refers to this test result. This is unique across all Stb-tester devices in your test farm.

  • result_url (string) – The REST API URL of this test result. You can use this URL to retrieve more information about the test run – see /api/v2/results/(result_id). You can also retrieve test artifacts such as logs and screenshots by appending /artifacts/(filename) to the url.

  • triage_url (string) – The URL of this test result in the portal, for viewing in a web browser.

  • job_uid (string) – Identifier that refers to this test job. See /api/v2/jobs/(job_uid).

  • start_time (string) – The time at which the test run started as an ISO8601 formatted datetime (for example "2015-05-28T14:46:35.354791Z").

  • end_time (string) – The time at which the test run finished as an ISO8601 formatted datetime.

  • test_case (string) – The name of the testcase as given to /api/v2/run_tests.

  • test_pack_sha (string) – The git sha of the test-pack revision as given to /api/v2/run_tests.

  • result (string) –

    One of the following values:

    • pass – the testcase completed and passed.

    • fail – the testcase completed but failed.

    • error – the testcase couldn’t complete due to an error (see Exceptions in the Python API reference).

  • failure_reason (string) – The exception message when the test failed. null if the test passed.

Response Headers:
Status Codes:

Get list of test results (CSV)#

GET /api/v2/results.csv#

Takes the same parameters as /api/v2/results but returns CSV format (comma-separated values, suitable for opening with Excel) instead of JSON.

Get list of test results (XML)#

GET /api/v2/results.xml#

Takes the same parameters as /api/v2/results but returns XML data (in jUnit format, which Jenkins knows how to interpret) instead of JSON. Also accepts the following additional parameter:

Query Parameters:
  • include_tz – Include timezone information in the XML’s ISO8601 timestamps. This should be set to “true” unless the code interpreting the XML cannot cope with timezone information. Defaults to “false”, but this default may change in the future if no incompatible software is discovered — so you should always set this parameter.

Get detailed information about a test run#

GET /api/v2/results/(result_id)/#

Retrieve detailed information about a test result.

Example using Python requests:

response = requests.get(
    'https://company.stb-tester.com/api/v2/results/' +
    'stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44')
print response.json()
{'result_id': '/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34'
 'job_uid': '/stb-tester-abcdef123456/0a23/972',
 'result_url': 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34',
 'triage_url': 'https://company.stb-tester.com/app/#/result//stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34',
 'start_time': '2015-05-28T14:46:35.354791Z',
 'end_time': '2015-05-28T14:46:42.325432Z',
 'test_case': 'tests/epg.py::test_that_epg_is_populated',
 'test_pack_branch': 'refs/heads/master',
 'test_pack_sha': 'c2c82cad08114f973e2c36f0bbfbfb0a78dad911',
 'username': 'johnsmith',
 'result': 'fail',
 'failure_reason': 'EPG is empty',
 'job_category': 'example',
 'traceback': '''Traceback (most recent call last):
  File "/usr/lib/stbt/stbt-run", line 88, in <module>
    function()
  File "tests/epg.py", line 24, in test_that_epg_is_populated
    assert epg_is_populated(), "EPG is empty"
AssertionError: EPG is empty''',
 'artifacts': {
     'combined.log': {'size': 39381},
     'screenshot.png': {'size': 196119},
     'stderr.log': {'size': 39161},
     'stdout.log': {'size': 220},
     'thumbnail.jpg': {'size': 15220},
     'video.mp4': {'size': 262863},
     'my-custom-logfile.log': {'size': 52023},
     'a/file in a subdirectory/another.log': {'size': 2433}
 },
 'tags': {'model': 'T-1000'}
}
Parameters:
  • result_id – Identifier that refers to this test result, as returned from /api/v2/results. This is unique across all Stb-tester devices in your test farm.

The response consists of a JSON object, with the following elements:

Response JSON Object:
  • result_id (string) – Identifier that refers to this test result. This is unique across all Stb-tester devices in your test farm.

  • result_url (string) – The REST API URL of this test result.

  • triage_url (string) – The URL of this test result in the portal, for viewing in a web browser.

  • job_uid (string) – Identifier that refers to this test job. See /api/v2/jobs/(job_uid).

  • start_time (string) – The time at which the test run started as an ISO8601 formatted datetime (for example "2015-05-28T14:46:35.354791Z").

  • end_time (string) – The time at which the test run finished as an ISO8601 formatted datetime.

  • test_case (string) – The name of the testcase as given to /api/v2/run_tests.

  • test_pack_sha (string) – The git sha of the test-pack revision given to /api/v2/run_tests.

  • test_pack_branch (string) – The git “ref” name of the test-pack branch. If you specified a git sha instead of a branch name when you submitted /api/v2/run_tests, then this will be null.

  • username (string) – The user who started the test-job.

  • result (string) –

    One of the following values:

    • pass – the testcase completed and passed.

    • fail – the testcase completed but failed.

    • error – the testcase couldn’t complete due to an error (see Exceptions in the Python API reference).

  • failure_reason (string) – The exception message when the test failed. null if the test passed.

  • job_category (string) – The category as passed to /api/v2/run_tests when the tests were run.

  • traceback (string) – The traceback of the exception that caused the test to fail. null if the test passed.

  • artifacts (object) – The files created during the test run. See /api/v2/results/(result_id)/artifacts/ for details.

  • tags (object) – A mapping of name:value tags as given to /api/v2/run_tests.

Response Headers:
Status Codes:

Get log output from test run#

GET /api/v2/results/(result_id)/stbt.log#

Retrieve the output of the test run. This includes logging from stb-tester and any lines printed (written to stderr or stdout) by your Python code during the test run.

Each line consists of an ISO8601 datetime, followed by a space, followed by the message logged by your test script. For example:

2015-06-18T14:59:00.321421+00:00 A message printed by the test script

The file is served as utf-8, so you shouldn’t log invalid utf-8 byte sequences from your test script.

Example using Python requests:

Show the output of a test run:

result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44'
response = requests.get('%s/stbt.log' % result_url',
                        params={'tz': 'America/Denver'})
print response.text
2015-06-16T07:29:17.162452-06:00 stbt-run: Arguments:
2015-06-16T07:29:17.162615-06:00 control: lirc:172.17.0.133:8765:vstb
2015-06-16T07:29:17.162646-06:00 args: ['test_that_when_pressing_back_i_go_back_to_where_i_was_before_action_panel_epg']
2015-06-16T07:29:17.162673-06:00 verbose: 1
2015-06-16T07:29:17.162701-06:00 source_pipeline: ximagesrc use-damage=false remote=true show-pointer=false display-name=:10 ! video/x-raw,framerate=24/1
2015-06-16T07:29:17.162728-06:00 script: /var/lib/stbt/test-pack/tests/brand_rollups.py
2015-06-16T07:29:17.162754-06:00 restart_source: False
2015-06-16T07:29:17.162781-06:00 sink_pipeline: fakesink sync=false
2015-06-16T07:29:17.162808-06:00 write_json: stbt-run.json
2015-06-16T07:29:17.162835-06:00 save_video: video.webm
2015-06-16T07:29:17.212650-06:00 stbt-run: Saving video to 'video.webm'
Parameters:
  • result_id – The desired result’s identifier, as returned from /api/v2/results.

Query Parameters:
  • tz – A name like “America/Denver” from the Olson timezone database. The timestamp at the beginning of each log line will be displayed in this timezone. Defaults to “UTC”.

Response Headers:
Status Codes:

Get screenshot saved at end of test run#

GET /api/v2/results/(result_id)/screenshot.png#

At the end of each test-run stb-tester saves a screenshot (in a lossless format) from the device under test. This can be useful for performing automated triage or as a source of new reference images.

This endpoint retrieves that screenshot.

Example usage:

Save the screenshot to disk as screenshot.png, using curl from the command line:

curl -O "https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44/screenshot.png"

Save the screenshot to disk from Python code, using the urllib module from the Python standard library:

import urllib
result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44'
urllib.urlretrieve('%s/screenshot.png' % result_url, 'screenshot.png')

View the screenshot in IPython notebook, using the Python requests library:

import IPython.display, requests
result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44'
response = requests.get('%s/screenshot.png' % result_url)
IPython.display.Image(data=response.content)

Try a stbt.match against the saved screenshot:

import cv2, numpy, requests, stbt
result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44'
response = requests.get('%s/screenshot.png' % result_url)
image = cv2.imdecode(numpy.frombuffer(response.content, dtype='uint8'), 1)
print stbt.match('my-reference.png', frame=image)
MatchResult(timestamp=None, match=False, region=Region(x=82, y=48, width=54, height=54), first_pass_result=0.942756436765, frame=1280x720x3, image='my-reference.png')
Parameters:
  • result_id – The desired result’s identifier, as returned from /api/v2/results.

Response Headers:
Status Codes:

List artifacts produced during a test run#

GET /api/v2/results/(result_id)/artifacts/#

List the files saved during a test run. This includes files written by stb-tester and any files written by your test scripts into the current working directory while the test is running.

Note: The files that stb-tester writes may change depending on the value of test_pack.stbt_version in .stbt.conf. It is therefore recommended to only rely on this endpoint to retrieve test artifacts that the test-scripts explicitly write and to use the values of /api/v2/results/(result_id) for data provided by stb-tester.

Example using Python requests:

List the files produced by a test run.

result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44'
response = requests.get('%s/artifacts/ % result_url')
print response.json()
{
  'combined.log': {'size': 39381},
  'screenshot.png': {'size': 196119},
  'stderr.log': {'size': 39161},
  'stdout.log': {'size': 220},
  'thumbnail.jpg': {'size': 15220},
  'video.mp4': {'size': 262863},
  'my-custom-logfile.log': {'size': 52023},
  'a/file in a subdirectory/another.log': {'size': 2433}
}
Parameters:
  • result_id – The desired result’s identifier, as returned from /api/v2/results.

The response is a JSON object. The keys of the object are filenames and the values are dictionaries containing additional information about the files. Files in subdirectories are also listed, but the directories themselves won’t appear in the listing.

The information about each file is:

Response JSON Object:
  • size (string) – The size of the file in bytes.

Response Headers:
Status Codes:

Get an artifact produced during a test run#

GET /api/v2/results/(result_id)/artifacts/(filename)#

Retrieve files recorded during a test run.

For examples see the examples for the screenshot endpoint.

Parameters:
  • result_id – The desired result’s identifier, as returned from /api/v2/results.

  • filename – The name of the file to retrive.

The response consists of the contents of a file given by filename recorded during a test run.

Response Headers:
  • Content-Type – Varies depending on the filename extension.

Status Codes:

Test farm node information#

Get status of all nodes#

GET /api/v2/nodes#

List all the Stb-tester devices in your test farm. The response is a JSON list of objects, one for each Stb-tester Node. See Get a node’s current status, below, for documentation about these objects.

Example using Python requests:

response = requests.get(
   'https://company.stb-tester.com/api/v2/nodes',
   headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
print(response.json())
[
    {
        "node_id": "stb-tester-abcdef123456",
        "available": false,
        ... etc ...
    },
    ... more nodes ...
]
Response Headers:
Status Codes:

Get a node’s current status#

GET /api/v2/nodes/(node_id)#

Get information about an Stb-tester device in your test farm. This includes information about the node’s configuration in git, the test job that it is running, and its active reservation, if any.

Example using Python requests:

node_id = "stb-tester-abcdef123456"
response = requests.get(
   'https://company.stb-tester.com/api/v2/nodes/' + node_id,
   headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
print(response.json())
{
   "available": false,
   "config": {
      "node": {
         "friendly_name": "Rack 3, Node 1"
      },
      "device_under_test": {
         "device_type": "roku",
         "ip_address": "192.168.1.108"
      }
   },
   "device_type": "roku",
   "external_ip_address": "1.2.3.4",
   "friendly_name": "Rack 3, Node 1",
   "geoip_city": "London",
   "geoip_country": "United Kingdom",
   "job": {
      "end_time": "2023-02-18T21:53:15.908299+00:00",
      "job_uid": "/stb-tester-abcdef123456/0000/319",
      "job_url": "https://company.stb-tester.com/api/v2/jobs/stb-tester-abcdef123456/0000/319",
      "log_url": "https://company.stb-tester.com/api/v2/jobs/stb-tester-abcdef123456/0000/319/log",
      "result_counts": {
         "error": 1,
         "fail": 0,
         "pass": 0,
         "total": 1
      },
      "start_time": "2023-02-18T21:52:26.139210+00:00",
      "status": "exited",
      "triage_url": "https://company.stb-tester.com/app/#/results?filter=job:/stb-tester-abcdef123456/0000/319"
   },
   "last_used_by": "johnsmith",
   "last_used_time": "2023-02-22T14:25:02.156078+00:00",
   "licence_expiry": "2024-01-31",
   "local_ip_address": "192.168.1.101",
   "node_id": "stb-tester-abcdef123456",
   "node_url": "https://company.stb-tester.com/api/v2/nodes/stb-tester-abcdef123456",
   "not_available_reason": "Node stb-tester-abcdef123456 reserved by @johnsmith",
   "online": false,
   "reservation": {
      "expires": "2023-02-22T16:56:11+00:00",
      "message": "Overnight DVR soak",
      "message_html": "<p>Overnight DVR soak</p>",
      "node_id": "stb-tester-abcdef123456",
      "reservation_id": 6,
      "reserved_by_you": true,
      "start_time": "2023-02-22T15:56:11+00:00",
      "username": "johnsmith"
   }
}
Parameters:
  • node_id – The node ID (e.g. “stb-tester-abcdef123456”)

Response JSON Object:
  • available (bool) –

    true if this node can be reserved. This will be false if the node is offline, reserved (even if it’s reserved by you), running a test, licence expired, has a pending software update, etc. See not_available_reason below.

    Note: Reserving a node may still fail, if someone else has reserved it between the time you checked available and the time you tried to reserve it.

  • config (object) – Configuration from the node-specific config file in git (on your main branch). This only includes node-specific configuration and doesn’t include the global configuration from stbt.conf.

  • device_type (string or null) – The type of device under test, taken from the node-specific config file in git (on your main branch). This will be null if this configuration value is not set.

  • external_ip_address (string or null) – The IP address that the node is currently using to connect to the portal from the perspective of the portal. This will be null if the portal has never seen this node. This will typically be a public IP address.

  • friendly_name (string or null) – The friendly name of the node taken from the node-specific config file in git (on your main branch). This will be null if this configuration value is not set.

  • geoip_city (string or null) – The physical location (city) of the node, as determined by geo-ip lookup using external_ip_address. See Location data. This will be null if the portal has never seen this node, if the IP address is not in the geo-ip database, or if the city can’t be determined from the IP address. This information may be incorrect or change in a backward incompatible manner so shouldn’t be relied upon.

  • geoip_country (string or null) – The physical location (country) of the node, as determined by geo-ip lookup using external_ip_address. See the caveats under geoip_city, above.

  • job (object or null) – The job that is currently running on the node, or the last job that ran on the node. This will be null if the node has never run a job. For the description of each field see Inspect a test job.

  • local_ip_address (string or null) – The IP address of the node’s network interface. This will be null if the portal has never seen this node. This will typically be a private IP address (e.g. 10.x.x.x or 192.168.x.x)

  • last_used_by (string or null) – The username of the last user to use the node by running or stopping a job, using the manual remote control, making a reservation, grabbing a screenshot, etc. This will be null if the node has never been used.

  • last_used_time (string or null) – The date and time that the node was last used, in ISO8601 format. This will be null if the node has never been used.

  • licence_expiry (string) – The date that the node’s licence expires, in ISO8601 format.

  • node_id (string) – The node ID (e.g. “stb-tester-abcdef123456”).

  • node_url (string) – The URL of this node’s API endpoint.

  • not_available_reason (string or null) – Human-readable reason why available is false. This will be null if available is true.

  • online (boolean) – Whether the node is currently online (powered on and can connect to the portal). See Troubleshooting: My Stb-tester node is offline.

  • reservation (object or null) – The reservation that is currently held on the node. This will be null if the node is not currently reserved. For documentation about this object see Reservations.

Response Headers:
Status Codes:

Reservations#

You can “reserve” an Stb-tester Node so that other users can’t start test jobs, stop test jobs, or use the manual remote control.

Your reservation is held until you end it using the End a reservation endpoint, or until it expires; you can Extend a reservation before it expires.

Other users can interrupt your reservation. In this way, reservations are advisory — any user can interrupt any other user’s reservation.

Reserve nodes for exclusive use#

POST /api/v2/reservations#

Reserve one or more nodes.

This API is atomic: You will reserve all nodes, or none of them. If any of the nodes is in use (because it is already reserved or busy running a test-job), the request will fail with “409 Conflict”.

Example using Python requests:

Reserve two nodes for 12 hours:

response = requests.post(
    "https://company.stb-tester.com/api/v2/reservations",
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"},
    json={
        "node_ids": ["stb-tester-000000000001", "stb-tester-000000000002"],
        "message": "Reserved for overnight DVR soak\n\nSee JIRA-12345 for details",
        "duration_secs": 12 * 60 * 60,
    })
print(response.json())
{
   "reservations": [
      {
         "expires": "2023-02-07T12:22:16+00:00",
         "message": "Reserved for overnight DVR soak\n\nSee JIRA-12345 for details",
         "message_html": "<p>Reserved for overnight DVR soak</p>\n<p>See JIRA-12345 for details</p>",
         "node_id": "stb-tester-000000000001",
         "reservation_id": 2,
         "reserved_by_you": true,
         "start_time": "2023-02-07T11:22:16+00:00",
         "username": "johnsmith"
      },
      {
         "expires": "2023-02-07T12:22:16+00:00",
         "message": "Reserved for overnight DVR soak\n\nSee JIRA-12345 for details",
         "message_html": "<p>Reserved for overnight DVR soak</p>\n<p>See JIRA-12345 for details</p>",
         "node_id": "stb-tester-000000000002",
         "reservation_id": 3,
         "reserved_by_you": true,
         "start_time": "2023-02-07T11:22:16+00:00",
         "username": "johnsmith"
      }
   ]
}
Request JSON Object:
  • node_ids (array) – (mandatory) Which Stb-tester devices to reserve.

  • message (string) – (mandatory) Message that will be displayed to other users in the Stb-tester Portal while the reservation is active.

  • duration_secs (int) – (optional) Duration of the reservation in seconds. After this time, the reservation will end automatically. null (or unspecified) means that the reservation will never expire.

Response JSON Object:
  • reservations (array) –

    List of the reservations created by this request. This an array of objects with the same length as node_ids. Each object has the following fields:

    • reservation_id (int) – An identifier that uniquely identifies this reservation.

    • node_id (string) – The node that was reserved, for example "stb-tester-abcdef123456".

    • username (string) – The user who reserved the node.

    • start_time (string) – The time when the reservation started, in ISO8601 format.

    • expires (string) – The time when the reservation will expire, in ISO8601 format.

    • message (string) – The message that was given to the API.

    • message_html (string) – The message, converted from Markdown format to HTML.

    • reserved_by_you (bool) – Whether the reservation was made by the user who made this REST API request. This will always be true for the response to this request, but it will be false for other users querying the status of a reservation via other API endpoints.

Request Headers:
Response Headers:
Status Codes:

Extend a reservation#

POST /api/v2/reservations/(reservation_id)/extend#

Extend your reservation. This affects the expires field of the reservation.

Only the user who created the reservation can extend it.

Example using Python requests:

Extend a reservation by 10 minutes:

response = requests.post(
    "https://company.stb-tester.com/api/v2/reservations/%i/extend" % reservation_id,
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"},
    json={"duration_secs": 10 * 60})
Parameters:
Request JSON Object:
  • duration_secs (int) – (mandatory) Extend the reservation’s current expiry by this amount of seconds.

Request Headers:
Status Codes:

End a reservation#

DELETE /api/v2/reservations/(reservation_id)#

End a reservation. Call this when you have finished using the Stb-tester Node.

Only the user who created the reservation can use this endpoint. Other users must use the Interrupt a reservation endpoint.

Example using Python requests:

response = requests.delete(
    "https://company.stb-tester.com/api/v2/reservations/%i" % reservation_id,
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
Parameters:
Status Codes:

Interrupt a reservation#

POST /api/v2/reservations/(reservation_id)/interrupt#

Interrupt someone else’s reservation. Unlike End a reservation, this endpoint can be used by any user to end a reservation that was made by another user — but you must specify a message for the owner of the reservation.

Example using Python requests:

Interrupt a reservation that was created by the previous example:

response = requests.post(
    "https://company.stb-tester.com/api/v2/reservations/%i/interrupt" % reservation_id,
    headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"},
    json={"message": "Node needed for emergency regression testing\n\nSee JIRA-54321."})
Parameters:
Request JSON Object:
  • message (string) – (mandatory) Message that will be displayed to the owner of the reservation.

Request Headers:
Status Codes: