Base URL https://your-testhide-server
All endpoints require Authorization: Bearer <token>. Obtain a token via POST /api/v3/authenticate or create a long-lived API token in Settings → API Tokens.
Health
Server liveness probe. No authentication required.
Returns server status and version. No auth required. Use as a Kubernetes liveness probe or uptime-monitor endpoint.
Required headers
Header Value
— None required
curl
Python
curl https://your-testhide-server/api/v3/healthz
import requests
r = requests.get("https://your-testhide-server/api/v3/healthz")
print(r.json())
Response 200
{"status": "ok", "version": "3.14.2", "build": "a1b2c3d"}
Authentication
Obtain and manage JWT tokens. Session tokens expire in 8 hours; API tokens never expire unless revoked.
Exchange username and password for a JWT session token. Pass the returned token in the Authorization header for all subsequent requests.
Required headers
Header Value
Content-Type application/json
Required body
Field Type Description
username string User email or login name
password string Account password
curl
Python
curl -X POST https://your-testhide-server/api/v3/authenticate \
-H "Content-Type: application/json" \
-d '{"username": "[email protected] ", "password": "s3cr3t!"}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/authenticate",
json={"username": "[email protected] ", "password": "s3cr3t!"}
)
token = r.json()["token"]
print(token)
Response 200
{"token": "eyJhbGci...", "expires_at": "2026-05-21T14:00:00Z", "user_id": 42}
Invalidate the current session token immediately. The token is server-side blacklisted.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -X POST https://your-testhide-server/api/v3/logout \
-H "Authorization: Bearer $TOKEN"
import requests
requests.post(
"https://your-testhide-server/api/v3/logout",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
Response 204
(no content)
Return the profile of the currently authenticated user including role, permissions, and accessible project IDs.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl https://your-testhide-server/api/v3/me \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/me",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
{"id": 42, "email": "[email protected] ", "role": "admin", "projects": [1, 3, 7]}
Return server-level configuration visible to the current user — feature flags, enabled integrations, AI settings, and global pipeline options.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl https://your-testhide-server/api/v3/config \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/config",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
{"version": "3.14.2", "global_options": {"ai_assist": {"enabled": true}, "max_parallel_builds": 20}}
Authenticate via SAML SSO. Exchange a base64-encoded IdP-signed SAML response for a Testhide JWT session token.
Required headers
Header Value
Content-Type application/json
Required body
Field Type Description
saml_response string Base64-encoded SAML response from IdP
curl
Python
curl -X POST https://your-testhide-server/api/v3/sso \
-H "Content-Type: application/json" \
-d '{"saml_response": "PHNhbWxwOlJlc3BvbnNl..."}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/sso",
json={"saml_response": "PHNhbWxwOlJlc3BvbnNl..."}
)
print(r.json()["token"])
Response 200
{"token": "eyJhbGci...", "user_id": 42, "expires_at": "2026-05-21T14:00:00Z"}
POST /api/v3/reset-password
Request a password reset email. A one-use time-limited link is sent to the address if an account exists.
Required headers
Header Value
Content-Type application/json
Required body
Field Type Description
email string Account email address
curl
Python
curl -X POST https://your-testhide-server/api/v3/reset-password \
-H "Content-Type: application/json" \
-d '{"email": "[email protected] "}'
import requests
requests.post(
"https://your-testhide-server/api/v3/reset-password",
json={"email": "[email protected] "}
)
Response 202
{"detail": "Reset link sent if the account exists."}
POST /api/v3/reset-password/confirm
Complete a password reset using the token from the reset email and the new desired password.
Required headers
Header Value
Content-Type application/json
Required body
Field Type Description
token string Reset token from the email link
new_password string New password (min 8 chars)
curl
Python
curl -X POST https://your-testhide-server/api/v3/reset-password/confirm \
-H "Content-Type: application/json" \
-d '{"token": "abc123xyz", "new_password": "Str0ng!Pass"}'
import requests
requests.post(
"https://your-testhide-server/api/v3/reset-password/confirm",
json={"token": "abc123xyz", "new_password": "Str0ng!Pass"}
)
Response 200
{"detail": "Password updated successfully."}
List all long-lived API tokens for the current user. Token secrets are never returned after creation.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl https://your-testhide-server/api/v3/api-tokens \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/api-tokens",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
[{"id": 1, "name": "CI Bot", "created_at": "2026-01-10T09:00:00Z", "last_used": "2026-05-19T12:30:00Z"}]
Create a new long-lived API token. The token secret is returned only once — store it securely immediately.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
name string Human-readable label, e.g. "GitHub Actions"
curl
Python
curl -X POST https://your-testhide-server/api/v3/api-tokens \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "GitHub Actions Bot"}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/api-tokens",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"name": "GitHub Actions Bot"}
)
secret = r.json()["secret"] # save this — shown only once
Response 201
{"id": 5, "name": "GitHub Actions Bot", "secret": "th_live_xK9p...Q2rZ", "created_at": "2026-05-20T10:00:00Z"}
DELETE /api/v3/api-tokens/{token_id}
Permanently revoke an API token. Takes effect immediately.
Required headers
Header Value
Authorization Bearer <token>
Path parameters
Param Type Description
token_id integer ID of the token to revoke
curl
Python
curl -X DELETE https://your-testhide-server/api/v3/api-tokens/5 \
-H "Authorization: Bearer $TOKEN"
import requests
requests.delete(
"https://your-testhide-server/api/v3/api-tokens/5",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
Response 204
(no content)
Users
Manage platform users. Admin role required for create/update operations.
Return a paginated list of all platform users with their roles and project assignments.
Required headers
Header Value
Authorization Bearer <token>
Optional query params
Param Type Description
page integer Page number (default: 1)
limit integer Items per page (default: 50, max: 200)
search string Filter by email or name
curl
Python
curl "https://your-testhide-server/api/v3/users?page=1&limit=20" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/users",
params={"page": 1, "limit": 20},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
{"total": 84, "results": [{"id": 1, "email": "[email protected] ", "role": "admin", "active": true}]}
Create a new platform user. An invitation email is sent to the provided address.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
email string User email address
role string admin | developer | viewer
Optional body
Field Type Description
first_name string First name
last_name string Last name
project_ids array[int] Grant access to these project IDs
curl
Python
curl -X POST https://your-testhide-server/api/v3/users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected] ", "role": "developer", "project_ids": [1, 3]}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/users",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"email": "[email protected] ", "role": "developer", "project_ids": [1, 3]}
)
print(r.json()["id"])
Response 201
{"id": 88, "email": "[email protected] ", "role": "developer", "invited_at": "2026-05-20T10:00:00Z"}
GET /api/v3/users/{user_id}
Fetch full profile of a single user by ID including role, project access, and last login.
Required headers
Header Value
Authorization Bearer <token>
Path parameters
Param Type Description
user_id integer ID of the user
curl
Python
curl https://your-testhide-server/api/v3/users/88 \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/users/88",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
{"id": 88, "email": "[email protected] ", "role": "developer", "active": true, "projects": [1, 3], "last_login": "2026-05-19T08:00:00Z"}
PUT /api/v3/users/{user_id}
Update a user's role, active status, or project assignments.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path parameters
Param Type Description
user_id integer ID of the user to update
Optional body
Field Type Description
role string admin | developer | viewer
active boolean Enable or disable the account
project_ids array[int] Replace project access list entirely
curl
Python
curl -X PUT https://your-testhide-server/api/v3/users/88 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "admin", "project_ids": [1, 3, 7]}'
import requests
r = requests.put(
"https://your-testhide-server/api/v3/users/88",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"role": "admin", "project_ids": [1, 3, 7]}
)
print(r.json())
Response 200
{"id": 88, "email": "[email protected] ", "role": "admin", "project_ids": [1, 3, 7]}
GET /api/v3/users/{user_id}/permissions
Return the resolved effective permission set for a user across all projects and platform resources.
Required headers
Header Value
Authorization Bearer <token>
Path parameters
Param Type Description
user_id integer ID of the user
curl
Python
curl https://your-testhide-server/api/v3/users/88/permissions \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/users/88/permissions",
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
{"user_id": 88, "can_start_builds": true, "can_manage_nodes": false, "is_admin": false, "projects": {"1": "write", "3": "read"}}
Projects
Projects group jobs, builds, and settings into isolated workspaces.
List all projects the current user has access to.
Required headers
Header Value Authorization Bearer <token>
curl Python
curl https://your-testhide-server/api/v3/projects \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/projects", headers={"Authorization": "Bearer YOUR_TOKEN"})
for p in r.json(): print(p["id"], p["name"])
Response 200
[{"id": 1, "name": "Backend API", "slug": "backend-api", "jobs_count": 12}]
Create a new project. The creating user is automatically assigned as project admin.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description name string Project display name
Optional body
Field Type Description
description string Short description
scm_endpoint_id integer Default SCM connection ID
curl Python
curl -X POST https://your-testhide-server/api/v3/projects \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Mobile App", "description": "iOS/Android tests", "scm_endpoint_id": 2}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/projects",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"name": "Mobile App", "description": "iOS/Android tests", "scm_endpoint_id": 2}
)
print(r.json()["id"])
Response 201
{"id": 12, "name": "Mobile App", "slug": "mobile-app", "webhook_secret": "wh_sec_abc..."}
GET /api/v3/projects/{project_id}
Fetch full details of a project including webhook URL, SCM configuration, and job statistics.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description project_id integer Project ID
curl Python
curl https://your-testhide-server/api/v3/projects/12 \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/projects/12", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"id": 12, "name": "Mobile App", "jobs_count": 8, "last_build_at": "2026-05-19T18:00:00Z", "webhook_url": "https://your-testhide-server/webhook/proj/12"}
PUT /api/v3/projects/{project_id}
Update project name, description, or SCM endpoint association.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description project_id integer Project ID
Optional body
Field Type Description
name string New display name
description string Updated description
scm_endpoint_id integer Default SCM connection
curl Python
curl -X PUT https://your-testhide-server/api/v3/projects/12 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Mobile App v2", "scm_endpoint_id": 3}'
import requests
r = requests.put("https://your-testhide-server/api/v3/projects/12", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"name": "Mobile App v2", "scm_endpoint_id": 3})
print(r.json())
Response 200
{"id": 12, "name": "Mobile App v2", "scm_endpoint_id": 3}
POST /api/v3/projects/{project_id}/rotate-webhook-secret
Generate a new webhook HMAC secret. The old secret is invalidated immediately — update your SCM webhook settings after rotation.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description project_id integer Project ID
curl Python
curl -X POST https://your-testhide-server/api/v3/projects/12/rotate-webhook-secret \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.post("https://your-testhide-server/api/v3/projects/12/rotate-webhook-secret", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json()["webhook_secret"])
Response 200
{"webhook_secret": "wh_sec_xK9p...Q2rZ"}
Jobs
Jobs define the test pipeline — what runs, on which nodes, with which configuration. A Job produces Builds when triggered.
List all jobs accessible to the current user, optionally filtered by project.
Required headers
Header Value Authorization Bearer <token>
Optional query params
Param Type Description
project_id integer Filter by project
search string Filter by job name
enabled boolean Filter by enabled state
curl Python
curl "https://your-testhide-server/api/v3/jobs?project_id=1&enabled=true" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/jobs", params={"project_id": 1, "enabled": "true"}, headers={"Authorization": "Bearer YOUR_TOKEN"})
for job in r.json(): print(job["id"], job["name"])
Response 200
[{"id": 55, "name": "Regression Suite", "project_id": 1, "node_pool_id": 2, "enabled": true}]
Create a new job within a project.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
name string Job display name
project_id integer Parent project ID
Optional body
Field Type Description
node_pool_id integer Target node pool (default: any available)
timeout_minutes integer Build timeout in minutes (default: 60)
max_parallel integer Max concurrent builds (default: 1)
pipeline_template_id integer Pre-defined pipeline template to apply
curl Python
curl -X POST https://your-testhide-server/api/v3/jobs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Smoke Tests",
"project_id": 1,
"node_pool_id": 2,
"timeout_minutes": 30,
"max_parallel": 3
}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/jobs",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"name": "Smoke Tests", "project_id": 1, "node_pool_id": 2, "timeout_minutes": 30, "max_parallel": 3}
)
print(r.json()["id"])
Response 201
{"id": 56, "name": "Smoke Tests", "project_id": 1, "enabled": true}
Fetch full job details including configuration, node pool, and last build status.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description job_id integer Job ID
curl Python
curl https://your-testhide-server/api/v3/jobs/55 \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/jobs/55", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"id": 55, "name": "Regression Suite", "node_pool_id": 2, "last_build_id": 1024, "last_build_status": "passed"}
Update job settings: name, node pool, timeout, enabled state, or max parallel builds.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description job_id integer Job ID
Optional body
Field Type Description
name string New display name
enabled boolean Enable or pause the job
node_pool_id integer Reassign to a different pool
timeout_minutes integer Build timeout in minutes
curl Python
curl -X PUT https://your-testhide-server/api/v3/jobs/55 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false, "timeout_minutes": 90}'
import requests
r = requests.put("https://your-testhide-server/api/v3/jobs/55", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"enabled": False, "timeout_minutes": 90})
print(r.json())
Response 200
{"id": 55, "enabled": false, "timeout_minutes": 90}
DELETE /api/v3/jobs/{job_id}
Permanently delete a job and all its associated builds. This action cannot be undone.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description job_id integer Job ID to delete
curl Python
curl -X DELETE https://your-testhide-server/api/v3/jobs/55 \
-H "Authorization: Bearer $TOKEN"
import requests
requests.delete("https://your-testhide-server/api/v3/jobs/55", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 204
(no content)
GET /api/v3/jobs/{job_id}/configuration
Return the full pipeline configuration — setup commands, test command, environment variables, and artifact paths.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description job_id integer Job ID
curl Python
curl https://your-testhide-server/api/v3/jobs/55/configuration \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/jobs/55/configuration", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"setup": ["pip install -r requirements.txt"], "command": "pytest tests/ -x", "env": {"ENV": "staging"}, "artifacts": ["reports/*.xml"]}
PUT /api/v3/jobs/{job_id}/configuration
Replace the full pipeline configuration for a job. The next build will use the updated config.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description job_id integer Job ID
Required body
Field Type Description
command string Main test execution command
setup array[string] Shell commands run before the main command
env object Environment variables key/value map
artifacts array[string] Glob patterns for artifact collection
curl Python
curl -X PUT https://your-testhide-server/api/v3/jobs/55/configuration \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"setup": ["pip install -r requirements.txt"],
"command": "pytest tests/ --junitxml=report.xml",
"env": {"ENV": "staging", "DB_HOST": "db.internal"},
"artifacts": ["report.xml", "logs/*.log"]
}'
import requests
r = requests.put(
"https://your-testhide-server/api/v3/jobs/55/configuration",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={
"setup": ["pip install -r requirements.txt"],
"command": "pytest tests/ --junitxml=report.xml",
"env": {"ENV": "staging", "DB_HOST": "db.internal"},
"artifacts": ["report.xml", "logs/*.log"]
}
)
print(r.status_code)
Response 200
{"job_id": 55, "updated_at": "2026-05-20T10:15:00Z"}
POST /api/v3/jobs/{job_id}/export
Export a job as a portable JSON bundle including configuration, pipeline template, and all settings. Pair with /jobs/import to migrate between servers.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description job_id integer Job ID to export
curl Python
curl -X POST https://your-testhide-server/api/v3/jobs/55/export \
-H "Authorization: Bearer $TOKEN" \
-o job_55_export.json
import requests, json
r = requests.post("https://your-testhide-server/api/v3/jobs/55/export", headers={"Authorization": "Bearer YOUR_TOKEN"})
with open("job_55_export.json", "w") as f:
json.dump(r.json(), f, indent=2)
Response 200
{"export_version": "1", "job": {"name": "Regression Suite", ...}, "configuration": {...}}
Import a job from a bundle exported via /jobs/{id}/export. Creates a new job in the specified target project.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
project_id integer Target project for the imported job
bundle object Export bundle from /jobs/{id}/export
curl Python
curl -X POST https://your-testhide-server/api/v3/jobs/import \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project_id": 3, "bundle": {...}}'
import requests, json
bundle = json.load(open("job_55_export.json"))
r = requests.post(
"https://your-testhide-server/api/v3/jobs/import",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"project_id": 3, "bundle": bundle}
)
print("New job ID:", r.json()["id"])
Response 201
{"id": 99, "name": "Regression Suite (imported)", "project_id": 3}
Builds
Builds are triggered executions of a Job. Each build runs the pipeline on CI agents and collects test results and artifacts.
Manually trigger a build for a job. Accepts optional branch, commit SHA, and runtime environment variable overrides.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
job_id integer Job to trigger
Optional body
Field Type Description
branch string Git branch (default: job default branch)
commit_sha string Exact commit SHA to test
env object Runtime env var overrides for this build only
priority integer Queue priority 1–10 (higher = sooner)
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/start \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"job_id": 55,
"branch": "main",
"commit_sha": "a1b2c3d4",
"env": {"RUN_SLOW": "true"}
}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/builds/start",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"job_id": 55, "branch": "main", "commit_sha": "a1b2c3d4", "env": {"RUN_SLOW": "true"}}
)
build_id = r.json()["id"]
print("Build started:", build_id)
Response 201
{"id": 1025, "job_id": 55, "status": "queued", "branch": "main", "commit_sha": "a1b2c3d4", "created_at": "2026-05-20T10:00:00Z"}
List builds with filtering by job, status, branch, or date range. Returns paginated results sorted by creation time descending.
Required headers
Header Value Authorization Bearer <token>
Optional query params
Param Type Description
job_id integer Filter by job
status string queued | running | passed | failed
branch string Filter by branch name
page integer Page number (default: 1)
limit integer Results per page (default: 25)
curl Python
curl "https://your-testhide-server/api/v3/builds?job_id=55&status=failed&limit=10" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/builds",
params={"job_id": 55, "status": "failed", "limit": 10},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
print(r.json())
Response 200
{"total": 3, "results": [{"id": 1024, "status": "failed", "branch": "main", "duration_s": 312, "failed_tests": 7}]}
GET /api/v3/builds/{build_id}
Fetch full build details: status, timings, node assignment, test counts, and triggered-by information.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID
curl Python
curl https://your-testhide-server/api/v3/builds/1024 \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/builds/1024", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"id": 1024, "job_id": 55, "status": "passed", "duration_s": 287, "total_tests": 412, "passed": 410, "failed": 0, "skipped": 2, "node_id": 7}
POST /api/v3/builds/{build_id}/restart
Re-queue a finished build using the same commit SHA and configuration. Optionally restart only failed tests.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID to restart
Optional body
Field Type Description
failed_only boolean Run only tests that failed in previous build
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/1024/restart \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"failed_only": true}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/builds/1024/restart",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"failed_only": True}
)
print("New build ID:", r.json()["id"])
Response 201
{"id": 1026, "status": "queued", "restarted_from": 1024}
POST /api/v3/builds/{build_id}/stop
Abort a running or queued build. The build status is set to aborted.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID to stop
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/1025/stop \
-H "Authorization: Bearer $TOKEN"
import requests
requests.post("https://your-testhide-server/api/v3/builds/1025/stop", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 200
{"id": 1025, "status": "aborted"}
DELETE /api/v3/builds/{build_id}
Permanently delete a build and all associated test results, artifacts, and logs.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID to delete
curl Python
curl -X DELETE https://your-testhide-server/api/v3/builds/1020 \
-H "Authorization: Bearer $TOKEN"
import requests
requests.delete("https://your-testhide-server/api/v3/builds/1020", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 204
(no content)
POST /api/v3/builds/{build_id}/push_to_top
Move a queued build to the top of the job queue so it executes next.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID (must be in queued state)
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/1025/push_to_top \
-H "Authorization: Bearer $TOKEN"
import requests
requests.post("https://your-testhide-server/api/v3/builds/1025/push_to_top", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 200
{"id": 1025, "queue_position": 1}
POST /api/v3/builds/{build_id}/keep-forever
Pin a build so it is excluded from automatic cleanup and retention policies.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID to pin
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/1024/keep-forever \
-H "Authorization: Bearer $TOKEN"
import requests
requests.post("https://your-testhide-server/api/v3/builds/1024/keep-forever", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 200
{"id": 1024, "keep_forever": true}
GET /api/v3/builds/{build_id}/pipeline_logs
Return paginated pipeline-level logs (setup, teardown, and orchestration output) for a build. For test-level output use /builds/{id}/stream.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID
Optional query params
Param Type Description
offset integer Log line offset for pagination
limit integer Lines to return (default: 500)
curl Python
curl "https://your-testhide-server/api/v3/builds/1024/pipeline_logs?offset=0&limit=200" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/builds/1024/pipeline_logs",
params={"offset": 0, "limit": 200},
headers={"Authorization": "Bearer YOUR_TOKEN"}
)
for line in r.json()["lines"]: print(line)
Response 200
{"total_lines": 1240, "lines": ["[10:00:01] Setup started", "[10:00:03] pip install OK", "..."]}
GET /api/v3/builds/{build_id}/stream
Server-Sent Events stream of real-time build output. The connection stays open until the build finishes. Each event is a JSON line with type and data.
Required headers
Header Value
Authorization Bearer <token>
Accept text/event-stream
Path parameters
Param Type Description build_id integer Build ID to stream
curl Python
curl -N https://your-testhide-server/api/v3/builds/1025/stream \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: text/event-stream"
import requests
with requests.get(
"https://your-testhide-server/api/v3/builds/1025/stream",
headers={"Authorization": "Bearer YOUR_TOKEN", "Accept": "text/event-stream"},
stream=True
) as r:
for line in r.iter_lines():
if line:
print(line.decode())
SSE stream
data: {"type": "log", "data": "[10:00:05] PASSED tests/test_api.py::test_login"}
data: {"type": "status", "data": "passed"}
data: {"type": "done"}
POST /api/v3/builds/{build_id}/comment
Add a text comment to a build for team annotations or incident notes.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description build_id integer Build ID
Required body
Field Type Description text string Comment text
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/1024/comment \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"text": "Flaky DB connection — infra issue, not code."}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/builds/1024/comment",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"text": "Flaky DB connection — infra issue, not code."}
)
print(r.json())
Response 201
{"id": 88, "build_id": 1024, "text": "Flaky DB connection...", "author": "[email protected] "}
POST /api/v3/builds/{build_id}/retry-flaky
Re-run only the tests that the AI has classified as flaky in this build. Creates a new build targeting those specific test node IDs.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID containing flaky tests
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/1024/retry-flaky \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.post("https://your-testhide-server/api/v3/builds/1024/retry-flaky", headers={"Authorization": "Bearer YOUR_TOKEN"})
print("New build:", r.json()["id"], "| Retrying", r.json()["test_count"], "tests")
Response 201
{"id": 1027, "status": "queued", "test_count": 4, "restarted_from": 1024}
POST /api/v3/builds/git-notify
Notify Testhide of a new commit or pull-request event from an SCM that doesn't support native webhooks. Testhide evaluates matching job triggers and queues builds as appropriate.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
project_id integer Project to notify
branch string Branch that was pushed
commit_sha string Full commit SHA
Optional body
Field Type Description
author string Commit author email
message string Commit message
curl Python
curl -X POST https://your-testhide-server/api/v3/builds/git-notify \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project_id": 1,
"branch": "feature/login-fix",
"commit_sha": "d4e5f6a7",
"author": "[email protected] ",
"message": "Fix auth token refresh"
}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/builds/git-notify",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"project_id": 1, "branch": "feature/login-fix", "commit_sha": "d4e5f6a7", "author": "[email protected] "}
)
print("Builds queued:", r.json()["queued"])
Response 200
{"queued": 2, "build_ids": [1028, 1029]}
Artifacts
Files produced by builds — test reports, screenshots, binaries, logs. Stored per-build and downloadable on demand.
List artifacts for a build, optionally filtered by file type or name pattern.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description build_id integer Build to list artifacts for
Optional query params
Param Type Description
type string report | log | screenshot | binary
search string Filter by filename substring
curl Python
curl "https://your-testhide-server/api/v3/artifacts?build_id=1024" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/artifacts", params={"build_id": 1024}, headers={"Authorization": "Bearer YOUR_TOKEN"})
for a in r.json(): print(a["name"], a["size_bytes"])
Response 200
[{"id": 201, "name": "report.xml", "type": "report", "size_bytes": 48200, "created_at": "2026-05-20T10:05:00Z"}]
GET /api/v3/artifacts/tree
Return the artifact directory tree for a build — useful for navigating complex artifact hierarchies.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description build_id integer Build ID
curl Python
curl "https://your-testhide-server/api/v3/artifacts/tree?build_id=1024" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/artifacts/tree", params={"build_id": 1024}, headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"name": "/", "children": [{"name": "reports", "children": [{"name": "report.xml", "id": 201}]}, {"name": "logs", "children": []}]}
POST /api/v3/artifacts/upload
Upload an artifact file for a build. Use multipart/form-data. Called by CI agents automatically; use manually to attach external reports.
Required headers
Header Value
Authorization Bearer <token>
Content-Type multipart/form-data
Required form fields
Field Type Description
build_id integer Target build ID
file file File to upload
Optional form fields
Field Type Description
path string Virtual path inside the artifact tree (e.g. reports/)
curl Python
curl -X POST https://your-testhide-server/api/v3/artifacts/upload \
-H "Authorization: Bearer $TOKEN" \
-F "build_id=1024" \
-F "path=reports/" \
-F "[email protected] "
import requests
with open("report.xml", "rb") as f:
r = requests.post(
"https://your-testhide-server/api/v3/artifacts/upload",
headers={"Authorization": "Bearer YOUR_TOKEN"},
data={"build_id": 1024, "path": "reports/"},
files={"file": ("report.xml", f, "application/xml")}
)
print(r.json()["id"])
Response 201
{"id": 202, "name": "report.xml", "size_bytes": 48200, "path": "reports/report.xml"}
DELETE /api/v3/artifacts/{artifact_id}
Delete a single artifact file. Pinned builds cannot have artifacts deleted.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description artifact_id integer Artifact ID to delete
curl Python
curl -X DELETE https://your-testhide-server/api/v3/artifacts/201 \
-H "Authorization: Bearer $TOKEN"
import requests
requests.delete("https://your-testhide-server/api/v3/artifacts/201", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 204
(no content)
GET /api/v3/artifacts/{artifact_id}/download
Download the raw artifact file. Returns the file with Content-Disposition: attachment.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description artifact_id integer Artifact ID to download
curl Python
curl https://your-testhide-server/api/v3/artifacts/201/download \
-H "Authorization: Bearer $TOKEN" \
-o report.xml
import requests
r = requests.get("https://your-testhide-server/api/v3/artifacts/201/download", headers={"Authorization": "Bearer YOUR_TOKEN"})
with open("report.xml", "wb") as f:
f.write(r.content)
Response 200
(binary file content with Content-Type matching the artifact)
Reports & Tests
Access test execution results, history, and defect classification for individual test cases.
GET /api/v3/report/{build_id}
Return the aggregated test report for a build: pass/fail/skip counts, duration, and suite breakdown.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description build_id integer Build ID
curl Python
curl https://your-testhide-server/api/v3/report/1024 \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/report/1024", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"build_id": 1024, "total": 412, "passed": 400, "failed": 7, "skipped": 5, "duration_s": 287, "suites": [{"name": "auth", "passed": 45, "failed": 1}]}
Paginated list of individual test results for a build, with filtering by status, suite, or search string.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description build_id integer Build ID to query tests for
Optional query params
Param Type Description
status string passed | failed | skipped
suite string Filter by test suite name
search string Filter by test name substring
page integer Page number (default: 1)
limit integer Results per page (default: 50)
curl Python
curl "https://your-testhide-server/api/v3/tests?build_id=1024&status=failed" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/tests", params={"build_id": 1024, "status": "failed"}, headers={"Authorization": "Bearer YOUR_TOKEN"})
for t in r.json()["results"]: print(t["node_id"], t["message"])
Response 200
{"total": 7, "results": [{"id": 5001, "node_id": "tests/test_auth.py::test_token_refresh", "status": "failed", "duration_ms": 1230, "message": "AssertionError: Expected 200, got 401"}]}
GET /api/v3/tests/{test_id}/history
Return the execution history for a specific test case across recent builds — useful for spotting flakiness trends.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description test_id integer Test result ID
Optional query params
Param Type Description limit integer Number of past runs to return (default: 20)
curl Python
curl "https://your-testhide-server/api/v3/tests/5001/history?limit=10" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/tests/5001/history", params={"limit": 10}, headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"node_id": "tests/test_auth.py::test_token_refresh", "history": [{"build_id": 1024, "status": "failed"}, {"build_id": 1023, "status": "passed"}, {"build_id": 1022, "status": "failed"}]}
POST /api/v3/tests/{test_id}/classification
Manually override the AI-assigned classification for a failed test result. Classifications guide quarantine and retry decisions.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description test_id integer Test result ID
Required body
Field Type Description
classification string product_bug | infra | flaky | test_bug | no_defect
curl Python
curl -X POST https://your-testhide-server/api/v3/tests/5001/classification \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"classification": "product_bug"}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/tests/5001/classification",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"classification": "product_bug"}
)
print(r.json())
Response 200
{"test_id": 5001, "classification": "product_bug", "set_by": "[email protected] "}
POST /api/v3/tests/{test_id}/defect
Link a failed test to a defect ticket (Jira, GitHub Issues, etc.) for tracking.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description test_id integer Test result ID
Required body
Field Type Description
defect_key string Ticket key, e.g. AUTH-421
defect_url string Full URL to the ticket
curl Python
curl -X POST https://your-testhide-server/api/v3/tests/5001/defect \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"defect_key": "AUTH-421", "defect_url": "https://jira.corp.com/browse/AUTH-421"}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/tests/5001/defect",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"defect_key": "AUTH-421", "defect_url": "https://jira.corp.com/browse/AUTH-421"}
)
print(r.json())
Response 200
{"test_id": 5001, "defect_key": "AUTH-421", "defect_url": "https://jira.corp.com/browse/AUTH-421"}
POST /api/v3/tests/{test_id}/resolution
Set a resolution note for a failed test — explains the root cause or fix applied.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description test_id integer Test result ID
Required body
Field Type Description resolution string Free-text explanation of the resolution
curl Python
curl -X POST https://your-testhide-server/api/v3/tests/5001/resolution \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"resolution": "Fixed in PR #847 — token expiry now handles edge case."}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/tests/5001/resolution",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"resolution": "Fixed in PR #847 — token expiry now handles edge case."}
)
print(r.json())
Response 200
{"test_id": 5001, "resolution": "Fixed in PR #847...", "set_by": "[email protected] "}
POST /api/v3/tests/{test_id}/known-issue
Link a failed test to a tracked known-issue entry so future identical failures are auto-classified without manual review.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description test_id integer Test result ID
Required body
Field Type Description known_issue_id integer ID of an existing known-issue entry
curl Python
curl -X POST https://your-testhide-server/api/v3/tests/5001/known-issue \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"known_issue_id": 17}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/tests/5001/known-issue",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"known_issue_id": 17}
)
print(r.json())
Response 200
{"test_id": 5001, "known_issue_id": 17, "auto_classify_future": true}
Quarantine
Quarantined tests are excluded from build pass/fail determination while remaining tracked. Manage quarantine lists to stabilize noisy pipelines.
List all quarantined test node IDs for a job.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description job_id integer Job ID to query quarantine for
curl Python
curl "https://your-testhide-server/api/v3/quarantine?job_id=55" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/quarantine", params={"job_id": 55}, headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
[{"id": 1, "node_id": "tests/test_auth.py::test_token_refresh", "reason": "flaky", "quarantined_at": "2026-05-10T09:00:00Z"}]
Quarantine a single test node ID. Future builds will still run it but its failure won't affect the build result.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
job_id integer Job to apply quarantine to
node_id string Full test node ID (e.g. tests/test_auth.py::test_login)
reason string flaky | infra | wip
curl Python
curl -X POST https://your-testhide-server/api/v3/quarantine \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"job_id": 55, "node_id": "tests/test_auth.py::test_token_refresh", "reason": "flaky"}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/quarantine",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"job_id": 55, "node_id": "tests/test_auth.py::test_token_refresh", "reason": "flaky"}
)
print(r.json()["id"])
Response 201
{"id": 2, "node_id": "tests/test_auth.py::test_token_refresh", "reason": "flaky"}
POST /api/v3/quarantine/bulk
Quarantine multiple tests in a single request, or remove a list of node IDs from quarantine.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
job_id integer Job to apply changes to
action string add | remove
node_ids array[string] List of test node IDs
curl Python
curl -X POST https://your-testhide-server/api/v3/quarantine/bulk \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"job_id": 55, "action": "add", "node_ids": ["tests/test_a.py::test_x", "tests/test_b.py::test_y"]}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/quarantine/bulk",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"job_id": 55, "action": "add", "node_ids": ["tests/test_a.py::test_x", "tests/test_b.py::test_y"]}
)
print(r.json())
Response 200
{"added": 2, "skipped": 0}
GET /api/v3/quarantine/stats
Return quarantine statistics for a job — total quarantined, by reason, and age distribution.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description job_id integer Job ID
curl Python
curl "https://your-testhide-server/api/v3/quarantine/stats?job_id=55" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/quarantine/stats", params={"job_id": 55}, headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"total": 14, "by_reason": {"flaky": 9, "infra": 3, "wip": 2}, "oldest_days": 42}
GET /api/v3/quarantine/nodeids
Return a plain list of quarantined test node IDs for a job — suitable for passing to pytest with --deselect or for CI agent configuration.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description job_id integer Job ID
curl Python
curl "https://your-testhide-server/api/v3/quarantine/nodeids?job_id=55" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/quarantine/nodeids", params={"job_id": 55}, headers={"Authorization": "Bearer YOUR_TOKEN"})
node_ids = r.json()["node_ids"]
deselect_args = " ".join(f"--deselect={n}" for n in node_ids)
print(deselect_args)
Response 200
{"node_ids": ["tests/test_auth.py::test_token_refresh", "tests/test_db.py::test_conn_pool"]}
Pipeline Templates
Reusable pipeline configuration blueprints. Apply a template to multiple jobs to share setup commands, environment, and artifact patterns.
GET /api/v3/pipeline-templates
List all pipeline templates available to the current user.
Required headers
Header Value Authorization Bearer <token>
curl Python
curl https://your-testhide-server/api/v3/pipeline-templates \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/pipeline-templates", headers={"Authorization": "Bearer YOUR_TOKEN"})
for t in r.json(): print(t["id"], t["name"])
Response 200
[{"id": 3, "name": "Python pytest", "description": "Standard Python test pipeline", "jobs_using": 12}]
POST /api/v3/pipeline-templates
Create a new pipeline template.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
name string Template name
setup array[string] Setup shell commands
env object Default environment variables
Optional body
Field Type Description
description string Human-readable description
artifacts array[string] Default artifact glob patterns
curl Python
curl -X POST https://your-testhide-server/api/v3/pipeline-templates \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Node.js Jest",
"setup": ["npm ci"],
"env": {"NODE_ENV": "test"},
"artifacts": ["coverage/**", "test-results/*.xml"]
}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/pipeline-templates",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"name": "Node.js Jest", "setup": ["npm ci"], "env": {"NODE_ENV": "test"}, "artifacts": ["coverage/**"]}
)
print(r.json()["id"])
Response 201
{"id": 4, "name": "Node.js Jest", "jobs_using": 0}
PUT /api/v3/pipeline-templates/{template_id}
Update an existing pipeline template. All jobs using this template will pick up the changes on their next build.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description template_id integer Template ID to update
curl Python
curl -X PUT https://your-testhide-server/api/v3/pipeline-templates/4 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"setup": ["npm ci", "npx playwright install --with-deps"]}'
import requests
r = requests.put("https://your-testhide-server/api/v3/pipeline-templates/4", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"setup": ["npm ci", "npx playwright install --with-deps"]})
print(r.json())
Response 200
{"id": 4, "name": "Node.js Jest", "updated_at": "2026-05-20T11:00:00Z"}
DELETE /api/v3/pipeline-templates/{template_id}
Delete a pipeline template. Will fail if any jobs still reference it — reassign those jobs first.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description template_id integer Template ID to delete
curl Python
curl -X DELETE https://your-testhide-server/api/v3/pipeline-templates/4 \
-H "Authorization: Bearer $TOKEN"
import requests
requests.delete("https://your-testhide-server/api/v3/pipeline-templates/4", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 204
(no content)
Nodes / CI Agents
Physical or virtual machines running the Testhide agent binary. Nodes pick up builds from the queue and execute test pipelines.
List all registered nodes with their status, pool assignment, and current load.
Required headers
Header Value Authorization Bearer <token>
Optional query params
Param Type Description
pool_id integer Filter by node pool
status string online | offline | quarantined
curl Python
curl "https://your-testhide-server/api/v3/nodes?status=online" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/nodes", params={"status": "online"}, headers={"Authorization": "Bearer YOUR_TOKEN"})
for n in r.json(): print(n["name"], n["status"])
Response 200
[{"id": 7, "name": "agent-01", "status": "online", "pool_id": 2, "running_builds": 1, "cpu_pct": 62}]
Register a new CI agent node. Returns an agent token for the node to use when connecting to the server.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Required body
Field Type Description
name string Unique node name
pool_id integer Node pool to join
Optional body
Field Type Description
tags array[string] Labels for routing (e.g. ["linux", "gpu"])
max_parallel integer Max concurrent builds on this node (default: 1)
curl Python
curl -X POST https://your-testhide-server/api/v3/nodes \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "agent-05", "pool_id": 2, "tags": ["linux", "docker"], "max_parallel": 2}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/nodes",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"name": "agent-05", "pool_id": 2, "tags": ["linux", "docker"], "max_parallel": 2}
)
agent_token = r.json()["agent_token"]
print("Agent token:", agent_token) # configure agent with this
Response 201
{"id": 12, "name": "agent-05", "pool_id": 2, "agent_token": "agt_xK9p...Q2rZ"}
Find a node by name. Useful for scripted registration checks before adding a node.
Required headers
Header Value Authorization Bearer <token>
Required query params
Param Type Description name string Exact node name to look up
curl Python
curl "https://your-testhide-server/api/v3/nodes/find?name=agent-05" \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/nodes/find", params={"name": "agent-05"}, headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"id": 12, "name": "agent-05", "status": "online", "pool_id": 2}
GET /api/v3/nodes/{node_id}
Fetch full details for a single node: hardware info, uptime, running builds, and error counts.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description node_id integer Node ID
curl Python
curl https://your-testhide-server/api/v3/nodes/12 \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/nodes/12", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"id": 12, "name": "agent-05", "status": "online", "cpu_cores": 8, "ram_gb": 16, "uptime_s": 86400, "running_builds": 1}
PUT /api/v3/nodes/{node_id}
Update a node's name, pool assignment, tags, or max_parallel builds.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description node_id integer Node ID
Optional body
Field Type Description
pool_id integer Move to a different node pool
tags array[string] Replace the full tag list
max_parallel integer Max concurrent builds
curl Python
curl -X PUT https://your-testhide-server/api/v3/nodes/12 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"pool_id": 3, "max_parallel": 4}'
import requests
r = requests.put("https://your-testhide-server/api/v3/nodes/12", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"pool_id": 3, "max_parallel": 4})
print(r.json())
Response 200
{"id": 12, "pool_id": 3, "max_parallel": 4}
DELETE /api/v3/nodes/{node_id}
Deregister a CI node. Any running builds will be aborted. The agent binary can then be uninstalled from the host.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description node_id integer Node ID to deregister
curl Python
curl -X DELETE https://your-testhide-server/api/v3/nodes/12 \
-H "Authorization: Bearer $TOKEN"
import requests
requests.delete("https://your-testhide-server/api/v3/nodes/12", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 204
(no content)
POST /api/v3/nodes/{node_id}/quarantine
Quarantine a node — it stops receiving new build assignments but remains registered for inspection.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description node_id integer Node ID
curl Python
curl -X POST https://your-testhide-server/api/v3/nodes/12/quarantine \
-H "Authorization: Bearer $TOKEN"
import requests
requests.post("https://your-testhide-server/api/v3/nodes/12/quarantine", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 200
{"id": 12, "status": "quarantined"}
GET /api/v3/nodes/{node_id}/health
Return real-time health metrics for a node: CPU, memory, disk, and agent heartbeat age.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description node_id integer Node ID
curl Python
curl https://your-testhide-server/api/v3/nodes/12/health \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/nodes/12/health", headers={"Authorization": "Bearer YOUR_TOKEN"})
print(r.json())
Response 200
{"node_id": 12, "cpu_pct": 62, "ram_pct": 48, "disk_free_gb": 120, "last_heartbeat_s": 4}
POST /api/v3/nodes/{node_id}/restart
Send a restart command to the Testhide agent process on a node. Useful after configuration changes or to clear stuck builds.
Required headers
Header Value Authorization Bearer <token>
Path parameters
Param Type Description node_id integer Node ID
curl Python
curl -X POST https://your-testhide-server/api/v3/nodes/12/restart \
-H "Authorization: Bearer $TOKEN"
import requests
requests.post("https://your-testhide-server/api/v3/nodes/12/restart", headers={"Authorization": "Bearer YOUR_TOKEN"})
Response 202
{"detail": "Restart command sent to node 12."}
POST /api/v3/nodes/{node_id}/execute
Run an ad-hoc shell command on a node and return stdout/stderr. Useful for diagnostics. Requires admin role.
Required headers
Header Value Authorization Bearer <token> Content-Type application/json
Path parameters
Param Type Description node_id integer Node ID
Required body
Field Type Description
command string Shell command to execute
Optional body
Field Type Description
timeout_s integer Max execution time in seconds (default: 30)
curl Python
curl -X POST https://your-testhide-server/api/v3/nodes/12/execute \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "df -h /", "timeout_s": 10}'
import requests
r = requests.post(
"https://your-testhide-server/api/v3/nodes/12/execute",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={"command": "df -h /", "timeout_s": 10}
)
print(r.json()["stdout"])
Response 200
{"exit_code": 0, "stdout": "Filesystem Size Used Avail Use%\n/dev/sda1 500G 380G 120G 76%", "stderr": ""}
GET /api/v3/nodes/agent/latest
Return download URLs and checksums for the latest Testhide agent binary for each supported platform.
Required headers
Header Value Authorization Bearer <token>
curl Python
curl https://your-testhide-server/api/v3/nodes/agent/latest \
-H "Authorization: Bearer $TOKEN"
import requests
r = requests.get("https://your-testhide-server/api/v3/nodes/agent/latest", headers={"Authorization": "Bearer YOUR_TOKEN"})
linux = r.json()["linux_amd64"]
print("Download:", linux["url"])
Response 200
{"version": "3.14.2", "linux_amd64": {"url": "https://your-server/agent/3.14.2/linux-amd64", "sha256": "abc123..."}, "windows_amd64": {"url": "...", "sha256": "..."}}
Node Pools
Group CI agents into pools for targeted job routing. Pools let you assign jobs to specific hardware or environment tiers.
List all node pools with member counts and routing rules.
Required headers
Header Value
Authorization Bearer <token>
Optional query params
Param Type Description
project_id int Filter pools by project
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/node-pools
import requests
r = requests.get(
"https://your-testhide-server/api/v3/node-pools",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": 3, "name": "linux-large", "project_id": 12,
"node_count": 8, "labels": {"arch": "amd64", "size": "large"}}]
Create a new node pool. Assign labels that pipeline steps can target via pool: selectors.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
name string Pool name (unique per project)
project_id int Owning project ID
Optional body
Field Type Description
labels object Key-value labels for job routing
max_parallel int Max concurrent jobs in pool
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"linux-large","project_id":12,"labels":{"arch":"amd64","size":"large"},"max_parallel":10}' \
https://your-testhide-server/api/v3/node-pools
import requests
r = requests.post(
"https://your-testhide-server/api/v3/node-pools",
headers={"Authorization": "Bearer TOKEN"},
json={"name": "linux-large", "project_id": 12,
"labels": {"arch": "amd64", "size": "large"}, "max_parallel": 10}
)
print(r.json())
Response 201
{"id": 3, "name": "linux-large", "project_id": 12, "max_parallel": 10,
"labels": {"arch": "amd64", "size": "large"}, "node_count": 0}
PUT /api/v3/node-pools/{id}
Update pool name, labels, or concurrency limits.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path params
Param Type Description
id int Pool ID
Optional body
Field Type Description
name string New pool name
labels object Replacement label set
max_parallel int Max concurrent jobs
curl
Python
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_parallel":20,"labels":{"arch":"amd64","size":"xlarge"}}' \
https://your-testhide-server/api/v3/node-pools/3
import requests
r = requests.put(
"https://your-testhide-server/api/v3/node-pools/3",
headers={"Authorization": "Bearer TOKEN"},
json={"max_parallel": 20, "labels": {"arch": "amd64", "size": "xlarge"}}
)
print(r.json())
Response 200
{"id": 3, "name": "linux-large", "max_parallel": 20,
"labels": {"arch": "amd64", "size": "xlarge"}, "node_count": 8}
DELETE /api/v3/node-pools/{id}
Delete a node pool. Nodes in the pool are unassigned, not deleted. Fails if active builds are routed to this pool.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Pool ID
curl
Python
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/node-pools/3
import requests
r = requests.delete(
"https://your-testhide-server/api/v3/node-pools/3",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.status_code) # 204
Response 204
— No content —
Docker Agents
Manage ephemeral Docker-based CI agents. Spawn containers on demand, stream logs, and destroy them when done.
List all Docker agent containers across all hosts. Returns status, image, and assigned build.
Required headers
Header Value
Authorization Bearer <token>
Optional query params
Param Type Description
status string running | stopped | error
project_id int Filter by project
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/docker-agents?status=running"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/docker-agents",
headers={"Authorization": "Bearer TOKEN"},
params={"status": "running"}
)
print(r.json())
Response 200
[{"id": "da-7f3c", "host": "build-host-01", "image": "testhide/agent:3.14",
"status": "running", "build_id": 9812, "started_at": "2025-06-10T08:12:00Z"}]
POST /api/v3/docker-agents/spawn
Spawn a new Docker agent container on a specified host. The container registers itself with the server and is immediately available to pick up queued jobs.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
host string Docker host identifier or IP
image string Docker image to use (e.g. testhide/agent:3.14)
Optional body
Field Type Description
pool_id int Assign to a node pool
env object Extra environment variables injected into container
memory_mb int Memory limit in MB
cpus float CPU quota (e.g. 2.0)
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"host":"build-host-01","image":"testhide/agent:3.14","pool_id":3,"cpus":4.0,"memory_mb":8192}' \
https://your-testhide-server/api/v3/docker-agents/spawn
import requests
r = requests.post(
"https://your-testhide-server/api/v3/docker-agents/spawn",
headers={"Authorization": "Bearer TOKEN"},
json={"host": "build-host-01", "image": "testhide/agent:3.14",
"pool_id": 3, "cpus": 4.0, "memory_mb": 8192}
)
print(r.json())
Response 201
{"id": "da-9a1e", "host": "build-host-01", "status": "starting",
"image": "testhide/agent:3.14", "pool_id": 3}
POST /api/v3/docker-agents/{id}/start
Start a stopped Docker agent container without re-spawning it.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id string Docker agent container ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/docker-agents/da-7f3c/start
import requests
r = requests.post(
"https://your-testhide-server/api/v3/docker-agents/da-7f3c/start",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"id": "da-7f3c", "status": "running"}
POST /api/v3/docker-agents/{id}/stop
Gracefully stop a running Docker agent. The container is paused and can be restarted later.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id string Docker agent container ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/docker-agents/da-7f3c/stop
import requests
r = requests.post(
"https://your-testhide-server/api/v3/docker-agents/da-7f3c/stop",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"id": "da-7f3c", "status": "stopped"}
DELETE /api/v3/docker-agents/{id}
Destroy and remove a Docker agent container. The container is stopped and deleted from the host. Any running build is aborted.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id string Docker agent container ID
curl
Python
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/docker-agents/da-7f3c
import requests
r = requests.delete(
"https://your-testhide-server/api/v3/docker-agents/da-7f3c",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.status_code) # 204
Response 204
— No content —
GET /api/v3/docker-agents/{id}/logs
Fetch the last N lines of stdout/stderr from a Docker agent container.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id string Docker agent container ID
Optional query params
Param Type Description
tail int Number of lines to return (default 200)
stream bool If true, returns SSE stream of live log lines
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/docker-agents/da-7f3c/logs?tail=100"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/docker-agents/da-7f3c/logs",
headers={"Authorization": "Bearer TOKEN"},
params={"tail": 100}
)
print(r.json())
Response 200
{"lines": ["[08:12:01] Agent started", "[08:12:02] Connected to server",
"[08:12:05] Picked up build 9812"]}
Webhooks
Register HTTP endpoints to receive real-time events when builds start, finish, or change state.
List all registered webhooks with their event subscriptions and delivery stats.
Required headers
Header Value
Authorization Bearer <token>
Optional query params
Param Type Description
project_id int Filter by project
active bool Return only active/inactive hooks
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/webhooks
import requests
r = requests.get(
"https://your-testhide-server/api/v3/webhooks",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": 14, "url": "https://hooks.example.com/testhide",
"events": ["build.finished","build.failed"], "active": true,
"deliveries_ok": 312, "deliveries_failed": 2}]
Register a new webhook. Testhide signs each delivery with HMAC-SHA256 using the secret you provide.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
url string HTTPS endpoint to deliver events to
events string[] Event types: build.started, build.finished, build.failed, build.cancelled, test.flaky, test.quarantined, node.offline
Optional body
Field Type Description
secret string HMAC secret for signature verification
project_id int Scope to a single project
active bool Enable immediately (default true)
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/testhide","events":["build.finished","build.failed"],"secret":"s3cr3t"}' \
https://your-testhide-server/api/v3/webhooks
import requests
r = requests.post(
"https://your-testhide-server/api/v3/webhooks",
headers={"Authorization": "Bearer TOKEN"},
json={"url": "https://hooks.example.com/testhide",
"events": ["build.finished", "build.failed"],
"secret": "s3cr3t"}
)
print(r.json())
Response 201
{"id": 14, "url": "https://hooks.example.com/testhide",
"events": ["build.finished","build.failed"], "active": true}
Update webhook URL, event subscriptions, secret, or active state.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path params
Param Type Description
id int Webhook ID
Optional body
Field Type Description
url string New target URL
events string[] Replacement event list
secret string New HMAC secret
active bool Enable or disable the hook
curl
Python
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"active":false}' \
https://your-testhide-server/api/v3/webhooks/14
import requests
r = requests.put(
"https://your-testhide-server/api/v3/webhooks/14",
headers={"Authorization": "Bearer TOKEN"},
json={"active": False}
)
print(r.json())
Response 200
{"id": 14, "active": false, "events": ["build.finished","build.failed"]}
DELETE /api/v3/webhooks/{id}
Permanently delete a webhook registration.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Webhook ID
curl
Python
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/webhooks/14
import requests
r = requests.delete(
"https://your-testhide-server/api/v3/webhooks/14",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.status_code) # 204
Response 204
— No content —
POST /api/v3/webhooks/{id}/test
Send a test ping delivery to the webhook URL to verify connectivity and signature validation.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Webhook ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/webhooks/14/test
import requests
r = requests.post(
"https://your-testhide-server/api/v3/webhooks/14/test",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"delivered": true, "status_code": 200, "latency_ms": 142}
GET /api/v3/webhooks/{id}/history
Retrieve recent delivery history for a webhook, including response codes and error details.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Webhook ID
Optional query params
Param Type Description
limit int Max deliveries to return (default 50)
status string ok | failed — filter by delivery outcome
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/webhooks/14/history?limit=20&status=failed"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/webhooks/14/history",
headers={"Authorization": "Bearer TOKEN"},
params={"limit": 20, "status": "failed"}
)
print(r.json())
Response 200
[{"delivery_id": "d-882f", "event": "build.failed", "status_code": 503,
"error": "connection refused", "attempted_at": "2025-06-10T07:55:12Z"}]
POST /api/v3/webhooks/bulk-delete
Delete multiple webhooks in a single request.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
ids int[] Array of webhook IDs to delete
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids":[14,15,16]}' \
https://your-testhide-server/api/v3/webhooks/bulk-delete
import requests
r = requests.post(
"https://your-testhide-server/api/v3/webhooks/bulk-delete",
headers={"Authorization": "Bearer TOKEN"},
json={"ids": [14, 15, 16]}
)
print(r.json())
Response 200
{"deleted": 3, "ids": [14, 15, 16]}
MS Teams
Configure Microsoft Teams notification channels to receive build and test result alerts directly in Teams channels.
List all configured MS Teams notification channels.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ms-teams
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ms-teams",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": 5, "name": "CI Alerts", "project_id": 12,
"webhook_url": "https://outlook.office.com/webhook/...",
"events": ["build.failed","test.flaky"], "active": true}]
Register a new MS Teams incoming webhook for build notifications. Get the webhook URL from the Teams channel connector settings.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
name string Display name for this integration
webhook_url string MS Teams incoming webhook URL
project_id int Project to monitor
events string[] Events: build.failed, build.finished, test.flaky, test.quarantined, node.offline
Optional body
Field Type Description
mention_on_fail string Teams user email to @mention on failures
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"CI Alerts","webhook_url":"https://outlook.office.com/webhook/xxx","project_id":12,"events":["build.failed","test.flaky"]}' \
https://your-testhide-server/api/v3/ms-teams
import requests
r = requests.post(
"https://your-testhide-server/api/v3/ms-teams",
headers={"Authorization": "Bearer TOKEN"},
json={"name": "CI Alerts",
"webhook_url": "https://outlook.office.com/webhook/xxx",
"project_id": 12,
"events": ["build.failed", "test.flaky"]}
)
print(r.json())
Response 201
{"id": 5, "name": "CI Alerts", "active": true,
"events": ["build.failed","test.flaky"]}
Update a Teams notification channel — change events, webhook URL, or toggle active state.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path params
Param Type Description
id int Integration ID
Optional body
Field Type Description
events string[] Replacement event list
webhook_url string New webhook URL
active bool Enable or disable
curl
Python
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"events":["build.failed","build.finished","test.flaky"],"active":true}' \
https://your-testhide-server/api/v3/ms-teams/5
import requests
r = requests.put(
"https://your-testhide-server/api/v3/ms-teams/5",
headers={"Authorization": "Bearer TOKEN"},
json={"events": ["build.failed", "build.finished", "test.flaky"], "active": True}
)
print(r.json())
Response 200
{"id": 5, "active": true, "events": ["build.failed","build.finished","test.flaky"]}
DELETE /api/v3/ms-teams/{id}
Remove a Teams notification integration.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Integration ID
curl
Python
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ms-teams/5
import requests
r = requests.delete(
"https://your-testhide-server/api/v3/ms-teams/5",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.status_code) # 204
Response 204
— No content —
POST /api/v3/ms-teams/{id}/test
Send a test message to the Teams channel to verify the webhook is reachable and the integration is working.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Integration ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ms-teams/5/test
import requests
r = requests.post(
"https://your-testhide-server/api/v3/ms-teams/5/test",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"sent": true, "status_code": 200, "latency_ms": 198}
SCM Endpoints
Connect source control repositories (GitHub, GitLab, Bitbucket) to link builds to commits, branches, and pull requests.
List all SCM integrations configured on the server.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/scm
import requests
r = requests.get(
"https://your-testhide-server/api/v3/scm",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": 2, "type": "github", "host": "github.com",
"name": "Main GitHub", "project_id": 12, "repo": "acme/backend"}]
Create an SCM integration. The token is stored encrypted and used to fetch commit metadata and set build statuses on PRs.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
type string github | gitlab | bitbucket
name string Display name
project_id int Associated project
repo string Repo path (owner/name)
token string Personal access or app token with repo read + status write
Optional body
Field Type Description
host string Self-hosted SCM base URL (default: public SaaS)
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"github","name":"Main GitHub","project_id":12,"repo":"acme/backend","token":"ghp_xxxxx"}' \
https://your-testhide-server/api/v3/scm
import requests
r = requests.post(
"https://your-testhide-server/api/v3/scm",
headers={"Authorization": "Bearer TOKEN"},
json={"type": "github", "name": "Main GitHub",
"project_id": 12, "repo": "acme/backend", "token": "ghp_xxxxx"}
)
print(r.json())
Response 201
{"id": 2, "type": "github", "name": "Main GitHub",
"repo": "acme/backend", "project_id": 12}
Retrieve a single SCM integration by ID. The stored token is never returned.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int SCM integration ID
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/scm/2
import requests
r = requests.get(
"https://your-testhide-server/api/v3/scm/2",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"id": 2, "type": "github", "host": "github.com",
"name": "Main GitHub", "repo": "acme/backend", "project_id": 12}
Update an SCM integration — rotate the token or change the repo target.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path params
Param Type Description
id int SCM integration ID
Optional body
Field Type Description
token string New access token
repo string New repo path
name string New display name
curl
Python
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"token":"ghp_newtoken_yyyy"}' \
https://your-testhide-server/api/v3/scm/2
import requests
r = requests.put(
"https://your-testhide-server/api/v3/scm/2",
headers={"Authorization": "Bearer TOKEN"},
json={"token": "ghp_newtoken_yyyy"}
)
print(r.json())
Response 200
{"id": 2, "type": "github", "repo": "acme/backend", "updated": true}
Remove an SCM integration. Existing builds retain their linked commit data.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int SCM integration ID
curl
Python
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/scm/2
import requests
r = requests.delete(
"https://your-testhide-server/api/v3/scm/2",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.status_code) # 204
Response 204
— No content —
GET /api/v3/scm/{id}/branches
List branches in the connected repository. Useful for populating branch selectors in build trigger UIs.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int SCM integration ID
Optional query params
Param Type Description
q string Filter branches by name prefix
limit int Max results (default 50)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/scm/2/branches?q=release"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/scm/2/branches",
headers={"Authorization": "Bearer TOKEN"},
params={"q": "release"}
)
print(r.json())
Response 200
["release/3.14", "release/3.13", "release/3.12"]
GET /api/v3/scm/{id}/commits
List recent commits for a branch, used to link builds to specific SHAs.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int SCM integration ID
Optional query params
Param Type Description
branch string Branch name (default: default branch)
limit int Max commits (default 20)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/scm/2/commits?branch=main&limit=5"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/scm/2/commits",
headers={"Authorization": "Bearer TOKEN"},
params={"branch": "main", "limit": 5}
)
print(r.json())
Response 200
[{"sha": "a1b2c3d", "message": "Fix race condition in worker pool",
"author": "alice", "date": "2025-06-10T09:30:00Z"}]
vCenter
Integrate with VMware vCenter to provision and manage virtual machine CI agents. Testhide can clone, power-on, and revert VMs automatically for isolated build environments.
List all vCenter integrations configured on the server.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/vcenter
import requests
r = requests.get(
"https://your-testhide-server/api/v3/vcenter",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": 1, "name": "Prod vCenter", "host": "vcenter.corp.local",
"datacenter": "DC-East", "connected": true}]
Add a vCenter server integration. Credentials are stored encrypted and used for all VM lifecycle operations.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
name string Display name
host string vCenter FQDN or IP
username string vCenter service account username
password string vCenter service account password
datacenter string Target datacenter name
Optional body
Field Type Description
insecure bool Skip TLS certificate validation (not recommended)
cluster string Default compute cluster for VM placement
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Prod vCenter","host":"vcenter.corp.local","username":"svc-testhide","password":"s3cr3t","datacenter":"DC-East"}' \
https://your-testhide-server/api/v3/vcenter
import requests
r = requests.post(
"https://your-testhide-server/api/v3/vcenter",
headers={"Authorization": "Bearer TOKEN"},
json={"name": "Prod vCenter", "host": "vcenter.corp.local",
"username": "svc-testhide", "password": "s3cr3t",
"datacenter": "DC-East"}
)
print(r.json())
Response 201
{"id": 1, "name": "Prod vCenter", "host": "vcenter.corp.local",
"datacenter": "DC-East", "connected": true}
Retrieve a single vCenter integration by ID.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int vCenter integration ID
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/vcenter/1
import requests
r = requests.get(
"https://your-testhide-server/api/v3/vcenter/1",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"id": 1, "name": "Prod vCenter", "host": "vcenter.corp.local",
"datacenter": "DC-East", "cluster": "Compute-01", "connected": true}
POST /api/v3/vcenter/{id}/test
Test connectivity to the vCenter server using the stored credentials. Returns connection status and vCenter API version.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int vCenter integration ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/vcenter/1/test
import requests
r = requests.post(
"https://your-testhide-server/api/v3/vcenter/1/test",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"connected": true, "vcenter_version": "8.0.2", "latency_ms": 45}
POST /api/v3/vcenter/{id}/sync
Trigger a sync to refresh the VM inventory from vCenter. Updates power state and resource pool assignments for all known VMs.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int vCenter integration ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/vcenter/1/sync
import requests
r = requests.post(
"https://your-testhide-server/api/v3/vcenter/1/sync",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"synced_vms": 24, "updated": 3, "duration_ms": 1840}
POST /api/v3/vcenter/{id}/vm/power
Power on or off a VM agent managed by this vCenter integration. Used to bring up spare capacity or suspend idle agents.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path params
Param Type Description
id int vCenter integration ID
Required body
Field Type Description
vm_id string vCenter VM managed object ID (e.g. vm-1042)
action string power_on | power_off | reboot | suspend
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"vm_id":"vm-1042","action":"power_on"}' \
https://your-testhide-server/api/v3/vcenter/1/vm/power
import requests
r = requests.post(
"https://your-testhide-server/api/v3/vcenter/1/vm/power",
headers={"Authorization": "Bearer TOKEN"},
json={"vm_id": "vm-1042", "action": "power_on"}
)
print(r.json())
Response 200
{"vm_id": "vm-1042", "action": "power_on", "status": "powered_on"}
GitOps
Trigger pipeline synchronization from Git repository events and configure GitOps-style deployment webhooks.
Trigger a GitOps sync for a project — pulls the latest pipeline configuration from the configured repository branch and applies it. Use to force a config refresh without waiting for the next push event.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
project_id int Project to sync pipeline config for
Optional body
Field Type Description
branch string Branch to pull config from (default: main)
dry_run bool Validate config without applying changes
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project_id":12,"branch":"main","dry_run":false}' \
https://your-testhide-server/api/v3/gitops/sync
import requests
r = requests.post(
"https://your-testhide-server/api/v3/gitops/sync",
headers={"Authorization": "Bearer TOKEN"},
json={"project_id": 12, "branch": "main", "dry_run": False}
)
print(r.json())
Response 200
{"synced": true, "project_id": 12, "branch": "main",
"sha": "a1b2c3d", "jobs_updated": 4, "jobs_created": 1, "jobs_removed": 0}
POST /api/v3/gitops/webhook
Inbound webhook endpoint that receives push events from GitHub/GitLab/Bitbucket and automatically triggers a GitOps sync for the matching project. Point your SCM push webhook at this URL.
Required headers
Header Value
X-Hub-Signature-256 sha256=<hmac> (GitHub) — or platform equivalent
Required body
Field Type Description
(payload) object Standard SCM push event payload (passed through verbatim)
Optional query params
Param Type Description
project_id int Override project detection from repo URL
curl
Python
# Simulating a GitHub push event
curl -X POST \
-H "X-Hub-Signature-256: sha256=abc123..." \
-H "Content-Type: application/json" \
-d '{"ref":"refs/heads/main","repository":{"full_name":"acme/backend"}}' \
https://your-testhide-server/api/v3/gitops/webhook
import requests, hmac, hashlib, json
payload = {"ref": "refs/heads/main",
"repository": {"full_name": "acme/backend"}}
body = json.dumps(payload).encode()
sig = "sha256=" + hmac.new(b"webhook-secret", body, hashlib.sha256).hexdigest()
r = requests.post(
"https://your-testhide-server/api/v3/gitops/webhook",
headers={"X-Hub-Signature-256": sig,
"Content-Type": "application/json"},
data=body
)
print(r.json())
Response 200
{"accepted": true, "project_id": 12, "branch": "main", "sync_queued": true}
Jira
Link Testhide test failures and builds to Jira issues. Automatically create or update bug tickets when tests fail.
List all Jira integration configurations.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/jira
import requests
r = requests.get(
"https://your-testhide-server/api/v3/jira",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": 3, "name": "ACME Jira", "host": "https://acme.atlassian.net",
"project_key": "BACK", "auto_create": true}]
Create a Jira integration. Provide an API token (not your login password) from Atlassian account settings.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
name string Display name for this integration
host string Jira base URL (e.g. https://acme.atlassian.net)
email string Atlassian account email for authentication
api_token string Atlassian API token
project_key string Jira project key where issues are created (e.g. BACK)
Optional body
Field Type Description
auto_create bool Auto-create issues when new tests fail (default false)
issue_type string Jira issue type (default: Bug)
testhide_project_id int Scope to a specific Testhide project
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"ACME Jira","host":"https://acme.atlassian.net","email":"[email protected] ","api_token":"ATATT...","project_key":"BACK","auto_create":true}' \
https://your-testhide-server/api/v3/jira
import requests
r = requests.post(
"https://your-testhide-server/api/v3/jira",
headers={"Authorization": "Bearer TOKEN"},
json={"name": "ACME Jira", "host": "https://acme.atlassian.net",
"email": "[email protected] ", "api_token": "ATATT...",
"project_key": "BACK", "auto_create": True}
)
print(r.json())
Response 201
{"id": 3, "name": "ACME Jira", "project_key": "BACK",
"auto_create": true, "host": "https://acme.atlassian.net"}
Update a Jira integration — rotate token, change project key, or toggle auto-create.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Path params
Param Type Description
id int Jira integration ID
Optional body
Field Type Description
api_token string New API token
project_key string New project key
auto_create bool Toggle auto issue creation
issue_type string Jira issue type to use
curl
Python
curl -X PUT \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"auto_create":false,"project_key":"QA"}' \
https://your-testhide-server/api/v3/jira/3
import requests
r = requests.put(
"https://your-testhide-server/api/v3/jira/3",
headers={"Authorization": "Bearer TOKEN"},
json={"auto_create": False, "project_key": "QA"}
)
print(r.json())
Response 200
{"id": 3, "project_key": "QA", "auto_create": false}
Remove a Jira integration. Existing issue links on tests are retained.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Jira integration ID
curl
Python
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/jira/3
import requests
r = requests.delete(
"https://your-testhide-server/api/v3/jira/3",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.status_code) # 204
Response 204
— No content —
AI Chat & Investigation
Conversational AI interface for investigating build failures, diagnosing flaky tests, and getting plain-language explanations of CI results.
Send a message to the AI assistant. Optionally attach build or test context so the AI can answer questions about specific failures.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
message string User message / question
Optional body
Field Type Description
build_id int Build to investigate
test_id int Specific test case to investigate
session_id string Continue a previous conversation thread
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"message":"Why did this build fail?","build_id":9812}' \
https://your-testhide-server/api/v3/ai/chat
import requests
r = requests.post(
"https://your-testhide-server/api/v3/ai/chat",
headers={"Authorization": "Bearer TOKEN"},
json={"message": "Why did this build fail?", "build_id": 9812}
)
print(r.json())
Response 200
{"session_id": "sess-a8f3", "reply": "Build 9812 failed in stage 'unit-tests'. The test...",
"sources": ["build:9812", "test:47821"]}
POST /api/v3/ai/chat/stream
Same as POST /ai/chat but returns the AI reply as a Server-Sent Events stream for progressive rendering in the UI.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Accept text/event-stream
Required body
Field Type Description
message string User message
Optional body
Field Type Description
build_id int Build context
session_id string Continue a thread
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{"message":"Summarize this build","build_id":9812}' \
--no-buffer \
https://your-testhide-server/api/v3/ai/chat/stream
import requests
with requests.post(
"https://your-testhide-server/api/v3/ai/chat/stream",
headers={"Authorization": "Bearer TOKEN",
"Accept": "text/event-stream"},
json={"message": "Summarize this build", "build_id": 9812},
stream=True
) as r:
for line in r.iter_lines():
if line:
print(line.decode())
Response 200 (SSE)
data: {"token": "Build"}
data: {"token": " 9812"}
data: {"token": " failed"}
data: [DONE]
Check which LLM provider and model are configured on the server, and whether AI features are available.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ai/llm/status
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/llm/status",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"provider": "openai", "model": "gpt-4o", "available": true,
"features": ["chat", "investigation", "test_health"]}
Get the current AI token usage and quota limits for the authenticated user or organization.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ai/quota
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/quota",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"tokens_used": 142800, "tokens_limit": 1000000,
"resets_at": "2025-07-01T00:00:00Z", "percent_used": 14.3}
Run AI-powered root-cause analysis on a failed build. Returns a structured diagnosis with likely causes and suggested fixes.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
build_id int ID of the failed build to analyze
Optional body
Field Type Description
include_logs bool Include full build logs in the analysis (default true)
max_tests int Max number of failed tests to analyze (default 20)
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"build_id":9812,"include_logs":true}' \
https://your-testhide-server/api/v3/ai/diagnose
import requests
r = requests.post(
"https://your-testhide-server/api/v3/ai/diagnose",
headers={"Authorization": "Bearer TOKEN"},
json={"build_id": 9812, "include_logs": True}
)
print(r.json())
Response 200
{"build_id": 9812, "root_cause": "OOM in test worker",
"confidence": 0.87, "suggested_fix": "Increase JVM heap size or reduce parallelism",
"affected_tests": 14}
Retrieve AI-generated insights for a project — recurring failure patterns, top flaky tests, and build health trends.
Required headers
Header Value
Authorization Bearer <token>
Required query params
Param Type Description
project_id int Project to generate insights for
Optional query params
Param Type Description
days int Look-back window in days (default 7)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/ai/insights?project_id=12&days=14"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/insights",
headers={"Authorization": "Bearer TOKEN"},
params={"project_id": 12, "days": 14}
)
print(r.json())
Response 200
{"project_id": 12, "period_days": 14, "build_pass_rate": 0.82,
"top_flaky_tests": [{"test": "UserLoginTest", "flake_rate": 0.34}],
"failure_patterns": ["Database connection timeout on CI network"]}
GET /api/v3/ai/summary/{build_id}
Get a plain-language AI summary of a build — what passed, what failed, and what likely caused the failures.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
build_id int Build ID
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ai/summary/9812
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/summary/9812",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"build_id": 9812, "summary": "Build 9812 ran 1,240 tests, 14 failed. Most failures cluster around database timeout errors in the payment module. 3 tests appear flaky based on history."}
POST /api/v3/ai/job/stream
Start a long-running AI analysis job (e.g. full project audit). Returns a job ID; poll /ai/job/{job_id}/result for the result.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
type string Job type: project_audit | failure_cluster | regression_scan
project_id int Target project
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"project_audit","project_id":12}' \
https://your-testhide-server/api/v3/ai/job/stream
import requests
r = requests.post(
"https://your-testhide-server/api/v3/ai/job/stream",
headers={"Authorization": "Bearer TOKEN"},
json={"type": "project_audit", "project_id": 12}
)
print(r.json())
Response 202
{"job_id": "aijob-f2c8", "status": "queued", "estimated_seconds": 45}
GET /api/v3/ai/job/{job_id}/result
Poll the result of a long-running AI analysis job. Returns status while running, full result when complete.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
job_id string AI job ID from /ai/job/stream
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ai/job/aijob-f2c8/result
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/job/aijob-f2c8/result",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"job_id": "aijob-f2c8", "status": "complete",
"result": {"audit_score": 74, "recommendations": ["Quarantine 8 chronic flakes", "..."]}}
POST /api/v3/ai/job/{job_id}/cancel
Cancel a running AI analysis job.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
job_id string AI job ID
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/ai/job/aijob-f2c8/cancel
import requests
r = requests.post(
"https://your-testhide-server/api/v3/ai/job/aijob-f2c8/cancel",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"job_id": "aijob-f2c8", "status": "cancelled"}
Semantic search over build logs, test failure messages, and AI summaries using natural language queries.
Required headers
Header Value
Authorization Bearer <token>
Required query params
Param Type Description
q string Natural language search query
project_id int Scope search to a project
Optional query params
Param Type Description
limit int Max results (default 10)
type string Filter: build | test | log
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/ai/search?q=database+timeout&project_id=12"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/search",
headers={"Authorization": "Bearer TOKEN"},
params={"q": "database timeout", "project_id": 12}
)
print(r.json())
Response 200
{"results": [{"type": "build", "id": 9812, "score": 0.94,
"snippet": "...connection to postgres timed out after 30s..."}]}
AI Test Health
AI-powered test health analysis — detect emerging flaky tests before they become chronic, and get per-test health scores.
GET /api/v3/ai/tests/health
Get aggregated AI test health scores for a project. Returns a ranked list of tests by health risk, with flake rates and trend direction.
Required headers
Header Value
Authorization Bearer <token>
Required query params
Param Type Description
project_id int Project to analyze
Optional query params
Param Type Description
days int Look-back window (default 14)
limit int Max tests to return (default 50)
min_runs int Minimum run count to include a test (default 5)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/ai/tests/health?project_id=12&days=14"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/tests/health",
headers={"Authorization": "Bearer TOKEN"},
params={"project_id": 12, "days": 14}
)
print(r.json())
Response 200
{"tests": [{"test_id": 47821, "name": "UserLoginTest",
"health_score": 32, "flake_rate": 0.34, "trend": "worsening",
"risk": "high", "recommended_action": "quarantine"}]}
GET /api/v3/ai/tests/{id}/health
Get detailed AI health analysis for a single test — includes failure pattern breakdown, correlated builds, and actionable recommendation.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id int Test case ID
Optional query params
Param Type Description
days int Look-back window (default 30)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/ai/tests/47821/health?days=30"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/tests/47821/health",
headers={"Authorization": "Bearer TOKEN"},
params={"days": 30}
)
print(r.json())
Response 200
{"test_id": 47821, "health_score": 32, "flake_rate": 0.34,
"failure_patterns": ["Race condition on login session", "Timeout on slow CI"],
"correlated_builds": [9800, 9790, 9781],
"recommendation": "Add explicit wait or quarantine until fixed"}
GET /api/v3/ai/emerging/latest
Get the latest list of emerging flaky tests — tests that have started failing more than their historical baseline over the last N builds. Useful for catching new flakiness before it spreads.
Required headers
Header Value
Authorization Bearer <token>
Required query params
Param Type Description
project_id int Project to check
Optional query params
Param Type Description
threshold float Minimum flake-rate increase to flag (default 0.1)
window int Recent build count to compare against (default 10)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/ai/emerging/latest?project_id=12"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/emerging/latest",
headers={"Authorization": "Bearer TOKEN"},
params={"project_id": 12}
)
print(r.json())
Response 200
{"emerging": [{"test_id": 52004, "name": "PaymentFlowTest",
"baseline_rate": 0.02, "recent_rate": 0.18, "delta": 0.16,
"first_seen_build": 9808}]}
GET /api/v3/ai/emerging/history
Retrieve the historical log of emerging-flaky detections for a project. Useful for auditing when tests first became problematic.
Required headers
Header Value
Authorization Bearer <token>
Required query params
Param Type Description
project_id int Project to query
Optional query params
Param Type Description
days int History window in days (default 30)
test_id int Filter to a specific test
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/ai/emerging/history?project_id=12&days=30"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/ai/emerging/history",
headers={"Authorization": "Bearer TOKEN"},
params={"project_id": 12, "days": 30}
)
print(r.json())
Response 200
[{"detected_at": "2025-06-05T10:00:00Z", "test_id": 52004,
"name": "PaymentFlowTest", "delta": 0.16, "resolved": false},
{"detected_at": "2025-05-28T08:00:00Z", "test_id": 48120,
"name": "CacheWarmupTest", "delta": 0.22, "resolved": true}]
LLM Evaluations
Run and retrieve evaluations of the LLM models powering AI features. Use to benchmark quality, track regressions after model updates, and compare prompt strategies.
List all evaluation runs with their status, scores, and model configuration.
Required headers
Header Value
Authorization Bearer <token>
Optional query params
Param Type Description
status string pending | running | complete | failed
limit int Max results (default 20)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/evals
import requests
r = requests.get(
"https://your-testhide-server/api/v3/evals",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
[{"id": "eval-c3d9", "model": "gpt-4o", "status": "complete",
"score": 0.89, "cases_total": 100, "cases_passed": 89,
"created_at": "2025-06-10T07:00:00Z"}]
Get full details of a single evaluation run, including per-case results and failure examples.
Required headers
Header Value
Authorization Bearer <token>
Path params
Param Type Description
id string Evaluation run ID
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/evals/eval-c3d9
import requests
r = requests.get(
"https://your-testhide-server/api/v3/evals/eval-c3d9",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"id": "eval-c3d9", "model": "gpt-4o", "score": 0.89,
"cases_total": 100, "cases_passed": 89, "cases_failed": 11,
"failures": [{"case": "diagnose_oom", "expected": "OOM", "got": "timeout"}],
"duration_s": 142}
Start a new evaluation run against the configured LLM. The run is queued and executes asynchronously. Poll /evals/{id} for results.
Required headers
Header Value
Authorization Bearer <token>
Content-Type application/json
Required body
Field Type Description
suite string Eval suite to run: diagnosis | chat | health | full
Optional body
Field Type Description
model_override string Test a specific model instead of the configured one
sample_size int Number of eval cases to run (default: full suite)
curl
Python
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"suite":"diagnosis","model_override":"gpt-4o-mini","sample_size":50}' \
https://your-testhide-server/api/v3/evals/runs
import requests
r = requests.post(
"https://your-testhide-server/api/v3/evals/runs",
headers={"Authorization": "Bearer TOKEN"},
json={"suite": "diagnosis", "model_override": "gpt-4o-mini", "sample_size": 50}
)
print(r.json())
Response 202
{"id": "eval-d7a1", "status": "pending", "suite": "diagnosis",
"model": "gpt-4o-mini", "estimated_s": 90}
GET /api/v3/evals/regressions
Compare the latest eval run to the previous run and return any quality regressions — eval cases that previously passed but now fail.
Required headers
Header Value
Authorization Bearer <token>
Optional query params
Param Type Description
baseline_id string Eval ID to use as baseline (default: last complete run)
current_id string Eval ID to compare against baseline
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/evals/regressions?baseline_id=eval-c3d9¤t_id=eval-d7a1"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/evals/regressions",
headers={"Authorization": "Bearer TOKEN"},
params={"baseline_id": "eval-c3d9", "current_id": "eval-d7a1"}
)
print(r.json())
Response 200
{"baseline": "eval-c3d9", "current": "eval-d7a1",
"score_delta": -0.06, "regressions": [
{"case": "diagnose_oom", "baseline": "pass", "current": "fail"}
], "improvements": []}
Search
Full-text search across builds, tests, jobs, and nodes from a single endpoint.
Search across multiple resource types simultaneously. Returns ranked results with type, ID, and a short snippet showing the matched text.
Required headers
Header Value
Authorization Bearer <token>
Required query params
Param Type Description
q string Search query (min 2 chars)
Optional query params
Param Type Description
types string Comma-separated types to search: build,test,job,node,project (default: all)
project_id int Limit to a specific project
limit int Max results per type (default 5)
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
"https://your-testhide-server/api/v3/search?q=payment+timeout&types=build,test&project_id=12"
import requests
r = requests.get(
"https://your-testhide-server/api/v3/search",
headers={"Authorization": "Bearer TOKEN"},
params={"q": "payment timeout", "types": "build,test", "project_id": 12}
)
print(r.json())
Response 200
{"query": "payment timeout", "results": [
{"type": "test", "id": 52004, "name": "PaymentFlowTest",
"snippet": "...timed out waiting for payment gateway response...", "score": 0.97},
{"type": "build", "id": 9812,
"snippet": "...14 tests failed: payment gateway timeout...", "score": 0.91}
]}
License
Retrieve the current license status, tier, and feature entitlements for this Testhide installation.
GET /api/v3/license/status
Returns the active license tier, expiry date, seat count, and which feature capabilities are enabled. Use to check entitlements before calling tier-gated endpoints.
Required headers
Header Value
Authorization Bearer <token>
curl
Python
curl -H "Authorization: Bearer $TOKEN" \
https://your-testhide-server/api/v3/license/status
import requests
r = requests.get(
"https://your-testhide-server/api/v3/license/status",
headers={"Authorization": "Bearer TOKEN"}
)
print(r.json())
Response 200
{"tier": "enterprise", "valid": true,
"expires_at": "2026-12-31T23:59:59Z",
"seats_licensed": 100, "seats_used": 42,
"capabilities": {
"ai_chat": true,
"ai_test_health": true,
"llm_evals": true,
"white_label": true,
"vcenter": true,
"sso": true,
"max_users": 100
}}