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:
-
keystring - Your public API client key. Safe to share between your CI and the TestingBot grid; not a secret on its own.
-
secretstring 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.
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).
$ 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();
/v1/browsers
List supported browsers
Returns every browser environment available on the TestingBot grid: name, version, platform, and thebrowser_id used when attaching browsers to Codeless tests. No authentication required.
Arguments
-
typestring - Filter by automation protocol: "webdriver" (default) or "rc" (legacy Selenium RC).
Response fields
-
selenium_namestring -
Capability value to send as
browserNamein WebDriver. -
namestring - Human-readable browser identifier (e.g. "firefox", "iexplore").
-
versioninteger - Major version number.
-
long_versionstring - Full version string (e.g. "121.0.6167.184").
-
platformstring - Operating system (e.g. "WINDOWS", "MAC", "LINUX").
-
browser_idinteger - Unique TestingBot browser ID used to attach browsers to Codeless tests.
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();
[
{"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}
]
/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_namestring - Given name on the account.
-
last_namestring - Family name on the account.
-
emailstring - Account email address.
-
planstring - Subscription plan identifier (e.g. "live", "automated", "automated pro").
-
max_concurrentinteger - Maximum number of parallel VM-based sessions allowed by the plan.
-
max_concurrent_mobileinteger - Maximum number of parallel physical device sessions allowed by the plan.
-
secondsinteger - Remaining test seconds (credit balance) on the account.
-
last_logintimestamp - ISO-8601 timestamp of the most recent dashboard login.
-
companystring - Optional company name for billing.
-
streetstring - Billing address line.
-
citystring - Billing city.
-
countrystring - Billing country.
-
vatstring - VAT number (EU only).
$ 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();
{
"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"
}
/v1/user
Update your user info
Updates the authenticated account. Onlyfirst_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
-
successboolean - Whether the update was applied.
-
userobject - Updated user object.
$ 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);
{
"success": true,
"user": {
"first_name": "new",
"last_name": "King",
"seconds": 17745,
"last_login": "2011-08-06T16:47:04Z"
}
}
/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
-
concurrencyobject - Allowed vs current concurrency caps for the team, split in VM and physical device sessions.
$ 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();
{
"concurrency": {
"allowed": { "vms": 10, "physical": 2 },
"current": { "vms": 4, "physical": 1 }
}
}
/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
-
offsetinteger - Skip this many users from the start of the result set.
-
countinteger - Number of users to return .
Response fields
-
dataarray of team member objects - Team member accounts.
-
metameta object - —
$ 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();
{
"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 }
}
/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
-
idinteger required - Numeric ID of the team user to fetch.
Response fields
-
idinteger - Unique numeric user ID.
-
first_namestring - Given name.
-
last_namestring - Family name.
-
emailstring - Account email.
-
creditsinteger - Remaining VM credit seconds.
-
device_creditsinteger - Remaining physical-device credit seconds.
-
isPaidboolean - Whether the account has an active paid plan.
-
verifiedboolean - Whether the account email has been verified.
-
parent_idinteger - Parent (team owner) user ID; 0 means this user is the team owner.
$ 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);
{
"id": 337,
"first_name": "test",
"last_name": "user",
"seconds": 12000,
"plan": "Free Trial",
"max_concurrent": 2,
"max_concurrent_mobile": 2
}
/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
-
emailstring required - Email address for the new account; must be unique across TestingBot.
-
passwordstring required - Initial password for the new user.
-
first_namestring - New user's given name.
-
last_namestring - New user's family name.
-
concurrencyinteger -
Max parallel VM sessions (≤ team owner's
maxParallel). -
concurrencyPhysicalinteger -
Max parallel physical-device sessions (≤ team owner's
maxParallelDevice).
$ 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);
{
"id": 337,
"first_name": "Bruno",
"last_name": "Mars",
"seconds": 12000,
"plan": "Free Trial",
"max_concurrent": 2,
"max_concurrent_mobile": 2
}
/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
-
idinteger required - Numeric ID of the team user to update.
-
first_namestring - New given name.
-
last_namestring - New family name.
-
emailstring - New email address.
-
passwordstring - New password.
-
creditsinteger - Allocated VM credit seconds (≤ team owner's remaining VM credits).
-
device_creditsinteger - Allocated physical-device credit seconds (≤ team owner's remaining device credits).
-
concurrencyinteger - Max parallel VM sessions for this user.
-
concurrencyPhysicalinteger - Max parallel physical-device sessions for this user.
Response fields
-
idinteger - Unique numeric user ID.
-
first_namestring - Given name.
-
last_namestring - Family name.
-
emailstring - Account email.
-
creditsinteger - Remaining VM credit seconds.
-
device_creditsinteger - Remaining physical-device credit seconds.
-
isPaidboolean - Whether the account has an active paid plan.
-
verifiedboolean - Whether the account email has been verified.
-
parent_idinteger - Parent (team owner) user ID; 0 means this user is the team owner.
$ 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' });
{
"id": 337,
"first_name": "Bruno",
"last_name": "Mars",
"seconds": 12000,
"plan": "Free Trial"
}
/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
-
idinteger required - Numeric ID of the team user whose credentials to rotate.
$ 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);
{
"success": true,
"client_key": "d69e0800xc32ed2f059b7a630ee255b"
}
/v1/tests
List your tests
Paginated list of every test session belonging to the authenticated account, newest first. Filter bybrowser_id, group, or build to narrow the result. Use since to fetch only tests updated after a UNIX timestamp (poll-friendly).
Arguments
-
offsetinteger - Skip this many tests from the start of the result set.
-
countinteger - Number of tests to return .
-
sinceinteger - UNIX timestamp; return only tests updated at or after this time.
-
browser_idinteger - Filter to tests that ran on this browser_id (from /v1/browsers).
-
groupstring - Filter to tests tagged with this group name.
-
buildstring -
Filter to tests in this build (matches
capabilities.build). -
skip_fieldsstring - Comma-separated fields to omit (logs, thumbs).
Response fields
-
dataarray of test case objects - Test sessions for this page.
-
metameta object - —
$ 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 });
{
"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 }
}
/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
-
idstring required - Numeric test ID or WebDriver session_id (UUID).
-
skip_fieldsstring - Comma-separated fields to omit from the response (logs, thumbs, visual_run, groups).
Response fields
-
idinteger - Unique numeric test ID.
-
session_idstring - Selenium / WebDriver session ID (UUID).
-
namestring -
Human-readable test name set via capabilities or
update_test. -
statestring - Lifecycle state (RUNNING, COMPLETE, TIMEOUT, …).
-
successboolean - Whether the test passed.
-
status_idinteger - Numeric status code (0=fail, 1=pass, 2=unknown).
-
status_messagestring -
Failure reason or arbitrary status set via
test[status_message]. -
created_attimestamp - When the test session started.
-
completed_attimestamp - When the session ended; null while running.
-
durationinteger - Total run time in seconds.
-
browserstring - Browser identifier (e.g. "iexplore", "firefox").
-
browser_versioninteger - Browser major version.
-
osstring - OS (e.g. "WINDOWS", "MAC").
-
device_namestring - Mobile device name when the session ran on a physical device; null otherwise.
-
platform_namestring - Mobile OS name; null on desktop.
-
buildstring - Build identifier (free-form string set via capabilities).
-
groupsarray of string - Tag/group names attached to the test.
-
videostring - Signed S3 URL to the recorded video, or false if video was disabled.
-
thumbsarray of string - Signed S3 URLs to screenshot thumbnails.
-
logsobject - Map of log names → signed S3 URLs (selenium, browser, …).
-
assets_availableboolean - Whether assets (video, logs, screenshots) have finished processing.
-
extrastring -
Arbitrary metadata string set via
test[extra]. -
typestring - Driver type (WEBDRIVER, APPIUM).
$ 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);
{
"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"
}
/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
-
idstring 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.
-
groupsstring - Comma-separated string or array of tag/group names to attach to the test.
-
buildstring -
Build identifier (alternative location to
test[build]).
$ 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);
{
"success": true
}
/v1/tests/:id
Delete a test
Permanently deletes a test session and every associated asset (video, logs, screenshots). This action cannot be undone.Arguments
-
idstring required - Numeric test ID or WebDriver session_id of the test to delete.
$ 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);
{
"success": true
}
/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
-
idstring required - Numeric test ID or WebDriver session_id of the test to stop.
$ 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);
{
"success": true
}
/v1/builds
List your builds
Returns a paginated list of test builds. A build is an aggregation of test cases that share the samecapabilities.build identifier, useful for grouping CI runs.
Arguments
-
offsetinteger - Skip this many builds from the start of the result set.
-
countinteger - Number of builds to return .
Response fields
-
dataarray of build objects - Builds for this page.
-
metameta object - —
$ 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);
{
"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 }
}
/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 viacapabilities.build.
Arguments
-
idstring required - Numeric build ID or string build identifier.
-
offsetinteger - Skip this many tests in the build.
-
countinteger - Number of tests to return .
-
skip_fieldsstring - Comma-separated fields to omit from each test (logs, thumbs).
Response fields
-
dataarray of test case objects - Test sessions for this page.
-
metameta object - —
$ 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);
{
"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 }
}
/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
-
idstring required - Numeric build ID or string build identifier to delete.
$ 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);
{
"success": true
}
/v1/devices
List physical mobile devices
Returns every real Android and iOS device in the TestingBot grid, with anavailable flag indicating whether it can be acquired right now. Filter by platform for a single OS family.
Arguments
-
platformstring - Filter to a single mobile OS family. Case-insensitive.
-
webboolean - Internal flag used by the dashboard — returns extra UI-only fields.
Response fields
-
idinteger - Unique numeric device ID.
-
namestring - Marketing name (e.g. "iPhone 15 Pro").
-
modelstring - Device model identifier.
-
manufacturerstring - OEM (e.g. "Apple", "Samsung").
-
platform_namestring - Mobile OS family (e.g. "iOS", "Android").
-
platform_versionstring - OS version (e.g. "17.4", "14").
-
screen_sizestring - Display size in inches (e.g. "6.1").
-
screen_resolutionstring - Display resolution (e.g. "1170x2532").
$ 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();
[
{
"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"
}
]
/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
-
idinteger - Unique numeric device ID.
-
namestring - Marketing name (e.g. "iPhone 15 Pro").
-
modelstring - Device model identifier.
-
manufacturerstring - OEM (e.g. "Apple", "Samsung").
-
platform_namestring - Mobile OS family (e.g. "iOS", "Android").
-
platform_versionstring - OS version (e.g. "17.4", "14").
-
screen_sizestring - Display size in inches (e.g. "6.1").
-
screen_resolutionstring - Display resolution (e.g. "1170x2532").
$ 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();
[
{
"id": 1,
"available": true,
"name": "Galaxy S8",
"platform_name": "Android",
"version": "9.0",
"resolution": "1080x2220"
}
]
/v1/devices/:id
Get a specific device
Returns the spec and current availability for a single device by numeric ID.Arguments
-
idinteger required - Numeric device ID.
Response fields
-
idinteger - Unique numeric device ID.
-
namestring - Marketing name (e.g. "iPhone 15 Pro").
-
modelstring - Device model identifier.
-
manufacturerstring - OEM (e.g. "Apple", "Samsung").
-
platform_namestring - Mobile OS family (e.g. "iOS", "Android").
-
platform_versionstring - OS version (e.g. "17.4", "14").
-
screen_sizestring - Display size in inches (e.g. "6.1").
-
screen_resolutionstring - Display resolution (e.g. "1170x2532").
$ 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);
{
"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" }
]
}
/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
-
urlstring required - Page URL to screenshot.
-
resolutionstring required - Browser viewport (e.g. "1920x1080").
-
browsersarray required -
Array of
{ browser, version, os }triples (orbrowser_ids) to render with. -
wait_timeinteger - Seconds to wait after page load before snapping.
-
fullpageboolean - Capture the entire scrollable page instead of just the viewport.
-
callback_urlstring - POST callback URL invoked when the batch finishes processing.
$ 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'
);
{
"id": 3454,
"wait_time": 0,
"resolution": "1280x1024",
"url": "https://www.google.com"
}
/v1/screenshots/{id}
Get screenshot batch detail
Returns per-browser screenshot results for a single batch, including thumbnail/image URLs and processing state.Arguments
-
idinteger required - Numeric screenshot batch ID.
-
excludeIdsstring - Comma-separated screenshot IDs to exclude (useful for delta-fetch).
Response fields
-
idinteger - Unique screenshot job ID.
-
urlstring - URL the screenshot was taken from.
-
statestring - Processing state.
-
wait_timeinteger - Seconds the browser waited before snapping.
-
resolutionstring - Browser viewport resolution.
-
screenshotsarray of object - Per-browser screenshot results with download URLs.
-
created_attimestamp - —
$ 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);
{
"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
}
]
}
/v1/screenshots
List screenshot batches
Returns batches of cross-browser screenshots the account has queued historically.Arguments
-
offsetinteger - Skip this many batches.
-
countinteger - Number of batches to return.
Response fields
-
dataarray of screenshot objects - —
-
metameta object - —
$ 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();
{
"data": [
{ "id": 3454, "url": "https://google.com", "resolution": "1280x1024" },
{ "id": 3452, "url": "https://testingbot.com", "resolution": "1280x1024" }
],
"meta": { "offset": 0, "count": 3, "total": 3 }
}
/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
-
idinteger - Unique numeric tunnel ID.
-
statestring - Tunnel lifecycle state (READY, STOPPED, …).
-
launchedtimestamp - When the tunnel was launched.
-
tunnel_idstring - Public tunnel identifier surfaced in the dashboard.
-
identifierstring - Custom name passed via --tunnel-identifier on the client.
-
metadataobject - Free-form metadata (client version, OS, region) reported by the tunnel binary.
$ 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();
[
{
"id": 1,
"state": "READY",
"ip": "xx",
"private_ip": "xx",
"requested_at": "2026-05-13 01:34:23"
}
]
/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
-
idinteger required - Numeric tunnel ID to stop.
$ 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);
{
"success": true
}
/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
-
offsetinteger - Skip this many tests from the start of the result set.
-
countinteger - Number of tests to return .
Response fields
-
dataarray of lab test objects - —
-
metameta object - —
$ 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();
{
"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 }
}
/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
-
idinteger required - Numeric Codeless test ID.
Response fields
-
idinteger - Unique numeric Codeless test ID.
-
namestring - Test name.
-
urlstring - Target URL the test runs against.
-
enabledboolean - Whether scheduled runs are active.
-
cronstring - Cron expression for scheduled runs; null if unscheduled.
-
created_attimestamp - —
-
updated_attimestamp - —
-
last_runtimestamp - Most recent run timestamp.
-
alertsarray of lab alert objects - Configured alert destinations.
-
browsersarray of browser objects - Browsers this test is configured to run on.
$ 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);
{
"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" }
]
}
/v1/lab
Create a Codeless test
Creates a new Codeless test. Passtest[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
fileis 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.
-
filefile -
Selenium IDE
.sideexport to import as the test's steps.
$ 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'
});
{
"success": true,
"lab_test_id": 59392
}
/v1/lab/{id}
Delete a Codeless test
Permanently deletes a Codeless test and its steps. Test runs in history remain.Arguments
-
idinteger required - Numeric Codeless test ID to delete.
$ 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);
{
"success": true
}
/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
-
idstring 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.
$ 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);
{
"success": true
}
/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
-
idinteger required - Numeric Codeless test ID.
-
typestring -
Schedule preset; use "custom" with
cronFormatfor fine control. -
daystring - Date (YYYY-MM-DD) for "once" or weekday for "weekly".
-
hourstring - Time (HH:MM) for "once", "daily", or "weekly".
-
cronFormatstring -
Raw cron expression (5-field) used when
type=custom.
$ 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);
{
"success": true
}
/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
-
idinteger required - Numeric Codeless test ID.
-
kindstring required - Alert channel.
-
levelstring required - When to send (every failure vs. daily digest).
-
contentstring required - Destination — email address, callback URL, or phone number.
$ 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);
{
"success": true
}
/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
-
idinteger required - Numeric Codeless test ID.
-
emailstring required - Email address that receives the report.
-
cronstring - Cron expression for when to send the report (defaults to daily).
$ 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);
{
"success": true
}
/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
-
idinteger required - Numeric Codeless test ID.
-
stepsarray required -
Ordered list of steps; each is
{ order:, cmd:, locator:, value: }.
$ 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);
{
"success": true
}
/v1/lab/{id}/steps
List Codeless test steps
Returns the recorded Selenium-IDE steps for a Codeless test, with pagination.Arguments
-
idinteger required - Numeric Codeless test ID.
-
offsetinteger - Skip this many steps.
-
countinteger - Number of steps to return.
Response fields
-
dataarray of lab test step objects - —
-
metameta object - —
$ curl "https://api.testingbot.com/v1/lab/{id}/steps" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestStepCollection steps = restApi.getLabTestSteps(labTestId);
{
"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 }
}
/v1/lab/{id}/browsers
Get browsers for a Codeless test
Returns the list of browsers this Codeless test is configured to run on.Arguments
-
idinteger required - Numeric Codeless test ID.
Response fields
-
selenium_namestring -
Capability value to send as
browserNamein WebDriver. -
namestring - Human-readable browser identifier (e.g. "firefox", "iexplore").
-
versioninteger - Major version number.
-
long_versionstring - Full version string (e.g. "121.0.6167.184").
-
platformstring - Operating system (e.g. "WINDOWS", "MAC", "LINUX").
-
browser_idinteger - Unique TestingBot browser ID used to attach browsers to Codeless tests.
$ curl "https://api.testingbot.com/v1/lab/{id}/browsers" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotBrowser> browsers = restApi.getLabTestBrowsers(labTestId);
[
{ "name": "firefox", "version": "41", "os": "VISTA" }
]
/v1/lab/{id}/browsers
Update browsers for a Codeless test
Replaces the entire browser set attached to this Codeless test. Passbrowser_ids as a comma-separated list of IDs from /v1/browsers.
Arguments
-
idinteger required - Numeric Codeless test ID.
-
browser_idsstring required - Comma-separated list of browser_ids the test should run on.
/v1/lab/{id}/trigger
Run a specific Codeless test
Triggers an immediate run of a Codeless test on the browsers configured for it. Returns ajob_id you can poll with GET /v1/jobs/:id.
Arguments
-
idinteger required - Numeric Codeless test ID to run.
-
urlstring - Override the test's base URL for this run only.
/v1/lab/{id}/stop
Stop a running Codeless test
Force-stops an in-flight Codeless test run. Optionalbrowser_id stops only the run on a specific browser.
Arguments
-
idinteger required - Numeric Codeless test ID.
-
browser_idinteger - Only stop the run on this browser_id (omit to stop all).
/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 viaGET /v1/jobs/:id. Optional url overrides each test's base URL for this run.
Arguments
-
urlstring - Override base URL for every queued test.
/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 byPOST /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
-
idinteger required - Numeric job ID returned by a trigger endpoint.
Response fields
-
statusstring - Job state (QUEUED, RUNNING, FINISHED, FAILED).
-
created_attimestamp - —
-
updated_attimestamp - —
-
successboolean - Aggregate pass/fail across all triggered tests; null until FINISHED.
-
test_idsarray of integer - Test IDs spawned by this job.
-
errorsarray of object - Per-test failure detail (step, browser, time).
$ curl "https://api.testingbot.com/v1/jobs/{id}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotJob job = restApi.getJob(jobId);
{
"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
}
]
}
(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.{
"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]
}
/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
-
offsetinteger - Skip this many suites from the start of the result set.
-
countinteger - Number of suites to return .
Response fields
-
dataarray of lab suite objects - —
-
metameta object - —
$ curl "https://api.testingbot.com/v1/labsuites" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabSuiteCollection suites = restApi.getLabSuites();
{
"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 }
}
/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
-
idinteger required - Numeric suite ID.
Response fields
-
idinteger - Unique numeric Codeless suite ID.
-
namestring - Suite name.
-
enabledboolean - Whether scheduled runs are active.
-
cronstring - Cron expression for scheduled runs.
-
test_countinteger - Number of Codeless tests attached.
-
created_attimestamp - —
-
updated_attimestamp - —
-
last_runtimestamp - —
-
alertsarray of lab alert objects - —
$ curl "https://api.testingbot.com/v1/labsuites/{id}" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabSuite suite = restApi.getLabSuite(suiteId);
{
"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" }
]
}
/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 withGET /v1/jobs/:id.
Arguments
-
idinteger required - Numeric suite ID to trigger.
/v1/labsuites
Create a Codeless suite
Creates a new Codeless suite. Attach Codeless tests withPOST /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.
$ 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);
{
"success": true,
"suite_id": 59391
}
/v1/labsuites/{id}
Delete a Codeless suite
Deletes the suite. The Codeless tests attached to it are not deleted — only the suite grouping.Arguments
-
idinteger required - Numeric suite ID to delete.
/v1/labsuites/{id}/browsers
Get browsers for a Codeless suite
Returns the list of browsers the suite is configured to run on.Arguments
-
idinteger required - Numeric suite ID.
Response fields
-
selenium_namestring -
Capability value to send as
browserNamein WebDriver. -
namestring - Human-readable browser identifier (e.g. "firefox", "iexplore").
-
versioninteger - Major version number.
-
long_versionstring - Full version string (e.g. "121.0.6167.184").
-
platformstring - Operating system (e.g. "WINDOWS", "MAC", "LINUX").
-
browser_idinteger - Unique TestingBot browser ID used to attach browsers to Codeless tests.
$ curl "https://api.testingbot.com/v1/labsuites/{id}/browsers" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotBrowser> browsers = restApi.getLabSuiteBrowsers(suiteId);
[
{ "name": "firefox", "version": "41", "os": "VISTA" }
]
/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
-
idinteger required - Numeric suite ID.
-
browser_idsstring required - Comma-separated list of browser_ids the suite should run on.
/v1/labsuites/{id}/tests
List tests in a Codeless suite
Returns the Codeless tests attached to a suite, with pagination.Arguments
-
idinteger required - Numeric suite ID.
-
offsetinteger - Skip this many tests.
-
countinteger - Number of tests to return.
Response fields
-
dataarray of lab test objects - —
-
metameta object - —
$ curl "https://api.testingbot.com/v1/labsuites/{id}/tests" \
-u key:secret
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestCollection tests = restApi.getLabSuiteTests(suiteId);
{
"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 }
}
/v1/labsuites/{id}/tests
Add tests to a Codeless suite
Attaches one or more existing Codeless tests to a suite. Passtest_ids as a comma-separated list.
Arguments
-
idinteger required - Numeric suite ID.
-
test_idsstring required - Comma-separated list of Codeless test IDs to attach.
/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
-
idinteger required - Numeric suite ID.
-
testidinteger required - Numeric Codeless test ID to detach.
/v1/storage
Upload an app to storage
Uploads an APK or IPA to TestingBot storage. Either send the binary as multipartfile 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
-
filefile - Multipart binary upload of an .apk or .ipa.
-
urlstring - Public HTTPS URL TestingBot will download the binary from.
$ 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);
{
"app_url": "tb://398eijf83i"
}
/v1/storage/{path}
Update an app binary by appkey
Replaces the binary stored under an existingappkey. 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
-
splatinteger required - —
-
filefile - Multipart binary replacement.
-
urlstring - Public HTTPS URL to fetch the new binary from.
$ 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);
{
"app_url": "tb://398eijf83i"
}
/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
-
splatinteger required - —
Response fields
-
idinteger - Unique numeric storage object ID.
-
app_urlstring -
TestingBot storage URL (
tb://<appkey>) — pass as a capability to reference this app in mobile tests. -
urlstring - Signed HTTPS URL to download the binary directly.
-
filenamestring - Original uploaded filename.
-
typestring - Detected app type (apk, ipa, zip).
-
versionstring - CFBundleShortVersionString / versionName extracted from the binary.
-
min_device_versionstring - Minimum OS version required by the app.
-
thumbstring - App icon (signed PNG URL).
-
created_attimestamp - Upload timestamp.
-
statestring - Processing state (PROCESSING, READY).
-
sim_onlyboolean - True for iOS simulator-only IPAs (no signing).
$ 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);
{
"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"
}
/v1/storage
List your storage apps
Paginated list of every app you've uploaded to TestingBot storage, newest first.Arguments
-
offsetinteger - Skip this many apps from the start of the result set.
-
countinteger - Number of apps to return .
Response fields
-
dataarray of storage file objects - Storage objects for this page.
-
metameta object - —
$ 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);
[
{
"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"
}
]
/v1/storage/{id}
Delete a stored app
Permanently removes the binary and its metadata. Sessions referencing theapp_url after deletion will fail at session-start with "app not found".
Arguments
-
idstring required - Numeric storage ID or appkey to delete.
$ 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);
{
"success": true
}
/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; nokey/secret required.
$ 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);
[
"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"
]