Skip to main content

TestingBot API Documentation

Access and modify all your TestingBot data through our comprehensive REST API. Build powerful integrations and automate your testing workflows.

Endpoint
api.testingbot.com
Version
v1
Format
JSON
Auth
HTTP Basic

API Clients

There are several open source client libraries available to easily interact with the TestingBot API:

Authentication

Every TestingBot API request is authenticated with your API key and API secret using HTTP Basic Auth over HTTPS. The only unauthenticated endpoint is GET /v1/browsers.

1 · Find your credentials

Sign in to TestingBot and open Account → Account Info. You'll find:

key string
Your public API client key. Safe to share between your CI and the TestingBot grid; not a secret on its own.
secret string sensitive
Treat this like a password. Never commit it to git, never paste it into screenshots, never embed it in client-side code. Use environment variables or a secret manager in CI.

2 · Send credentials on every request

Pass the credentials as the standard Authorization header. Most HTTP clients accept a user:password tuple and handle the Base64 encoding for you — examples on the right.

3 · Verify it works

Hit GET /v1/user. A JSON response with your name and plan means auth is set up correctly. A 401 Unauthorized means the key or secret is wrong.

Best practice. Store credentials in environment variables — TESTINGBOT_KEY and TESTINGBOT_SECRET — and inject them into your CI/CD pipeline as secrets. Rotate the secret immediately if it leaks (Account → Reset API credentials).
Authentication Examples
Authenticated request
$ curl https://api.testingbot.com/v1/user \
  -u "$TESTINGBOT_KEY:$TESTINGBOT_SECRET"
require 'testingbot'
api = TestingBot::Api.new(
  ENV['TESTINGBOT_KEY'],
  ENV['TESTINGBOT_SECRET']
)
api.get_user_info
import os, testingbotclient
tb = testingbotclient.TestingBotClient(
  os.environ['TESTINGBOT_KEY'],
  os.environ['TESTINGBOT_SECRET']
)
tb.user.get_user_information()
$api = new TestingBot\TestingBotAPI(
  getenv('TESTINGBOT_KEY'),
  getenv('TESTINGBOT_SECRET')
);
$api->getUserInfo();
TestingbotREST restApi = new TestingbotREST(
  System.getenv("TESTINGBOT_KEY"),
  System.getenv("TESTINGBOT_SECRET")
);
TestingbotUser user = restApi.getUserInfo();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key:    process.env.TESTINGBOT_KEY,
  api_secret: process.env.TESTINGBOT_SECRET
});

const userInfo = await api.getUserInfo();
GET /v1/browsers

List supported browsers

Returns every browser environment available on the TestingBot grid: name, version, platform, and the browser_id used when attaching browsers to Codeless tests. No authentication required.

Arguments

type string
Filter by automation protocol: "webdriver" (default) or "rc" (legacy Selenium RC).

Response fields

selenium_name string
Capability value to send as browserName in WebDriver.
name string
Human-readable browser identifier (e.g. "firefox", "iexplore").
version integer
Major version number.
long_version string
Full version string (e.g. "121.0.6167.184").
platform string
Operating system (e.g. "WINDOWS", "MAC", "LINUX").
browser_id integer
Unique TestingBot browser ID used to attach browsers to Codeless tests.
GET /v1/browsers
Request
curl "https://api.testingbot.com/v1/browsers"
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_browsers
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.information.get_browsers()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getBrowsers();
TestingbotREST restApi = new TestingbotREST(key, secret);
ArrayList<TestingbotBrowser> browsers = restApi.getBrowsers();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const browsers = await api.getBrowsers();
Response
[
  {"selenium_name": "IE8", "name": "iexplore", "version": 8, "platform": "WINDOWS", "browser_id": 1, "long_version": 8},
  {"selenium_name": "FF7", "name": "firefox", "version": 7, "platform": "WINDOWS", "browser_id": 22, "long_version": 7}
]
GET /v1/user

Get your user info

Returns the data associated with the authenticated account: name, plan, billing details, remaining credits, and concurrency caps.

Response fields

first_name string
Given name on the account.
last_name string
Family name on the account.
email string
Account email address.
plan string
Subscription plan identifier (e.g. "live", "automated", "automated pro").
max_concurrent integer
Maximum number of parallel VM-based sessions allowed by the plan.
max_concurrent_mobile integer
Maximum number of parallel physical device sessions allowed by the plan.
seconds integer
Remaining test seconds (credit balance) on the account.
last_login timestamp
ISO-8601 timestamp of the most recent dashboard login.
company string
Optional company name for billing.
street string
Billing address line.
city string
Billing city.
country string
Billing country.
vat string
VAT number (EU only).
GET /v1/user
Request
$ curl "https://api.testingbot.com/v1/user" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_user_info
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.user.get_user_information()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getUserInfo();
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotUser user = restApi.getUserInfo();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const userInfo = await api.getUserInfo();
Response
{
    "first_name": "Steven",
    "last_name": "King",
    "seconds": 17745,
    "plan": "small",
    "max_concurrent": 10,
    "max_concurrent_mobile": 2,
    "company": "companyName",
    "street": "companyStreet",
    "city": "companyCity",
    "country": "companyCountry",
    "vat": "ifInEurope"
}
PUT /v1/user

Update your user info

Updates the authenticated account. Only first_name and last_name are mutable through this endpoint; other profile fields require the dashboard.

Arguments

user[first_name] string
New given name.
user[last_name] string
New family name.

Response fields

success boolean
Whether the update was applied.
user object
Updated user object.
PUT /v1/user
Request
$ curl "https://api.testingbot.com/v1/user" \
-X PUT \
-d "user[first_name]=new" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.update_user_info({ "first_name" => 'new' })
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.user.update_user_information()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->updateUserInfo(array('first_name' => 'new'));
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotUser user = restApi.updateUserInfo(TestingBotUser);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const newUserData = { first_name: 'new' };
await api.updateUserInfo(newUserData);
Response
{
  "success": true,
  "user": {
    "first_name": "new",
    "last_name": "King",
    "seconds": 17745,
    "last_login": "2011-08-06T16:47:04Z"
  }
}
GET /v1/team-management

Get team concurrency info

Returns allowed vs current concurrent session counts for the team across both VMs and physical mobile devices. Useful for dashboards that surface "X of Y slots in use".

Response fields

concurrency object
Allowed vs current concurrency caps for the team, split in VM and physical device sessions.
GET /v1/team-management
Request
$ curl "https://api.testingbot.com/v1/team-management" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeam team = restApi.getTeam();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const teamInfo = await api.getTeam();
Response
{
  "concurrency": {
    "allowed": { "vms": 10, "physical": 2 },
    "current": { "vms": 4, "physical": 1 }
  }
}
GET /v1/team-management/users

List users in your team

Paginated list of all sub-accounts in the team. Requires admin role on the calling account.

Arguments

offset integer
Skip this many users from the start of the result set.
count integer max=500
Number of users to return .

Response fields

data array of team member objects
Team member accounts.
meta meta object
GET /v1/team-management/users
Request
$ curl "https://api.testingbot.com/v1/team-management/users" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeamMemberCollection members = restApi.getTeamMembers();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const users = await api.getUsersInTeam();
Response
{
  "data": [
    {
      "id": 337,
      "first_name": "test",
      "last_name": "user",
      "seconds": 12000,
      "plan": "Free Trial",
      "max_concurrent": 2,
      "max_concurrent_mobile": 2
    }
  ],
  "meta": { "offset": 0, "count": 1, "total": 1 }
}
GET /v1/team-management/users/:id

