User & Team Management
Your own account and credentials, plus everything needed to provision team members and service accounts from a script.
- Endpoint
- api.testingbot.com
- Version
- v1
- Format
- JSON
- Auth
- HTTP Basic
GET
/v1/user
Get your user info
Returns the data associated with the authenticated account: name, plan, billing details, remaining credits, and concurrency caps.Response fields
-
idinteger - Unique numeric user ID. Also the path param for team endpoints (e.g. /users/:id) and the parent_id reference on team members.
-
first_namestring - Given name on the account.
-
last_namestring - Family name on the account.
-
secondsinteger - Remaining test seconds (credit balance) on the account; -1 means unlimited (e.g. Live plans).
-
last_logintimestamp - ISO-8601 timestamp of the most recent dashboard login.
-
planstring - Subscription plan name (e.g. "Free Trial", "Live - 5 Sessions - Unlimited", "Automated Pro ..."). For a sub-account this is the team owner's plan.
-
max_concurrentinteger - Maximum number of parallel VM-based sessions allowed by the plan. For a sub-account this is the team owner's cap.
-
max_concurrent_mobileinteger - Maximum number of parallel physical device sessions allowed by the plan. For a sub-account this is the team owner's cap.
-
companystring - Optional company name for billing.
-
streetstring - Billing address line.
-
citystring - Billing city.
-
countrystring - Billing country.
-
vatstring - VAT number (EU only).
-
read_onlyboolean - Whether this account has read-only access within the team.
-
rolesarray of string - Roles held by the account: "admin" and/or "owner".
-
current_vm_concurrencyinteger - VM-based sessions this account is running right now.
-
current_physical_concurrencyinteger - Physical-device sessions this account is running right now.
Request
$ curl "https://api.testingbot.com/v1/user" \
-u key:secret
var client = new TestingBotClient(key, secret);
var user = await client.User.GetAsync();
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_user_info
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.user.get_user_information()
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getUserInfo();
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotUser user = restApi.getUserInfo();
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const userInfo = await api.getUserInfo();
Response
{
"first_name": "Steven",
"last_name": "King",
"seconds": 17745,
"plan": "small",
"max_concurrent": 10,
"max_concurrent_mobile": 2,
"company": "companyName",
"street": "companyStreet",
"city": "companyCity",
"country": "companyCountry",
"vat": "ifInEurope"
}
PUT
/v1/user
Update your user info
Updates the authenticated account. 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. Only present when
successis true. -
errorsobject -
Validation errors keyed by field name. Only present when
successis false.
Request
$ curl "https://api.testingbot.com/v1/user" \
-X PUT \
-d "user[first_name]=new" \
-u key:secret
var client = new TestingBotClient(key, secret);
await client.User.UpdateAsync(new UserUpdate { FirstName = "Bruno", LastName = "Mars" });
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({'user[first_name]': 'new'})
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->updateUserInfo(array('first_name' => 'new'));
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotUser user = restApi.updateUserInfo(TestingBotUser);
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const newUserData = { first_name: 'new' };
await api.updateUserInfo(newUserData);
Response
{
"success": true,
"user": {
"first_name": "new",
"last_name": "King",
"seconds": 17745,
"last_login": "2011-08-06T16:47:04Z"
}
}
GET
/v1/user/keys
Get your API key and secret
Returns the API client key and secret for the authenticated account. Useful for confirming the credentials currently in use, but never embed this response in client-side code.Response fields
-
keystring - API client key.
-
secretstring - API client secret. Treat as a password: never embed it in client-side code.
Request
$ curl "https://api.testingbot.com/v1/user/keys" \
-u key:secret
var client = new TestingBotClient(key, secret);
var keys = await client.User.GetKeysAsync();
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_user_keys
$client = new TestingBot\Client($key, $secret);
$keys = $client->user()->keys();
TestingbotREST restApi = new TestingbotREST(key, secret);
JsonElement keys = restApi.getUserKeys();
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const { key, secret } = await api.getUserKeys();
GET
/v1/team-management
Get team concurrency info
Returns allowed vs current concurrent session counts for the team across both VMs and physical mobile devices, plus how many sessions are waiting for a free slot. Poll this before fanning out a parallel build. Counts are team-wide and come from the Hub, so they match what the dashboard shows.Response fields
-
concurrencyobject - Allowed vs current concurrency caps for the team, split in VM and physical device sessions.
Request
$ curl "https://api.testingbot.com/v1/team-management" \
-u key:secret
var client = new TestingBotClient(key, secret);
var concurrency = await client.Team.GetConcurrencyAsync();
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_team
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.team.get_concurrency()
$client = new TestingBot\Client($key, $secret);
$team = $client->teamManagement()->get();
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeam team = restApi.getTeam();
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const teamInfo = await api.getTeam();
Response
{
"concurrency": {
"allowed": { "vms": 10, "physical": 2 },
"current": { "vms": 10, "physical": 1 },
"queued": { "vms": 3, "physical": 0 }
}
}
GET
/v1/team-management/users
List users in your team
Paginated list of all sub-accounts in the team. Requires admin role on the calling account.Arguments
-
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 - —
Request
$ curl "https://api.testingbot.com/v1/team-management/users" \
-u key:secret
var client = new TestingBotClient(key, secret);
var members = await client.Team.ListUsersAsync();
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_users_in_team(0, 10)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.team.get_users(offset=0, limit=10)
$client = new TestingBot\Client($key, $secret);
$members = $client->teamManagement()->listUsers(0, 10);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeamMemberCollection members = restApi.getTeamMembers();
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const users = await api.getUsersInTeam();
Response
{
"data": [
{
"id": 337,
"first_name": "test",
"last_name": "user",
"seconds": 12000,
"plan": "Free Trial",
"max_concurrent": 2,
"max_concurrent_mobile": 2
}
],
"meta": { "offset": 0, "count": 1, "total": 1 }
}
GET
/v1/team-management/users/:id
Get a specific team user
Returns the user record for a specific team member. Admins can fetch any team member; non-admins can only fetch themselves.Arguments
-
idinteger required - Numeric ID of the team user to fetch.
Response fields
-
idinteger - Unique numeric user ID. Also the path param for team endpoints (e.g. /users/:id) and the parent_id reference on team members.
-
first_namestring - Given name on the account.
-
last_namestring - Family name on the account.
-
secondsinteger - Remaining test seconds (credit balance) on the account; -1 means unlimited (e.g. Live plans).
-
last_logintimestamp - ISO-8601 timestamp of the most recent dashboard login.
-
planstring - Subscription plan name (e.g. "Free Trial", "Live - 5 Sessions - Unlimited", "Automated Pro ..."). For a sub-account this is the team owner's plan.
-
max_concurrentinteger - Maximum number of parallel VM-based sessions allowed by the plan. For a sub-account this is the team owner's cap.
-
max_concurrent_mobileinteger - Maximum number of parallel physical device sessions allowed by the plan. For a sub-account this is the team owner's cap.
-
companystring - Optional company name for billing.
-
streetstring - Billing address line.
-
citystring - Billing city.
-
countrystring - Billing country.
-
vatstring - VAT number (EU only).
-
read_onlyboolean - Whether this account has read-only access within the team.
-
rolesarray of string - Roles held by the account: "admin" and/or "owner".
-
current_vm_concurrencyinteger - VM-based sessions this account is running right now.
-
current_physical_concurrencyinteger - Physical-device sessions this account is running right now.
Request
$ curl "https://api.testingbot.com/v1/team-management/users/:id" \
-u key:secret
var client = new TestingBotClient(key, secret);
var member = await client.Team.GetUserAsync(userId);
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.get_user_in_team(user_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.team.get_user(user_id)
$client = new TestingBot\Client($key, $secret);
$member = $client->teamManagement()->getUser($userId);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeamMember member = restApi.getTeamMember(userId);
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const user = await api.getUserFromTeam(userId);
Response
{
"id": 337,
"first_name": "test",
"last_name": "user",
"seconds": 12000,
"plan": "Free Trial",
"max_concurrent": 2,
"max_concurrent_mobile": 2
}
POST
/v1/team-management/users
Create a user in your team
Provisions a new sub-account inside the team, copying the caller's subscription level and assigning a slice of the credit pool. Requires an upgraded plan and admin role.Arguments
-
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).
Request
$ curl -X POST -u key:secret \
https://api.testingbot.com/v1/team-management/users \
--header 'Content-Type: application/json' \
--data-raw '{
"first_name": "Bruno",
"last_name": "Mars",
"email": "bmars@example.com",
"password": "$bmaRs*RULES"
}'
var client = new TestingBotClient(key, secret);
var member = await client.Team.CreateUserAsync(new TeamMemberCreate
{
Email = "bmars@example.com",
Password = "$bmaRs*RULES",
FirstName = "Bruno",
LastName = "Mars"
});
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.create_user_in_team({ first_name: 'Bruno', last_name: 'Mars', email: 'bmars@example.com', password: '$bmaRs*RULES' })
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.team.create_user(email='bmars@example.com', password='$bmaRs*RULES', first_name='Bruno', last_name='Mars')
$client = new TestingBot\Client($key, $secret);
$member = $client->teamManagement()->createUser([
'email' => 'bmars@example.com',
'password' => '$bmaRs*RULES',
'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");
params.put("email", "bmars@example.com");
params.put("password", "$bmaRs*RULES");
TestingbotTeamMember member = restApi.createTeamMember(params);
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const userData = {
first_name: 'John',
last_name: 'Doe',
email: 'john@example.com',
password: 'StrongPassword!'
};
const result = await api.createUserInTeam(userData);
Response
{
"id": 337,
"first_name": "Bruno",
"last_name": "Mars",
"seconds": 12000,
"plan": "Free Trial",
"max_concurrent": 2,
"max_concurrent_mobile": 2
}
PUT
/v1/team-management/users/:id
Update a user in your team
Updates a team user's profile and credit allocation. Credit fields cannot exceed the team owner's remaining balance.Arguments
-
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. Also the path param for team endpoints (e.g. /users/:id) and the parent_id reference on team members.
-
first_namestring - Given name on the account.
-
last_namestring - Family name on the account.
-
secondsinteger - Remaining test seconds (credit balance) on the account; -1 means unlimited (e.g. Live plans).
-
last_logintimestamp - ISO-8601 timestamp of the most recent dashboard login.
-
planstring - Subscription plan name (e.g. "Free Trial", "Live - 5 Sessions - Unlimited", "Automated Pro ..."). For a sub-account this is the team owner's plan.
-
max_concurrentinteger - Maximum number of parallel VM-based sessions allowed by the plan. For a sub-account this is the team owner's cap.
-
max_concurrent_mobileinteger - Maximum number of parallel physical device sessions allowed by the plan. For a sub-account this is the team owner's cap.
-
companystring - Optional company name for billing.
-
streetstring - Billing address line.
-
citystring - Billing city.
-
countrystring - Billing country.
-
vatstring - VAT number (EU only).
-
read_onlyboolean - Whether this account has read-only access within the team.
-
rolesarray of string - Roles held by the account: "admin" and/or "owner".
-
current_vm_concurrencyinteger - VM-based sessions this account is running right now.
-
current_physical_concurrencyinteger - Physical-device sessions this account is running right now.
Request
$ curl -X PUT -u key:secret \
https://api.testingbot.com/v1/team-management/users/:id \
--header 'Content-Type: application/json' \
--data-raw '{
"first_name": "Bruno",
"last_name": "Mars"
}'
var client = new TestingBotClient(key, secret);
var member = await client.Team.UpdateUserAsync(userId, new TeamMemberUpdate { FirstName = "Bruno", LastName = "Mars" });
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.update_user_in_team(user_id, { first_name: 'Bruno', last_name: 'Mars' })
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.team.update_user(user_id, first_name='Bruno', last_name='Mars')
$client = new TestingBot\Client($key, $secret);
$client->teamManagement()->updateUser($userId, ['first_name' => 'Bruno']);
TestingbotREST restApi = new TestingbotREST(key, secret);
Map<String, Object> params = new HashMap<>();
params.put("first_name", "Bruno");
params.put("last_name", "Mars");
TestingbotTeamMember member = restApi.updateTeamMember(userId, params);
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const result = await api.updateUserInTeam(userId, { first_name: 'Jane', last_name: 'Smith' });
Response
{
"id": 337,
"first_name": "Bruno",
"last_name": "Mars",
"seconds": 12000,
"plan": "Free Trial"
}
POST
/v1/team-management/users/:id/reset-keys
Reset credentials for a team user
Rotates both the API key and secret for a team user. The old credentials stop working immediately, so any deployed automation using them must be updated.Arguments
-
idinteger required - Numeric ID of the team user whose credentials to rotate.
Request
$ curl -X POST -u key:secret \
https://api.testingbot.com/v1/team-management/users/:id/reset-keys
var client = new TestingBotClient(key, secret);
var reset = await client.Team.ResetUserKeysAsync(userId);
require 'testingbot'
api = TestingBot::Api.new(key, secret)
api.reset_credentials(user_id)
import testingbotclient
tb = testingbotclient.TestingBotClient(key, secret)
tb.team.reset_keys(user_id)
$client = new TestingBot\Client($key, $secret);
$credentials = $client->teamManagement()->resetUserKeys($userId);
TestingbotREST restApi = new TestingbotREST(key, secret);
TestingbotTeamCredentialReset reset = restApi.resetTeamMemberKeys(userId);
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const result = await api.resetCredentials(userId);
Response
{
"success": true,
"client_key": "d69e0800xc32ed2f059b7a630ee255b"
}
GET
/v1/team-management/service-accounts
List service accounts
Returns the team's API-only service accounts, each with its own key and secret. Service accounts run tests on the grid and REST API but cannot sign in to the dashboard. Admin only.Arguments
-
offsetinteger - Skip this many service accounts from the start of the result set.
-
countinteger - Number of service accounts to return.
Response fields
-
dataarray of service account objects - Service accounts for this team.
-
metameta object - —
Request
$ curl "https://api.testingbot.com/v1/team-management/service-accounts" \
-u key:secret
Response
{
"data": [
{
"id": 412,
"identifier": "ci-runner",
"key": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"secret": "f0e9d8c7b6a5948372615f4e3d2c1b0a",
"created_at": "2026-06-05T10:08:35Z"
}
],
"meta": { "offset": 0, "count": 10, "total": 1 }
}
GET
/v1/team-management/service-accounts/:id
Get a service account
Returns a single service account, including its key and secret. Admin only.Arguments
-
idinteger required - Numeric ID of the service account.
Response fields
-
idinteger - Unique numeric service-account ID.
-
identifierstring - Human-friendly label shown on the dashboard and test detail pages.
-
keystring - TestingBot API key (username) for this service account.
-
secretstring - TestingBot API secret for this service account. Store it as a CI secret.
-
created_attimestamp - When the service account was created.
Request
$ curl "https://api.testingbot.com/v1/team-management/service-accounts/:id" \
-u key:secret
Response
{
"id": 412,
"identifier": "ci-runner",
"key": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"secret": "f0e9d8c7b6a5948372615f4e3d2c1b0a",
"created_at": "2026-06-05T10:08:35Z"
}
POST
/v1/team-management/service-accounts
Create a service account
Creates a new API-only service account with its own generated key and secret. The identifier is a label (min 3 characters, unique within the team) shown next to the account's tests on the dashboard. Admin only.Arguments
-
identifierstring required - Human-friendly label for the service account (min 3 characters, unique within the team).
Request
$ curl -X POST -u key:secret \
https://api.testingbot.com/v1/team-management/service-accounts \
--header 'Content-Type: application/json' \
--data-raw '{
"identifier": "ci-runner"
}'
Response
{
"id": 412,
"identifier": "ci-runner",
"key": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"secret": "f0e9d8c7b6a5948372615f4e3d2c1b0a",
"created_at": "2026-06-05T10:08:35Z"
}
PUT
/v1/team-management/service-accounts/:id
Update a service account
Renames a service account by changing its identifier. The key and secret are unchanged. Admin only.Arguments
-
idinteger required - Numeric ID of the service account to update.
-
identifierstring required - New identifier (min 3 characters, unique within the team).
Response fields
-
idinteger - Unique numeric service-account ID.
-
identifierstring - Human-friendly label shown on the dashboard and test detail pages.
-
keystring - TestingBot API key (username) for this service account.
-
secretstring - TestingBot API secret for this service account. Store it as a CI secret.
-
created_attimestamp - When the service account was created.
Request
$ curl -X PUT -u key:secret \
https://api.testingbot.com/v1/team-management/service-accounts/:id \
--header 'Content-Type: application/json' \
--data-raw '{
"identifier": "nightly-regression"
}'
Response
{
"id": 412,
"identifier": "nightly-regression",
"key": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"secret": "f0e9d8c7b6a5948372615f4e3d2c1b0a",
"created_at": "2026-06-05T10:08:35Z"
}
POST
/v1/team-management/service-accounts/:id/rotate
Rotate a service account access key
Generates a fresh key and secret for the service account. The previous key and secret stop working immediately, so update any automation using them. Admin only.Arguments
-
idinteger required - Numeric ID of the service account whose key and secret to rotate.
Request
$ curl -X POST -u key:secret \
https://api.testingbot.com/v1/team-management/service-accounts/:id/rotate
Response
{
"id": 412,
"identifier": "ci-runner",
"key": "9f8e7d6c5b4a3i2h1g0f9e8d7c6b5a40",
"secret": "40a5b6c7d8e9f0g1h2i3a4b5c6d7e8f9",
"created_at": "2026-06-05T10:08:35Z"
}
DELETE
/v1/team-management/service-accounts/:id
Delete a service account
Permanently deletes the service account. Its key and secret stop working immediately. Tests it already ran stay in your history, still labelled with its identifier. Admin only.Arguments
-
idinteger required - Numeric ID of the service account to delete.
Request
$ curl -X DELETE -u key:secret \
https://api.testingbot.com/v1/team-management/service-accounts/:id
Response
{
"success": true,
"message": "Service account \"ci-runner\" deleted."
}
GET
/v1/team-management/users/{id}/client-key
Get a team user's client key
Admin-only endpoint that returns the API client key for a specific team user. Used by tooling that impersonates team members in CI; the secret is not exposed here — use reset-keys to rotate.Arguments
-
idinteger required - Numeric ID of the team user whose key to fetch.
Response fields
-
client_keystring - The API client key. The matching secret is never returned here; rotate both with reset-keys.
Request
$ curl "https://api.testingbot.com/v1/team-management/users/{id}/client-key" \
-u key:secret
var client = new TestingBotClient(key, secret);
var clientKey = await client.Team.GetUserClientKeyAsync(userId);
$client = new TestingBot\Client($key, $secret);
$clientKey = $client->teamManagement()->getUserClientKey($userId);
TestingbotREST restApi = new TestingbotREST(key, secret);
JsonElement clientKey = restApi.getTeamMemberClientKey(userId);
const TestingBot = require('testingbot-api');
const api = new TestingBot({
api_key: "your-tb-key",
api_secret: "your-tb-secret"
});
const { client_key } = await api.getUserClientKey(userId);