---
title: Codeless Automation & TestLab API | TestingBot API Documentation
description: Create, schedule and trigger codeless automation tests and TestLab suites,
  and read their steps, browsers and reports.
source_url:
  html: https://testingbot.com/support/api/codeless
  md: https://testingbot.com/support/api/codeless.md
---

# Codeless Automation & TestLab

Drive the codeless test builder and the TestLab suites that group those tests, end to end.

- **Endpoint:** api.testingbot.com
- **Version:** v1
- **Format:** JSON
- **Auth:** [HTTP Basic](https://testingbot.com/support/api#authentication)

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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/lab" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var tests = await client.CodelessTests.ListAsync();
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_tests(0, 10)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.get_tests(offset=0, limit=10)
```

```php
$client = new TestingBot\Client($key, $secret);
$tests = $client->lab()->listTests(0, 10);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestCollection labTests = restApi.getLabTests();
```

```javascript
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

```json
{
  "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}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/lab/{id}" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var test = await client.CodelessTests.GetAsync(testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_test(lab_test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.get_test(lab_test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$test = $client->lab()->getTest($labTestId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTest labTest = restApi.getLabTest(labTestId);
```

```javascript
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

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/lab" \
-u key:secret \
-d "test[name]=test" \
-d "test[cron]=31 * * * *"
```

```csharp
var client = new TestingBotClient(key, secret);
long testId = await client.CodelessTests.CreateAsync(new CodelessTestCreate { Name = "My test", Url = "https://example.com" });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.create_lab_test({ "test[name]" => 'test', "test[cron]" => '31 * * * *' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.create_test(name='test', cron='31 * * * *')
```

```php
$client = new TestingBot\Client($key, $secret);
$test = $client->lab()->createTest(['name' => 'smoke', 'url' => 'https://example.com']);
```

```java
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);
```

```javascript
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

```json
{
  "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}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/lab/{id}" \
-X DELETE \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.DeleteAsync(testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.delete_lab_test(lab_test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.delete_test(lab_test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->deleteTest($labTestId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteLabTest(labTestId);
```

```javascript
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

```json
{
  "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.

### Response fields

- **`success` boolean:** Whether the operation succeeded.
- **`errors` object:** Validation errors keyed by field name. Only present when `success` is false.
- **`error` string:** Single human-readable reason, used by the older endpoints in place of `errors`. Only present when `success` is false.

PUT `/v1/lab/{id}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/lab/{id}" \
-X PUT \
-d "test[cron]=* * * * *" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.UpdateAsync(testId, new CodelessTestUpdate { Name = "Renamed test" });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.update_lab_test(lab_test_id, { "test[cron]" => '* * * * *' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.update_test(lab_test_id, cron='* * * * *')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->updateTest($labTestId, ['name' => 'smoke test']);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> fields = new HashMap<>();
fields.put("cron", "* * * * *");
boolean success = restApi.updateLabTest(labTestId, fields);
```

```javascript
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

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/schedule" \
-u key:secret \
-d "type=daily" -d "hour=00:01"
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.ScheduleAsync(testId, new CodelessSchedule { Type = CodelessScheduleType.Daily, Hour = "09:00" });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.schedule_lab_test(lab_test_id, { type: 'daily', hour: '00:01' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.schedule(lab_test_id, 'daily', hour='00:01')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->schedule($labTestId, ['cron' => '0 * * * *']);
```

```java
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);
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.scheduleCodelessTest(labTestId, { type: 'daily', hour: '00:01' });
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ 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"
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.AddAlertAsync(testId, new CodelessAlertInput
{
    Kind = AlertKind.Email,
    Level = AlertLevel.Immediately,
    Content = "dev@example.com"
});
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.add_lab_test_alert(lab_test_id, { kind: 'EMAIL', level: 'IMMEDIATELY', content: 'alerts@example.com' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.add_alert(lab_test_id, 'EMAIL', 'IMMEDIATELY', 'alerts@example.com')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->addAlert($labTestId, ['content' => 'ops@example.com']);
```

```java
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);
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.createCodelessAlert(labTestId, { kind: 'EMAIL', level: 'IMMEDIATELY', content: 'alerts@example.com' });
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/report" \
-u key:secret \
-d "email=reports@example.com" -d "cron=0 9 * * *"
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.AddReportAsync(testId, new CodelessReportInput { Email = "dev@example.com" });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.create_lab_test_report(lab_test_id, { email: 'reports@example.com', cron: '0 9 * * *' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.add_report(lab_test_id, 'reports@example.com', cron='0 9 * * *')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->addReport($labTestId, ['email' => 'ops@example.com']);
```

```java
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);
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.createCodelessReport(labTestId, { email: 'reports@example.com', cron: '0 9 * * *' });
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ 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": "" }] }'
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.SetStepsAsync(testId, new[]
{
    new CodelessStepInput { Order = 1, Command = "open", Value = "/" }
});
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.set_lab_test_steps(lab_test_id, { steps: [{ order: 0, cmd: 'open', locator: '/', value: '' }] })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.set_steps(lab_test_id, [{'order': 0, 'cmd': 'open', 'locator': '/', 'value': ''}])
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->setSteps($labTestId, [
    ['order' => 0, 'cmd' => 'open', 'locator' => '/', 'value' => ''],
]);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
List<String> steps = Arrays.asList("open", "click");
boolean success = restApi.setLabTestSteps(labTestId, steps);
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.addCodelessStep(labTestId, {
  steps: [{ order: 0, cmd: 'open', locator: '/', value: '' }]
});
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/lab/{id}/steps" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var steps = await client.CodelessTests.GetStepsAsync(testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_test_steps(lab_test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.get_steps(lab_test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$steps = $client->lab()->getSteps($labTestId, 0, 10);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestStepCollection steps = restApi.getLabTestSteps(labTestId);
```

```javascript
const TestingBot = require('testingbot-api');

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

const steps = await api.getCodelessSteps(labTestId);
```

Response

```json
{
  "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

- **`name` string:** Browser identifier (e.g. "firefox", "chrome").
- **`version` string:** Browser version the test runs against.
- **`os` string:** Operating system the test runs on (e.g. "WINDOWS", "MAC", "LINUX").

GET `/v1/lab/{id}/browsers`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/lab/{id}/browsers" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var browsers = await client.CodelessTests.GetBrowsersAsync(testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_test_browsers(lab_test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.get_browsers(lab_test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$browsers = $client->lab()->getBrowsers($labTestId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotBrowser> browsers = restApi.getLabTestBrowsers(labTestId);
```

```javascript
const TestingBot = require('testingbot-api');

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

const browsers = await api.getCodelessBrowsers(labTestId);
```

Response

```json
[
  { "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/browsers" \
-u key:secret \
-d "browser_ids=1,5,12"
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.SetBrowsersAsync(testId, new[] { 1, 22 });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.set_lab_test_browsers(lab_test_id, { browser_ids: '1,5,12' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.set_browsers(lab_test_id, '1,5,12')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->setBrowsers($labTestId, [1, 2]);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.setLabTestBrowsers(labTestId, "1,5,12");
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.setCodelessBrowsers(labTestId, { browser_ids: '1,5,12' });
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/lab/{id}/trigger" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var result = await client.CodelessTests.TriggerAsync(testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.trigger_lab_test(lab_test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.trigger(lab_test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$run = $client->lab()->trigger($labTestId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabRunAck ack = restApi.triggerLabTest(labTestId);
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.triggerCodelessTest(labTestId);
```

Response

```json
{
  "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).

### Response fields

- **`success` boolean:** Whether the operation succeeded.
- **`errors` object:** Validation errors keyed by field name. Only present when `success` is false.
- **`error` string:** Single human-readable reason, used by the older endpoints in place of `errors`. Only present when `success` is false.

PUT `/v1/lab/{id}/stop`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X PUT "https://api.testingbot.com/v1/lab/{id}/stop" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.StopAsync(testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.stop_lab_test(lab_test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.stop(lab_test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->stop($labTestId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.stopLabTest(labTestId);
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.stopCodelessTest(labTestId);
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/lab/trigger_all" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var result = await client.CodelessTests.TriggerAllAsync();
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.trigger_all_lab_tests
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.lab.trigger_all()
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->triggerAll();
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabRunAck ack = restApi.triggerAllLabTests();
```

```javascript
const TestingBot = require('testingbot-api');

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

const result = await api.triggerAllCodelessTests();
```

Response

```json
{
  "success": true,
  "job_id": 14
}
```

PUT `/v1/lab/{id}/alert`

## Update an existing alert
 Replaces the alert configuration on a Codeless test. POST to /alert creates one; PUT updates it. 
### Arguments

- **`id` integer required:** Numeric Codeless test ID.
- **`kind` string:** Alert channel.
- **`level` string:** When to send.
- **`content` string:** Updated destination value.

### Response fields

- **`success` boolean:** Whether the operation succeeded.
- **`errors` object:** Validation errors keyed by field name. Only present when `success` is false.
- **`error` string:** Single human-readable reason, used by the older endpoints in place of `errors`. Only present when `success` is false.

PUT `/v1/lab/{id}/alert`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X PUT "https://api.testingbot.com/v1/lab/{id}/alert" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.UpdateAlertAsync(testId, new CodelessAlertInput { Content = "ops@example.com" });
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->updateAlert($labTestId, ['content' => 'ops@example.com']);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> alert = Map.of("content", "ops@example.com");
boolean success = restApi.updateLabTestAlert(labTestId, alert);
```

```javascript
const TestingBot = require('testingbot-api');

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

await api.updateCodelessAlert(testId, { content: 'ops@example.com' });
```

PUT `/v1/lab/{id}/report`

## Update a daily report config
 Replaces the report destination/schedule for a Codeless test. 
### Arguments

- **`id` integer required:** Numeric Codeless test ID.
- **`email` string:** Updated email address.
- **`cron` string:** Updated cron expression.

### Response fields

- **`success` boolean:** Whether the operation succeeded.
- **`errors` object:** Validation errors keyed by field name. Only present when `success` is false.
- **`error` string:** Single human-readable reason, used by the older endpoints in place of `errors`. Only present when `success` is false.

PUT `/v1/lab/{id}/report`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#) [NodeJS](https://testingbot.com#)
Request

```bash
$ curl -X PUT "https://api.testingbot.com/v1/lab/{id}/report" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessTests.UpdateReportAsync(testId, new CodelessReportInput { Email = "ops@example.com" });
```

```php
$client = new TestingBot\Client($key, $secret);
$client->lab()->updateReport($labTestId, ['email' => 'ops@example.com']);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> report = Map.of("email", "ops@example.com");
boolean success = restApi.updateLabTestReport(labTestId, report);
```

```javascript
const TestingBot = require('testingbot-api');

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

await api.updateCodelessReport(testId, { email: 'ops@example.com' });
```

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}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/jobs/{id}" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var job = await client.Jobs.GetAsync(jobId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_job(job_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.jobs.get_job(job_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$job = $client->jobs()->get($jobId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotJob job = restApi.getJob(jobId);
```

Response

```json
{
  "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

```json
{
    "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/labsuites" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var suites = await client.CodelessSuites.ListAsync();
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_suites(0, 10)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.get_suites(offset=0, limit=10)
```

```php
$client = new TestingBot\Client($key, $secret);
$suites = $client->labSuites()->list(0, 10);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabSuiteCollection suites = restApi.getLabSuites();
```

Response

```json
{
  "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:** —
- **`browsers` array of lab browser objects:** Browsers the suite runs against. Only present on GET /v1/labsuites; the single-suite endpoint omits it.

GET `/v1/labsuites/{id}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/labsuites/{id}" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var suite = await client.CodelessSuites.GetAsync(suiteId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_suite(suite_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.get_suite(suite_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$suite = $client->labSuites()->get($suiteId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabSuite suite = restApi.getLabSuite(suiteId);
```

Response

```json
{
  "id": 41,
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/labsuites/{id}/trigger" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var result = await client.CodelessSuites.TriggerAsync(suiteId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.trigger_lab_suite(suite_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.trigger(suite_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$run = $client->labSuites()->trigger($suiteId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabRunAck ack = restApi.triggerLabSuite(suiteId);
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/labsuites" \
-u key:secret \
-d "suite[name]=My Suite"
```

```csharp
var client = new TestingBotClient(key, secret);
long suiteId = await client.CodelessSuites.CreateAsync(new CodelessSuiteCreate { Name = "Regression suite" });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.create_lab_suite({ "suite[name]" => 'My Suite' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.create_suite('My Suite')
```

```php
$client = new TestingBot\Client($key, $secret);
$suite = $client->labSuites()->create(['name' => 'regression']);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> fields = new HashMap<>();
fields.put("name", "My Suite");
TestingbotLabSuiteCreateAck ack = restApi.createLabSuite(fields);
```

Response

```json
{
  "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}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl -X DELETE "https://api.testingbot.com/v1/labsuites/{id}" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessSuites.DeleteAsync(suiteId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.delete_lab_suite(suite_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.delete_suite(suite_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$client->labSuites()->delete($suiteId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.deleteLabSuite(suiteId);
```

Response

```json
{
  "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

- **`name` string:** Browser identifier (e.g. "firefox", "chrome").
- **`version` string:** Browser version the test runs against.
- **`os` string:** Operating system the test runs on (e.g. "WINDOWS", "MAC", "LINUX").

GET `/v1/labsuites/{id}/browsers`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/labsuites/{id}/browsers" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var browsers = await client.CodelessSuites.GetBrowsersAsync(suiteId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_suite_browsers(suite_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.get_browsers(suite_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$browsers = $client->labSuites()->getBrowsers($suiteId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
List<TestingbotBrowser> browsers = restApi.getLabSuiteBrowsers(suiteId);
```

Response

```json
[
  { "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/labsuites/{id}/browsers" \
-u key:secret \
-d "browser_ids=1,5,12"
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessSuites.SetBrowsersAsync(suiteId, new[] { 1, 22 });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.set_lab_suite_browsers(suite_id, { browser_ids: '1,5,12' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.set_browsers(suite_id, '1,5,12')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->labSuites()->setBrowsers($suiteId, [1, 2]);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.setLabSuiteBrowsers(suiteId, "1,5,12");
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/labsuites/{id}/tests" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
var tests = await client.CodelessSuites.GetTestsAsync(suiteId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_lab_suite_tests(suite_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.get_tests(suite_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$tests = $client->labSuites()->getTests($suiteId, 0, 10);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotLabTestCollection tests = restApi.getLabSuiteTests(suiteId);
```

Response

```json
{
  "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`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl -X POST "https://api.testingbot.com/v1/labsuites/{id}/tests" \
-u key:secret \
-d "test_ids=215,228"
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessSuites.AddTestsAsync(suiteId, new long[] { 123, 456 });
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.add_lab_suite_tests(suite_id, { test_ids: '215,228' })
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.add_tests(suite_id, '215,228')
```

```php
$client = new TestingBot\Client($key, $secret);
$client->labSuites()->addTests($suiteId, [$labTestId]);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.addLabSuiteTests(suiteId, "215,228");
```

Response

```json
{
  "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}`
[cURL](https://testingbot.com#) [.NET](https://testingbot.com#) [Ruby](https://testingbot.com#) [Python](https://testingbot.com#) [PHP](https://testingbot.com#) [Java](https://testingbot.com#)
Request

```bash
$ curl -X DELETE "https://api.testingbot.com/v1/labsuites/{id}/tests/{testid}" \
-u key:secret
```

```csharp
var client = new TestingBotClient(key, secret);
await client.CodelessSuites.RemoveTestAsync(suiteId, testId);
```

```ruby
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.remove_lab_suite_test(suite_id, test_id)
```

```python
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.labsuites.remove_test(suite_id, test_id)
```

```php
$client = new TestingBot\Client($key, $secret);
$client->labSuites()->removeTest($suiteId, $labTestId);
```

```java
TestingbotREST restApi = new TestingbotREST(key, secret);
boolean success = restApi.removeLabSuiteTest(suiteId, testId);
```

Response

```json
{
  "success": true
}
```

[Previous Tunnel](https://testingbot.com/support/api/tunnel) [Next TestingBot Storage](https://testingbot.com/support/api/storage)