Get a specific team user

Returns the user record for a specific team member. Admins can fetch any team member; non-admins can only fetch themselves.

Arguments

id integer required
Numeric ID of the team user to fetch.

Response fields

id integer
Unique numeric user ID.
first_name string
Given name.
last_name string
Family name.
email string
Account email.
credits integer
Remaining VM credit seconds.
device_credits integer
Remaining physical-device credit seconds.
isPaid boolean
Whether the account has an active paid plan.
verified boolean
Whether the account email has been verified.
parent_id integer
Parent (team owner) user ID; 0 means this user is the team owner.
GET /v1/team-management/users/:id
Request
$ curl "https://api.testingbot.com/v1/team-management/users/:id" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeamMember member = restApi.getTeamMember(userId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const user = await api.getUserFromTeam(userId);
Response
{
  "id": 337,
  "first_name": "test",
  "last_name": "user",
  "seconds": 12000,
  "plan": "Free Trial",
  "max_concurrent": 2,
  "max_concurrent_mobile": 2
}
POST /v1/team-management/users

Create a user in your team

Provisions a new sub-account inside the team, copying the caller's subscription level and assigning a slice of the credit pool. Requires an upgraded plan and admin role.

Arguments

email string required
Email address for the new account; must be unique across TestingBot.
password string required
Initial password for the new user.
first_name string
New user's given name.
last_name string
New user's family name.
concurrency integer
Max parallel VM sessions (≤ team owner's maxParallel).
concurrencyPhysical integer
Max parallel physical-device sessions (≤ team owner's maxParallelDevice).
POST /v1/team-management/users
Request
$ curl -X POST -u key:secret \
  https://api.testingbot.com/v1/team-management/users \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "first_name": "Bruno",
    "last_name": "Mars",
    "email": "bmars@example.com",
    "password": "$bmaRs*RULES"
  }'
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("first_name", "Bruno");
params.put("last_name", "Mars");
params.put("email", "bmars@example.com");
params.put("password", "$bmaRs*RULES");
TestingbotTeamMember member = restApi.createTeamMember(params);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const userData = {
  first_name: 'John',
  last_name: 'Doe',
  email: 'john@example.com',
  password: 'StrongPassword!'
};

const result = await api.createUserInTeam(userData);
Response
{
  "id": 337,
  "first_name": "Bruno",
  "last_name": "Mars",
  "seconds": 12000,
  "plan": "Free Trial",
  "max_concurrent": 2,
  "max_concurrent_mobile": 2
}
PUT /v1/team-management/users/:id

Update a user in your team

Updates a team user's profile and credit allocation. Credit fields cannot exceed the team owner's remaining balance.

Arguments

id integer required
Numeric ID of the team user to update.
first_name string
New given name.
last_name string
New family name.
email string
New email address.
password string
New password.
credits integer
Allocated VM credit seconds (≤ team owner's remaining VM credits).
device_credits integer
Allocated physical-device credit seconds (≤ team owner's remaining device credits).
concurrency integer
Max parallel VM sessions for this user.
concurrencyPhysical integer
Max parallel physical-device sessions for this user.

Response fields

id integer
Unique numeric user ID.
first_name string
Given name.
last_name string
Family name.
email string
Account email.
credits integer
Remaining VM credit seconds.
device_credits integer
Remaining physical-device credit seconds.
isPaid boolean
Whether the account has an active paid plan.
verified boolean
Whether the account email has been verified.
parent_id integer
Parent (team owner) user ID; 0 means this user is the team owner.
PUT /v1/team-management/users/:id
Request
$ curl -X PUT -u key:secret \
  https://api.testingbot.com/v1/team-management/users/:id \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "first_name": "Bruno",
    "last_name": "Mars"
  }'
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("first_name", "Bruno");
params.put("last_name", "Mars");
TestingbotTeamMember member = restApi.updateTeamMember(userId, params);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const result = await api.updateUserInTeam(userId, { first_name: 'Jane', last_name: 'Smith' });
Response
{
  "id": 337,
  "first_name": "Bruno",
  "last_name": "Mars",
  "seconds": 12000,
  "plan": "Free Trial"
}
POST /v1/team-management/users/:id/reset-keys

Reset credentials for a team user

Rotates both the API key and secret for a team user. The old credentials stop working immediately, so any deployed automation using them must be updated.

Arguments

id integer required
Numeric ID of the team user whose credentials to rotate.
POST /v1/team-management/users/:id/reset-keys
Request
$ curl -X POST -u key:secret \
  https://api.testingbot.com/v1/team-management/users/:id/reset-keys
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeamCredentialReset reset = restApi.resetTeamMemberKeys(userId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const result = await api.resetCredentials(userId);
Response
{
  "success": true,
  "client_key": "d69e0800xc32ed2f059b7a630ee255b"
}
GET /v1/tests

List your tests

Paginated list of every test session belonging to the authenticated account, newest first. Filter by browser_id, group, or build to narrow the result. Use since to fetch only tests updated after a UNIX timestamp (poll-friendly).

Arguments

offset integer
Skip this many tests from the start of the result set.
count integer max=500
Number of tests to return .
since integer
UNIX timestamp; return only tests updated at or after this time.
browser_id integer
Filter to tests that ran on this browser_id (from /v1/browsers).
group string
Filter to tests tagged with this group name.
build string
Filter to tests in this build (matches capabilities.build).
skip_fields string
Comma-separated fields to omit (logs, thumbs).

Response fields

data array of test case objects
Test sessions for this page.
meta meta object
GET /v1/tests
Request
$ curl "https://api.testingbot.com/v1/tests?offset=0&count=10" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_tests(0, 10)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tests.get_tests(offset=0, limit=10)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getJobs(0, 10);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTestCollection tests = restApi.getTests(0, 10);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const tests = await api.getTests({ offset, limit });
Response
{
  "data": [
    {
      "created_at": "2011-07-30T23:21:23Z",
      "completed_at": "2011-07-30T23:22:44Z",
      "id": 3,
      "name": "MyTest::testTitle",
      "session_id": "f7903f9e93e74fe1b0e924bf9d2ce9fc",
      "status_message": "Failed asserting that 1 equals 0.",
      "status_id": 0,
      "success": false,
      "browser": "iexplore",
      "browser_version": 8,
      "os": "WINDOWS",
      "duration": 13,
      "build": "buildid",
      "video": "https://s3.amazonaws.com/rectestingbot/sample.mp4",
      "groups": ["testingbot.com"]
    }
  ],
  "meta": { "offset": 0, "count": 10, "total": 789 }
}
GET /v1/tests/:id

Get a specific test

Returns the full detail record for a single test session: status, environment (browser/OS or device/platform), assets (video, logs, screenshots), groups, build, and duration. Accepts either the numeric test ID or the WebDriver session_id.

Arguments

id string required
Numeric test ID or WebDriver session_id (UUID).
skip_fields string
Comma-separated fields to omit from the response (logs, thumbs, visual_run, groups).

Response fields

id integer
Unique numeric test ID.
session_id string
Selenium / WebDriver session ID (UUID).
name string
Human-readable test name set via capabilities or update_test.
state string
Lifecycle state (RUNNING, COMPLETE, TIMEOUT, …).
success boolean
Whether the test passed.
status_id integer
Numeric status code (0=fail, 1=pass, 2=unknown).
status_message string
Failure reason or arbitrary status set via test[status_message].
created_at timestamp
When the test session started.
completed_at timestamp
When the session ended; null while running.
duration integer
Total run time in seconds.
browser string
Browser identifier (e.g. "iexplore", "firefox").
browser_version integer
Browser major version.
os string
OS (e.g. "WINDOWS", "MAC").
device_name string
Mobile device name when the session ran on a physical device; null otherwise.
platform_name string
Mobile OS name; null on desktop.
build string
Build identifier (free-form string set via capabilities).
groups array of string
Tag/group names attached to the test.
video string
Signed S3 URL to the recorded video, or false if video was disabled.
thumbs array of string
Signed S3 URLs to screenshot thumbnails.
logs object
Map of log names → signed S3 URLs (selenium, browser, …).
assets_available boolean
Whether assets (video, logs, screenshots) have finished processing.
extra string
Arbitrary metadata string set via test[extra].
type string
Driver type (WEBDRIVER, APPIUM).
GET /v1/tests/:id
Request
$ curl "https://api.testingbot.com/v1/tests/:id" -u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_test(test_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tests.get_test(test_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getJob($test_id);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTest test = restApi.getTest(test_id);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const test = await api.getTestDetails(testId);
Response
{
  "id": 3,
  "name": "MyTest::testTitle",
  "session_id": "f7903f9e93e74fe1b0e924bf9d2ce9fc",
  "state": "COMPLETE",
  "success": false,
  "status_id": 0,
  "status_message": "Failed asserting that 1 equals 0.",
  "created_at": "2011-07-30T23:21:23Z",
  "completed_at": "2011-07-30T23:22:23Z",
  "duration": 60,
  "browser": "iexplore",
  "browser_version": 8,
  "os": "WINDOWS",
  "device_name": null,
  "platform_name": null,
  "build": null,
  "groups": ["testingbot.com"],
  "video": "https://s3.amazonaws.com/rectestingbot/sample.mp4",
  "thumbs": ["https://s3.amazonaws.com/euthumbtestingbot/3_f93782fji.jpg"],
  "logs": { "selenium": "https://s3-eu-west-1.amazonaws.com/eulogtestingbot/session.txt" },
  "assets_available": true,
  "type": "WEBDRIVER"
}
PUT /v1/tests/:id

Update a test

Updates a test's metadata after it's been recorded. Use this to mark a test as passed/failed from the test runner, attach groups/tags, set a build identifier, or add a status message. Accepts either a numeric test ID or a WebDriver session_id.

Arguments

id string required
Numeric test ID or WebDriver session_id (UUID).
test[name] string
Human-readable test name.
test[success] boolean
true=pass, false=fail.
test[status_message] string
Failure reason or arbitrary status text.
test[extra] string
Arbitrary metadata.
test[build] string
Build identifier to associate this test with.
test[public] boolean
When true, makes the test publicly viewable via share URL.
groups string
Comma-separated string or array of tag/group names to attach to the test.
build string
Build identifier (alternative location to test[build]).
PUT /v1/tests/:id
Request
$ curl "https://api.testingbot.com/v1/tests/:id" \
-X PUT \
-d "test[success]=1" \
-d "groups[]=regression" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.update_test(test_id, { name: 'new_name', success: true })
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tests.update_test(test_id, status_message='..', passed=1, build='..', name='..')
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->updateJob($test_id, ['name' => 'mytest', 'success' => true]);
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.updateTest(testId, details);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

await api.updateTest({ 'test[success]': '1', 'test[status_message]': 'failure reason' }, testId);
Response
{
  "success": true
}
DELETE /v1/tests/:id

Delete a test

Permanently deletes a test session and every associated asset (video, logs, screenshots). This action cannot be undone.

Arguments

id string required
Numeric test ID or WebDriver session_id of the test to delete.
DELETE /v1/tests/:id
Request
$ curl "https://api.testingbot.com/v1/tests/:id" \
-X DELETE \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.delete_test(test_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tests.delete_test(test_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->deleteJob($test_id);
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteTest(testId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

await api.deleteTest(testId);
Response
{
  "success": true
}
PUT /v1/tests/:id/stop

Stop a running test

Terminates an in-flight test session. The test is marked complete; any assets gathered (video, logs, screenshots) become available for download. Returns 404 if the test has already finished.

Arguments

id string required
Numeric test ID or WebDriver session_id of the test to stop.
PUT /v1/tests/:id/stop
Request
$ curl "https://api.testingbot.com/v1/tests/:id/stop" \
-X PUT \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.stop_test(test_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tests.stop_test(test_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->stopJob($test_id);
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.stopTest(testId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

await api.stopTest(testId);
Response
{
  "success": true
}
GET /v1/builds

List your builds

Returns a paginated list of test builds. A build is an aggregation of test cases that share the same capabilities.build identifier, useful for grouping CI runs.

Arguments

offset integer
Skip this many builds from the start of the result set.
count integer max=500
Number of builds to return .

Response fields

data array of build objects
Builds for this page.
meta meta object
GET /v1/builds
Request
$ curl "https://api.testingbot.com/v1/builds?offset=0&count=10" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_builds(0, 10)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.build.get_builds(offset=0, limit=10)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getBuilds(0, 10);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotBuildCollection builds = restApi.getBuilds(0, 10);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const builds = await api.getBuilds(offset, limit);
Response
{
  "data": [
    {
      "id": 4331,
      "build_identifier": "first-build",
      "created_at": "2016-08-01T11:09:02.000Z",
      "updated_at": "2016-08-01T11:09:02.000Z"
    }
  ],
  "meta": { "offset": 0, "count": 10, "total": 3 }
}
GET /v1/builds/:id

Get tests for a build

Returns all test cases that belong to a single build, with pagination. The build can be referenced by either its numeric internal ID or the string identifier you set via capabilities.build.

Arguments

id string required
Numeric build ID or string build identifier.
offset integer
Skip this many tests in the build.
count integer max=500
Number of tests to return .
skip_fields string
Comma-separated fields to omit from each test (logs, thumbs).

Response fields

data array of test case objects
Test sessions for this page.
meta meta object
GET /v1/builds/:id
Request
$ curl "https://api.testingbot.com/v1/builds/:id" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_build(build_identifier)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.build.get_tests_for_build(build_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getBuild($build_id);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTestBuildCollection tests = restApi.getTestsForBuild(buildId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const tests = await api.getTestsForBuild(buildId);
Response
{
  "data": [
    {
      "id": 3,
      "name": "MyTest::testTitle",
      "session_id": "f7903f9e93e74fe1b0e924bf9d2ce9fc",
      "state": "COMPLETE",
      "success": false,
      "status_id": 0,
      "created_at": "2011-07-30T23:21:23Z",
      "completed_at": "2011-07-30T23:22:44Z",
      "duration": 13,
      "browser": "iexplore",
      "browser_version": 8,
      "os": "WINDOWS",
      "build": "buildid",
      "video": "https://s3.amazonaws.com/rectestingbot/sample.mp4"
    }
  ],
  "meta": { "offset": 0, "count": 10, "total": 1 }
}
DELETE /v1/builds/:id

Delete a build

Permanently deletes a build and every test, asset (video, logs, screenshots) attached to it. This action cannot be undone.

Arguments

id string required
Numeric build ID or string build identifier to delete.
DELETE /v1/builds/:id
Request
$ curl "https://api.testingbot.com/v1/builds/:id" \
-X DELETE \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.delete_build(build_identifier)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.build.delete_build(build_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->deleteBuild($build_id);
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteBuild(buildId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

await api.deleteBuild(buildId);
Response
{
  "success": true
}
GET /v1/devices

List physical mobile devices

Returns every real Android and iOS device in the TestingBot grid, with an available flag indicating whether it can be acquired right now. Filter by platform for a single OS family.

Arguments

platform string
Filter to a single mobile OS family. Case-insensitive.
web boolean
Internal flag used by the dashboard — returns extra UI-only fields.

Response fields

id integer
Unique numeric device ID.
name string
Marketing name (e.g. "iPhone 15 Pro").
model string
Device model identifier.
manufacturer string
OEM (e.g. "Apple", "Samsung").
platform_name string
Mobile OS family (e.g. "iOS", "Android").
platform_version string
OS version (e.g. "17.4", "14").
screen_size string
Display size in inches (e.g. "6.1").
screen_resolution string
Display resolution (e.g. "1170x2532").
GET /v1/devices
Request
$ curl -u key:secret "https://api.testingbot.com/v1/devices"
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_devices
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.information.get_devices()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getDevices();
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotDevice> devices = restApi.getDevices(0, 100);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const devices = await api.getDevices();
Response
[
  {
    "id": 1,
    "available": true,
    "name": "Galaxy S8",
    "model_number": "SM-G950U1",
    "platform_name": "Android",
    "version": "9.0",
    "resolution": "1080x2220",
    "multiple_browsers": [
      { "id": 1727, "name": "chrome",   "version": "103" },
      { "id": 2133, "name": "firefox",  "version": "98.2" },
      { "id": 2953, "name": "samsung",  "version": "13.2.1.70" },
      { "id": 2954, "name": "opera",    "version": "67.1" }
    ]
  },
  {
    "id": 5,
    "available": false,
    "name": "iPhone XR",
    "platform_name": "iOS",
    "version": "16.3",
    "resolution": "828x1792"
  }
]
GET /v1/devices/available

List currently available devices

Subset of /v1/devices filtered to devices the authenticated account can acquire right now (not in use by another customer, not under maintenance).

Response fields

id integer
Unique numeric device ID.
name string
Marketing name (e.g. "iPhone 15 Pro").
model string
Device model identifier.
manufacturer string
OEM (e.g. "Apple", "Samsung").
platform_name string
Mobile OS family (e.g. "iOS", "Android").
platform_version string
OS version (e.g. "17.4", "14").
screen_size string
Display size in inches (e.g. "6.1").
screen_resolution string
Display resolution (e.g. "1170x2532").
GET /v1/devices/available
Request
$ curl -u key:secret "https://api.testingbot.com/v1/devices/available"
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_available_devices
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.information.get_available_devices()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getAvailableDevices();
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotDevice> devices = restApi.getAvailableDevices();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const devices = await api.getAvailableDevices();
Response
[
  {
    "id": 1,
    "available": true,
    "name": "Galaxy S8",
    "platform_name": "Android",
    "version": "9.0",
    "resolution": "1080x2220"
  }
]
GET /v1/devices/:id

Get a specific device

Returns the spec and current availability for a single device by numeric ID.

Arguments

id integer required
Numeric device ID.

Response fields

id integer
Unique numeric device ID.
name string
Marketing name (e.g. "iPhone 15 Pro").
model string
Device model identifier.
manufacturer string
OEM (e.g. "Apple", "Samsung").
platform_name string
Mobile OS family (e.g. "iOS", "Android").
platform_version string
OS version (e.g. "17.4", "14").
screen_size string
Display size in inches (e.g. "6.1").
screen_resolution string
Display resolution (e.g. "1170x2532").
GET /v1/devices/:id
Request
$ curl "https://api.testingbot.com/v1/devices/:id" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_device(device_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.information.get_device(device_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getDevice($deviceId);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotDevice device = restApi.getDevice(deviceId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const device = await api.getDevice(deviceId);
Response
{
  "id": 12,
  "available": true,
  "name": "Galaxy S20",
  "platform_name": "Android",
  "version": "10.0",
  "resolution": "1440x3200",
  "multiple_browsers": [
    { "id": 2598, "name": "chrome",  "version": "101" },
    { "id": 2919, "name": "firefox", "version": "98.2" },
    { "id": 2957, "name": "samsung", "version": "13.2.1.70" }
  ]
}
POST /v1/screenshots

Capture a new screenshot batch

Queues a cross-browser screenshot of a given URL at a specified resolution. Returns a batch ID you can poll via GET /v1/screenshots/:id.

Arguments

url string required
Page URL to screenshot.
resolution string required
Browser viewport (e.g. "1920x1080").
browsers array required
Array of { browser, version, os } triples (or browser_ids) to render with.
wait_time integer
Seconds to wait after page load before snapping.
fullpage boolean
Capture the entire scrollable page instead of just the viewport.
callback_url string
POST callback URL invoked when the batch finishes processing.
POST /v1/screenshots
Request
$ curl -H 'Content-Type: application/json' -X POST "https://api.testingbot.com/v1/screenshots" \
-u key:secret \
-d '{
  "url": "https://www.google.com",
  "resolution": "1280x1024",
  "browsers": [
    { "browserName": "chrome", "version": 134, "os": "WIN10" },
    { "browserName": "safari", "version": "17.2", "platformName": "iOS", "deviceName": "iPhone 15" }
  ]
}'
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("url", "https://www.google.com");
params.put("resolution", "1280x1024");
TestingbotScreenshot screenshots = restApi.createScreenshots(params);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const screenshots = await api.takeScreenshot(
  'https://example.com',
  [{ browserName: 'chrome', version: 'latest', os: 'WIN11' }],
  '1920x1080'
);
Response
{
  "id": 3454,
  "wait_time": 0,
  "resolution": "1280x1024",
  "url": "https://www.google.com"
}
GET /v1/screenshots/{id}

Get screenshot batch detail

Returns per-browser screenshot results for a single batch, including thumbnail/image URLs and processing state.

Arguments

id integer required
Numeric screenshot batch ID.
excludeIds string
Comma-separated screenshot IDs to exclude (useful for delta-fetch).

Response fields

id integer
Unique screenshot job ID.
url string
URL the screenshot was taken from.
state string
Processing state.
wait_time integer
Seconds the browser waited before snapping.
resolution string
Browser viewport resolution.
screenshots array of object
Per-browser screenshot results with download URLs.
created_at timestamp
GET /v1/screenshots/{id}
Request
$ curl "https://api.testingbot.com/v1/screenshots/{id}" -u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotScreenshot screenshot = restApi.getScreenshot(screenshotId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const screenshotResult = await api.retrieveScreenshots(screenshotJobId);
Response
{
  "state": "done",
  "screenshots": [
    {
      "image_url": "https://....",
      "thumb_url": "https://....",
      "state": "done",
      "id": "9c7deea4-6f23-4041-842b-39cccee447fa",
      "created_at": "2017-10-13T14:47:44.000Z",
      "os": "SEQUOIA",
      "browser_name": "googlechrome",
      "browser_version": "138",
      "browser_id": 1146
    }
  ]
}
GET /v1/screenshots

List screenshot batches

Returns batches of cross-browser screenshots the account has queued historically.

Arguments

offset integer
Skip this many batches.
count integer
Number of batches to return.

Response fields

data array of screenshot objects
meta meta object
GET /v1/screenshots
Request
$ curl "https://api.testingbot.com/v1/screenshots" -u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotScreenshotCollection screenshots = restApi.getScreenshots();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const screenshots = await api.getScreenshotList();
Response
{
  "data": [
    { "id": 3454, "url": "https://google.com", "resolution": "1280x1024" },
    { "id": 3452, "url": "https://testingbot.com", "resolution": "1280x1024" }
  ],
  "meta": { "offset": 0, "count": 3, "total": 3 }
}
GET /v1/tunnel/list

List active tunnels

Returns every TestingBot Tunnel currently running under the account. Use this to monitor running tunnels in CI dashboards or to find a tunnel ID before tearing it down.

Response fields

id integer
Unique numeric tunnel ID.
state string
Tunnel lifecycle state (READY, STOPPED, …).
launched timestamp
When the tunnel was launched.
tunnel_id string
Public tunnel identifier surfaced in the dashboard.
identifier string
Custom name passed via --tunnel-identifier on the client.
metadata object
Free-form metadata (client version, OS, region) reported by the tunnel binary.
GET /v1/tunnel/list
Request
$ curl "https://api.testingbot.com/v1/tunnel/list" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_tunnels
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tunnel.get_tunnels()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getTunnels();
TestingbotREST restApi = new TestingbotREST(key, secret);
ArrayList<TestingbotTunnel> tunnels = restApi.getTunnels();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const tunnels = await api.getTunnelList();
Response
[
  {
    "id": 1,
    "state": "READY",
    "ip": "xx",
    "private_ip": "xx",
    "requested_at": "2026-05-13 01:34:23"
  }
]
DELETE /v1/tunnel/{id}

Stop a tunnel

Tears down a running tunnel. Use this in CI teardown steps to release the slot for the next run; idle tunnels also self-terminate after the configured timeout.

Arguments

id integer required
Numeric tunnel ID to stop.
DELETE /v1/tunnel/{id}
Request
$ curl "https://api.testingbot.com/v1/tunnel/{id}" \
-X DELETE \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.delete_tunnel(tunnel_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.tunnel.delete_tunnel(tunnel_id)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->deleteTunnel($tunnelID);
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteTunnel(tunnelId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

await api.deleteTunnel(tunnelId);
Response
{
  "success": true
}
GET /v1/lab

List your Codeless tests

Paginated list of every Codeless test (a.k.a. Lab test) on the account. Codeless tests are recorded in TestingBot's in-browser recorder and can be scheduled on a cron, fired via API, or chained into suites.

Arguments

offset integer
Skip this many tests from the start of the result set.
count integer max=500
Number of tests to return .

Response fields

data array of lab test objects
meta meta object
GET /v1/lab
Request
$ curl "https://api.testingbot.com/v1/lab" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestCollection labTests = restApi.getLabTests();
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const codelessTests = await api.getCodelessTests();
Response
{
  "data": [
    {
      "id": 215,
      "enabled": false,
      "alerts": [],
      "url": "https://testingbot.com/",
      "name": "testingbot",
      "created_at": "2012-03-12T20:03:45Z",
      "updated_at": "2012-03-13T20:26:43Z",
      "last_run": "2012-03-13T06:50:48Z",
      "browsers": [
        { "name": "firefox", "version": 10, "os": "LINUX" }
      ]
    }
  ],
  "meta": { "offset": 0, "count": 10, "total": 25 }
}
GET /v1/lab/{id}

Get a specific Codeless test

Returns a single Codeless test's configuration: schedule, alerts, attached browsers, and timestamps. Use the steps endpoint to retrieve the actual test recording.

Arguments

id integer required
Numeric Codeless test ID.

Response fields

id integer
Unique numeric Codeless test ID.
name string
Test name.
url string
Target URL the test runs against.
enabled boolean
Whether scheduled runs are active.
cron string
Cron expression for scheduled runs; null if unscheduled.
created_at timestamp
updated_at timestamp
last_run timestamp
Most recent run timestamp.
alerts array of lab alert objects
Configured alert destinations.
browsers array of browser objects
Browsers this test is configured to run on.
GET /v1/lab/{id}
Request
$ curl "https://api.testingbot.com/v1/lab/{id}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTest labTest = restApi.getLabTest(labTestId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const codelessTest = await api.getCodelessTest(labTestId);
Response
{
  "id": 215,
  "enabled": false,
  "alerts": [],
  "url": "https://testingbot.com/",
  "name": "testingbot",
  "created_at": "2012-03-12T20:03:45Z",
  "updated_at": "2012-03-13T20:26:43Z",
  "last_run": "2012-03-13T06:50:48Z",
  "browsers": [
    { "name": "firefox", "version": 10, "os": "LINUX" }
  ]
}
POST /v1/lab

Create a Codeless test

Creates a new Codeless test. Pass test[name] and either test[url] (target URL the test visits) or file (Selenium IDE export to import). Optional test[ai_prompt] lets you describe what the AI test agent should verify in plain English.

Arguments

test[name] string
Test name.
test[url] string
Target URL to test (required if no file is uploaded).
test[cron] string
Cron expression for scheduled runs.
test[screenshot] boolean
Take screenshots at every step.
test[video] boolean
Record a video of the test.
test[idletimeout] integer
Seconds of idle time before the runner aborts the test.
test[screenresolution] string
Browser viewport (e.g. "1920x1080").
test[ai_prompt] string
Plain-English instruction for the AI test agent.
file file
Selenium IDE .side export to import as the test's steps.
POST /v1/lab
Request
$ curl -X POST "https://api.testingbot.com/v1/lab" \
-u key:secret \
-d "test[name]=test" \
-d "test[cron]=31 * * * *"
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> fields = new HashMap<>();
fields.put("name", "test");
fields.put("cron", "31 * * * *");
TestingbotLabCreateAck ack = restApi.createLabTest(fields);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const result = await api.createCodelessTest({
  name: 'My Codeless Test',
  url: 'https://example.com',
  ai_prompt: 'Test the login flow',
  cron: '0 0 * * *',
  screenshot: true,
  video: false,
  idletimeout: 60,
  screenresolution: '1920x1080'
});
Response
{
  "success": true,
  "lab_test_id": 59392
}
DELETE /v1/lab/{id}

Delete a Codeless test

Permanently deletes a Codeless test and its steps. Test runs in history remain.

Arguments

id integer required
Numeric Codeless test ID to delete.
DELETE /v1/lab/{id}
Request
$ curl "https://api.testingbot.com/v1/lab/{id}" \
-X DELETE \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteLabTest(labTestId);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const result = await api.deleteCodelessTest(testId);
Response
{
  "success": true
}
PUT /v1/lab/{id}

Update a Codeless test

Updates a Codeless test's metadata: name, target URL, cron schedule, enabled state. Accepts either a numeric Codeless test ID or a WebDriver session_id of a test run that originated from this Codeless test.

Arguments

id string required
Numeric Codeless test ID or WebDriver session_id.
test[name] string
New test name.
test[url] string
New target URL.
test[cron] string
New cron expression.
test[enabled] boolean
Enable or pause scheduled runs.
PUT /v1/lab/{id}
Request
$ curl "https://api.testingbot.com/v1/lab/{id}" \
-X PUT \
-d "test[cron]=* * * * *" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> fields = new HashMap<>();
fields.put("cron", "* * * * *");
boolean success = restApi.updateLabTest(labTestId, fields);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const result = await api.updateCodelessTest({
  test: { name: 'Updated Test Name', cron: '0 12 * * *' }
}, testId);
Response
{
  "success": true
}
POST /v1/lab/{id}/schedule

Set or update a Codeless test schedule

Schedules a Codeless test to run on a recurring interval. Choose between once / daily / weekly presets or a raw cron expression.

Arguments

id integer required
Numeric Codeless test ID.
type string
Schedule preset; use "custom" with cronFormat for fine control.
day string
Date (YYYY-MM-DD) for "once" or weekday for "weekly".
hour string
Time (HH:MM) for "once", "daily", or "weekly".
cronFormat string
Raw cron expression (5-field) used when type=custom.
POST /v1/lab/{id}/schedule
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/schedule" \
-u key:secret \
-d "type=daily" -d "hour=00:01"
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("type", "daily");
params.put("hour", "00:01");
boolean success = restApi.scheduleLabTest(labTestId, params);
Response
{
  "success": true
}
POST /v1/lab/{id}/alert

Add an alert to a Codeless test

Adds a notification channel (email, SMS, or callback URL) that fires when a scheduled run fails. Use PUT to modify an existing alert.

Arguments

id integer required
Numeric Codeless test ID.
kind string required
Alert channel.
level string required
When to send (every failure vs. daily digest).
content string required
Destination — email address, callback URL, or phone number.
POST /v1/lab/{id}/alert
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/alert" \
-u key:secret \
-d "kind=EMAIL" -d "level=IMMEDIATELY" -d "content=alerts@example.com"
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("kind", "EMAIL");
params.put("level", "IMMEDIATELY");
params.put("content", "alerts@example.com");
boolean success = restApi.addLabTestAlert(labTestId, params);
Response
{
  "success": true
}
POST /v1/lab/{id}/report

Add a daily report config to a Codeless test

Configures a recurring email report summarising pass/fail rate for this Codeless test. Use PUT to update.

Arguments

id integer required
Numeric Codeless test ID.
email string required
Email address that receives the report.
cron string
Cron expression for when to send the report (defaults to daily).
POST /v1/lab/{id}/report
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/report" \
-u key:secret \
-d "email=reports@example.com" -d "cron=0 9 * * *"
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("email", "reports@example.com");
params.put("cron", "0 9 * * *");
boolean success = restApi.createLabTestReport(labTestId, params);
Response
{
  "success": true
}
POST /v1/lab/{id}/steps

Replace the Codeless test's steps

Deletes the test's existing steps and replaces them with the provided array. Useful for programmatic editing of recorded tests.

Arguments

id integer required
Numeric Codeless test ID.
steps array required
Ordered list of steps; each is { order:, cmd:, locator:, value: }.
POST /v1/lab/{id}/steps
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/steps" \
-u key:secret \
-H 'Content-Type: application/json' \
-d '{ "steps": [{ "order": 0, "cmd": "open", "locator": "/", "value": "" }] }'
TestingbotREST restApi = new TestingbotREST(key, secret);
List<String> steps = Arrays.asList("open", "click");
boolean success = restApi.setLabTestSteps(labTestId, steps);
Response
{
  "success": true
}
GET /v1/lab/{id}/steps

List Codeless test steps

Returns the recorded Selenium-IDE steps for a Codeless test, with pagination.

Arguments

id integer required
Numeric Codeless test ID.
offset integer
Skip this many steps.
count integer
Number of steps to return.

Response fields

data array of lab test step objects
meta meta object
GET /v1/lab/{id}/steps
Request
$ curl "https://api.testingbot.com/v1/lab/{id}/steps" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestStepCollection steps = restApi.getLabTestSteps(labTestId);
Response
{
  "data": [
    { "test_order": 0, "cmd": "open",  "locator": "/",            "value": "",     "created_at": "2019-05-02T14:33:48.000Z", "updated_at": "2019-05-02T14:33:48.000Z" },
    { "test_order": 1, "cmd": "type",  "locator": "id=username",  "value": "test", "created_at": "2019-05-02T14:33:48.000Z", "updated_at": "2019-05-02T14:33:48.000Z" },
    { "test_order": 2, "cmd": "type",  "locator": "id=password",  "value": "test", "created_at": "2019-05-02T14:33:48.000Z", "updated_at": "2019-05-02T14:33:48.000Z" }
  ],
  "meta": { "offset": 0, "count": 3, "total": 3 }
}
GET /v1/lab/{id}/browsers

Get browsers for a Codeless test

Returns the list of browsers this Codeless test is configured to run on.

Arguments

id integer required
Numeric Codeless test ID.

Response fields

selenium_name string
Capability value to send as browserName in WebDriver.
name string
Human-readable browser identifier (e.g. "firefox", "iexplore").
version integer
Major version number.
long_version string
Full version string (e.g. "121.0.6167.184").
platform string
Operating system (e.g. "WINDOWS", "MAC", "LINUX").
browser_id integer
Unique TestingBot browser ID used to attach browsers to Codeless tests.
GET /v1/lab/{id}/browsers
Request
$ curl "https://api.testingbot.com/v1/lab/{id}/browsers" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotBrowser> browsers = restApi.getLabTestBrowsers(labTestId);
Response
[
  { "name": "firefox", "version": "41", "os": "VISTA" }
]
POST /v1/lab/{id}/browsers

Update browsers for a Codeless test

Replaces the entire browser set attached to this Codeless test. Pass browser_ids as a comma-separated list of IDs from /v1/browsers.

Arguments

id integer required
Numeric Codeless test ID.
browser_ids string required
Comma-separated list of browser_ids the test should run on.
POST /v1/lab/{id}/browsers
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/browsers" \
-u key:secret \
-d "browser_ids=1,5,12"
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.setLabTestBrowsers(labTestId, "1,5,12");
Response
{
  "success": true
}
POST /v1/lab/{id}/trigger

Run a specific Codeless test

Triggers an immediate run of a Codeless test on the browsers configured for it. Returns a job_id you can poll with GET /v1/jobs/:id.

Arguments

id integer required
Numeric Codeless test ID to run.
url string
Override the test's base URL for this run only.
POST /v1/lab/{id}/trigger
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/trigger" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabRunAck ack = restApi.triggerLabTest(labTestId);
Response
{
  "success": true,
  "job_id": 14
}
PUT /v1/lab/{id}/stop

Stop a running Codeless test

Force-stops an in-flight Codeless test run. Optional browser_id stops only the run on a specific browser.

Arguments

id integer required
Numeric Codeless test ID.
browser_id integer
Only stop the run on this browser_id (omit to stop all).
PUT /v1/lab/{id}/stop
Request
$ curl -X PUT "https://api.testingbot.com/v1/lab/{id}/stop" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.stopLabTest(labTestId);
Response
{
  "success": true
}
POST /v1/lab/trigger_all

Run all Codeless tests

Queues a run of every Codeless test on the account. Returns a job_id that aggregates the results — poll via GET /v1/jobs/:id. Optional url overrides each test's base URL for this run.

Arguments

url string
Override base URL for every queued test.
POST /v1/lab/trigger_all
Request
$ curl -X POST "https://api.testingbot.com/v1/lab/trigger_all" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabRunAck ack = restApi.triggerAllLabTests();
Response
{
  "success": true,
  "job_id": 14
}
GET /v1/jobs/{id}

Get a job's status

Returns the live status of an asynchronous job — typically used to poll Codeless test/suite runs started by POST /v1/lab/:id/trigger, POST /v1/lab/trigger_all, or POST /v1/labsuites/:id/trigger. Once status is FINISHED, the response includes success and per-test results.

Arguments

id integer required
Numeric job ID returned by a trigger endpoint.

Response fields

status string
Job state (QUEUED, RUNNING, FINISHED, FAILED).
created_at timestamp
updated_at timestamp
success boolean
Aggregate pass/fail across all triggered tests; null until FINISHED.
test_ids array of integer
Test IDs spawned by this job.
errors array of object
Per-test failure detail (step, browser, time).
GET /v1/jobs/{id}
Request
$ curl "https://api.testingbot.com/v1/jobs/{id}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotJob job = restApi.getJob(jobId);
Response
{
  "status": "FINISHED",
  "created_at": "2016-04-15T13:47:39.000Z",
  "updated_at": "2016-04-15T13:49:30.000Z",
  "success": false,
  "test_ids": [6620446],
  "errors": [
    {
      "msg": "Actual value 'Google' did not match 'Goooogle'",
      "step": "verifyTitle",
      "browser": { "name": "firefox", "version": "43", "os": "VISTA" },
      "time": "2016-04-15T13:48:25.839Z",
      "test": 6620446
    }
  ]
}
POST (your callback URL)

Webhook callback

If you have configured a webhook URL, we will POST the result to the callback URL you configured in the Codeless alerts section. The body below is the JSON payload we send; respond with 2xx to acknowledge.
POST (your callback URL)
Response
{
    "success": false,
    "errors": [
        {
            "msg": "word Not found",
            "step": "verifyTextPresent",
            "browser": {
                "name": "iexplore",
                "version": "8",
                "os": "WINDOWS"
            },
            "time": "2012-03-13 20:34:59 UTC",
            "test_id": "48586",
            "job_id": 17,
            "lab_id": 133
        }
    ],
    "job_id": 3,
    "test_ids": [48586]
}
GET /v1/labsuites

List your Codeless suites

Paginated list of every Codeless suite (a.k.a. Lab suite) on the account. A suite groups several Codeless tests so they can be scheduled, triggered, and reported on as a unit.

Arguments

offset integer
Skip this many suites from the start of the result set.
count integer max=500
Number of suites to return .

Response fields

data array of lab suite objects
meta meta object
GET /v1/labsuites
Request
$ curl "https://api.testingbot.com/v1/labsuites" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabSuiteCollection suites = restApi.getLabSuites();
Response
{
  "data": [
    {
      "id": 1051,
      "enabled": true,
      "name": "Example",
      "created_at": "2017-03-07T19:11:41.000Z",
      "updated_at": "2017-03-09T12:17:22.000Z",
      "last_run": "2017-03-09T12:17:22.000Z",
      "cron": null,
      "test_count": 5,
      "alerts": [
        { "type": "API", "value": "https://mysite.com/callback/", "level": "IMMEDIATELY" }
      ],
      "browsers": [
        { "name": "firefox", "version": "41", "os": "VISTA" }
      ]
    }
  ],
  "meta": { "offset": 0, "count": 10, "total": 1 }
}
GET /v1/labsuites/{id}

Get a specific Codeless suite

Returns a single Codeless suite's configuration: schedule, alerts, attached browsers, and number of tests inside.

Arguments

id integer required
Numeric suite ID.

Response fields

id integer
Unique numeric Codeless suite ID.
name string
Suite name.
enabled boolean
Whether scheduled runs are active.
cron string
Cron expression for scheduled runs.
test_count integer
Number of Codeless tests attached.
created_at timestamp
updated_at timestamp
last_run timestamp
alerts array of lab alert objects
GET /v1/labsuites/{id}
Request
$ curl "https://api.testingbot.com/v1/labsuites/{id}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabSuite suite = restApi.getLabSuite(suiteId);
Response
{
  "enabled": true,
  "name": "Example",
  "cron": null,
  "test_count": 5,
  "created_at": "2017-03-07T19:11:41.000Z",
  "updated_at": "2017-03-09T12:17:22.000Z",
  "last_run": "2017-03-09T12:17:22.000Z",
  "alerts": [
    { "type": "API", "value": "https://mysite.com/callback/", "level": "IMMEDIATELY" }
  ]
}
POST /v1/labsuites/{id}/trigger

Run a Codeless suite

Queues every test in the suite for an immediate run. Returns a job_id you can poll with GET /v1/jobs/:id.

Arguments

id integer required
Numeric suite ID to trigger.
POST /v1/labsuites/{id}/trigger
Request
$ curl -X POST "https://api.testingbot.com/v1/labsuites/{id}/trigger" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabRunAck ack = restApi.triggerLabSuite(suiteId);
Response
{
  "success": true,
  "job_id": 14
}
POST /v1/labsuites

Create a Codeless suite

Creates a new Codeless suite. Attach Codeless tests with POST /v1/labsuites/:id/tests after creation.

Arguments

suite[name] string required
Suite name.
suite[cron] string
Cron expression for scheduled suite runs.
suite[screenshot] boolean
Take screenshots at every step in every test.
suite[video] boolean
Record video for tests in this suite.
suite[idletimeout] integer
Idle timeout in seconds before tests are aborted.
suite[screenresolution] string
Browser viewport for every test in the suite.
POST /v1/labsuites
Request
$ curl -X POST "https://api.testingbot.com/v1/labsuites" \
-u key:secret \
-d "suite[name]=My Suite"
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> fields = new HashMap<>();
fields.put("name", "My Suite");
TestingbotLabSuiteCreateAck ack = restApi.createLabSuite(fields);
Response
{
  "success": true,
  "suite_id": 59391
}
DELETE /v1/labsuites/{id}

Delete a Codeless suite

Deletes the suite. The Codeless tests attached to it are not deleted — only the suite grouping.

Arguments

id integer required
Numeric suite ID to delete.
DELETE /v1/labsuites/{id}
Request
$ curl -X DELETE "https://api.testingbot.com/v1/labsuites/{id}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteLabSuite(suiteId);
Response
{
  "success": true
}
GET /v1/labsuites/{id}/browsers

Get browsers for a Codeless suite

Returns the list of browsers the suite is configured to run on.

Arguments

id integer required
Numeric suite ID.

Response fields

selenium_name string
Capability value to send as browserName in WebDriver.
name string
Human-readable browser identifier (e.g. "firefox", "iexplore").
version integer
Major version number.
long_version string
Full version string (e.g. "121.0.6167.184").
platform string
Operating system (e.g. "WINDOWS", "MAC", "LINUX").
browser_id integer
Unique TestingBot browser ID used to attach browsers to Codeless tests.
GET /v1/labsuites/{id}/browsers
Request
$ curl "https://api.testingbot.com/v1/labsuites/{id}/browsers" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotBrowser> browsers = restApi.getLabSuiteBrowsers(suiteId);
Response
[
  { "name": "firefox", "version": "41", "os": "VISTA" }
]
POST /v1/labsuites/{id}/browsers

Update browsers for a Codeless suite

Replaces the browser set attached to a suite. Every test in the suite will run on the new browser list at next trigger.

Arguments

id integer required
Numeric suite ID.
browser_ids string required
Comma-separated list of browser_ids the suite should run on.
POST /v1/labsuites/{id}/browsers
Request
$ curl -X POST "https://api.testingbot.com/v1/labsuites/{id}/browsers" \
-u key:secret \
-d "browser_ids=1,5,12"
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.setLabSuiteBrowsers(suiteId, "1,5,12");
Response
{
  "success": true
}
GET /v1/labsuites/{id}/tests

List tests in a Codeless suite

Returns the Codeless tests attached to a suite, with pagination.

Arguments

id integer required
Numeric suite ID.
offset integer
Skip this many tests.
count integer
Number of tests to return.

Response fields

data array of lab test objects
meta meta object
GET /v1/labsuites/{id}/tests
Request
$ curl "https://api.testingbot.com/v1/labsuites/{id}/tests" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestCollection tests = restApi.getLabSuiteTests(suiteId);
Response
{
  "data": [
    {
      "id": 18666,
      "enabled": true,
      "name": "MyTest",
      "url": "https://mysite.com/",
      "created_at": "2017-03-09T12:14:48.000Z",
      "updated_at": "2017-03-09T12:19:30.000Z",
      "last_run": "2017-03-09T12:19:30.000Z",
      "cron": null,
      "browsers": [
        { "name": "firefox", "version": "41", "os": "VISTA" }
      ]
    }
  ],
  "meta": { "offset": 0, "count": 1, "total": 1 }
}
POST /v1/labsuites/{id}/tests

Add tests to a Codeless suite

Attaches one or more existing Codeless tests to a suite. Pass test_ids as a comma-separated list.

Arguments

id integer required
Numeric suite ID.
test_ids string required
Comma-separated list of Codeless test IDs to attach.
POST /v1/labsuites/{id}/tests
Request
$ curl -X POST "https://api.testingbot.com/v1/labsuites/{id}/tests" \
-u key:secret \
-d "test_ids=215,228"
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.addLabSuiteTests(suiteId, "215,228");
Response
{
  "success": true
}
DELETE /v1/labsuites/{id}/tests/{testid}

Remove a test from a Codeless suite

Detaches a single Codeless test from a suite. The test itself is preserved.

Arguments

id integer required
Numeric suite ID.
testid integer required
Numeric Codeless test ID to detach.
DELETE /v1/labsuites/{id}/tests/{testid}
Request
$ curl -X DELETE "https://api.testingbot.com/v1/labsuites/{id}/tests/{testid}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.removeLabSuiteTest(suiteId, testId);
Response
{
  "success": true
}
POST /v1/storage

Upload an app to storage

Uploads an APK or IPA to TestingBot storage. Either send the binary as multipart file or pass a public url that TestingBot will fetch. The returned app_url (tb://<appkey>) can be set as the app capability on subsequent mobile sessions.

Arguments

file file
Multipart binary upload of an .apk or .ipa.
url string
Public HTTPS URL TestingBot will download the binary from.
POST /v1/storage
Request
$ curl -X POST "https://api.testingbot.com/v1/storage" \
-u key:secret \
-F "file=@/path/to/app/file/Application-debug.apk"
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.upload_local_file(local_file_path)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.storage.upload_local_file(local_file_path)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->uploadLocalFileToStorage($pathToLocalFile);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotStorageUploadResponse uploadResponse = restApi.uploadToStorage(file);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const { app_url } = await api.uploadFile(localFilePath);
Response
{
  "app_url": "tb://398eijf83i"
}
POST /v1/storage/{path}

Update an app binary by appkey

Replaces the binary stored under an existing appkey. The app_url (tb://<appkey>) stays the same so deployed CI configurations keep working without changes — useful for "always use the latest" CI flows.

Arguments

splat integer required
file file
Multipart binary replacement.
url string
Public HTTPS URL to fetch the new binary from.
POST /v1/storage/{path}
Request
$ curl -X POST "https://api.testingbot.com/v1/storage/{app_url}" \
-u key:secret \
-F "file=@/path/to/app/file/Application-debug.apk"
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const appUrl = await api.uploadFile(localFilePath);
Response
{
  "app_url": "tb://398eijf83i"
}
GET /v1/storage/{path}

Get a stored app by appkey

Returns metadata for a single uploaded app — its filename, type, version, icon, and download URL.

Arguments

splat integer required

Response fields

id integer
Unique numeric storage object ID.
app_url string
TestingBot storage URL (tb://<appkey>) — pass as a capability to reference this app in mobile tests.
url string
Signed HTTPS URL to download the binary directly.
filename string
Original uploaded filename.
type string
Detected app type (apk, ipa, zip).
version string
CFBundleShortVersionString / versionName extracted from the binary.
min_device_version string
Minimum OS version required by the app.
thumb string
App icon (signed PNG URL).
created_at timestamp
Upload timestamp.
state string
Processing state (PROCESSING, READY).
sim_only boolean
True for iOS simulator-only IPAs (no signing).
GET /v1/storage/{path}
Request
$ curl "https://api.testingbot.com/v1/storage/{app_url}" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_uploaded_file(app_url)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.storage.get_stored_file(app_url)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getStorageFile($appUrl);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingBotStorageFile storedFile = restApi.getStorageFile(appUrl);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

await api.getStorageFile(appUrl);
Response
{
  "app_url": "tb://0ec522702cd81ec1374e9b3c",
  "url": "http://...",
  "id": 261,
  "type": "ANDROID",
  "filename": "sample.apk",
  "version": "1.0.1",
  "min_device_version": "12.0",
  "thumb": "https://...image.png",
  "created_at": "2019-03-08T08:58:32.000Z"
}
GET /v1/storage

List your storage apps

Paginated list of every app you've uploaded to TestingBot storage, newest first.

Arguments

offset integer
Skip this many apps from the start of the result set.
count integer max=500
Number of apps to return .

Response fields

data array of storage file objects
Storage objects for this page.
meta meta object
GET /v1/storage
Request
$ curl "https://api.testingbot.com/v1/storage/" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_uploaded_files(0, 30)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.storage.get_stored_files(offset=0, limit=30)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getStorageFiles();
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingBotStorageFileCollection fileList = restApi.getStorageFiles(0, 30);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const files = await api.getStorageFiles(offset, count);
Response
[
  {
    "app_url": "tb://….",
    "url": "…",
    "id": 44,
    "type": "ANDROID",
    "filename": "sample.apk",
    "version": "1.0.1",
    "min_device_version": "23",
    "thumb": "https://...image.png",
    "created_at": "2019-01-08T13:42:42.000Z"
  }
]
DELETE /v1/storage/{id}

Delete a stored app

Permanently removes the binary and its metadata. Sessions referencing the app_url after deletion will fail at session-start with "app not found".

Arguments

id string required
Numeric storage ID or appkey to delete.
DELETE /v1/storage/{id}
Request
$ curl -X DELETE "https://api.testingbot.com/v1/storage/{app_url}" \
-u key:secret
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.delete_uploaded_file(file_identifier)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.storage.remove_file(app_url)
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->deleteStorageFile($appUrl);
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteStorageFile(appUrl);
const TestingBot = require('testingbot-api');

const api = new TestingBot({
  api_key: "your-tb-key",
  api_secret: "your-tb-secret"
});

const success = await api.deleteStorageFile(fileId);
Response
{
  "success": true
}
GET /v1/configuration/ip-ranges

TestingBot IP ranges for firewall whitelisting

Returns the up-to-date list of public IPv4 addresses used by TestingBot test machines. Allow these in your firewall when running tests against staging or production behind corporate VPN/network rules. The response is a flat JSON array of IPv4 strings (no CIDR ranges, no metadata) — re-fetch periodically since the pool changes as we scale capacity. Unauthenticated; no key/secret required.
GET /v1/configuration/ip-ranges
Request
$ curl "https://api.testingbot.com/v1/configuration/ip-ranges"
require 'net/http'
require 'json'

ips = JSON.parse(Net::HTTP.get(URI('https://api.testingbot.com/v1/configuration/ip-ranges')))
puts ips
import requests

ips = requests.get('https://api.testingbot.com/v1/configuration/ip-ranges').json()
print(ips)
TestingbotREST restApi = new TestingbotREST(key, secret);
JsonElement ipRanges = restApi.getIpRanges();
const res = await fetch('https://api.testingbot.com/v1/configuration/ip-ranges');
const ips = await res.json();
console.log(ips);
Response
[
  "109.68.162.161",
  "109.68.162.165",
  "78.20.187.211",
  "162.55.135.22",
  "95.217.83.184",
  "95.216.39.110",
  "95.216.229.109",
  "142.132.137.7",
  "195.201.167.43",
  "162.55.24.100",
  "185.223.133.13"
]
Was this page helpful?
Last updated