Test runs
Query run status, fetch artifacts and reports, and cancel runs
Test runs are created by the remote-run endpoints on Tests
or by schedules. Every route in this group requires the
testRuns:read scope. GET routes do not require an active subscription;
cancelling a run does. See
Authentication and
Scopes.
All routes require x-project-id. The branch is resolved from x-branch-id
or the project default branch.
Run status lifecycle
pending → queued → running → completed
→ failed
→ cancelledcompleted means every test in the run passed. Any test failure produces
failed. A run stays in pending while all parallels are busy; it
advances to queued once a parallel is reserved and running once the remote
runner picks it up.
List runs
GET /v1/test-runsReturns test runs for a project, with pagination.
Query parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 20 | Results per page. Minimum 1, maximum 500. |
page | integer | 0 | Zero-based page index. |
status | string | — | Filter by status: pending, queued, running, completed, failed, or cancelled. |
name | string | — | Substring filter on run name. |
testId | UUID | — | Filter to runs for this test or directory (directories expand to all descendants). |
scheduleId | UUID | — | Filter to runs triggered by this schedule. |
branchId | UUID | — | Override the x-branch-id header for this request. |
startDate | string | — | ISO 8601 date — include only runs created on or after this date. |
endDate | string | — | ISO 8601 date — include only runs created on or before this date (inclusive). |
Response
{
"data": [
{
"id": "run-uuid",
"name": "Login flow",
"status": "completed",
"testId": "test-uuid",
"testRevisionId": "rev-uuid",
"branchId": "branch-uuid",
"testName": "Login flow",
"branchName": "main",
"scheduleType": null,
"createdAt": "2026-09-20T10:00:00.000Z",
"startedAt": "2026-09-20T10:00:05.000Z",
"completedAt": "2026-09-20T10:04:12.000Z",
"duration": 247000
}
],
"pagination": {
"page": 0,
"limit": 20,
"total": 42,
"totalPages": 3,
"hasMore": true
}
}Get latest run
GET /v1/test-runs/latestReturns the most recent run for the given filter. Useful for dashboards and status badges.
Query parameters
| Parameter | Type | Notes |
|---|---|---|
testId | UUID | Filter to runs for this test or directory. |
scheduleId | UUID | Filter to runs triggered by this schedule. |
branchId | UUID | Override the active branch. |
Response
{
"data": {
"id": "run-uuid",
"name": "Login flow",
"status": "failed",
"createdAt": "2026-09-21T09:00:00.000Z"
}
}Returns { "data": null } when no run matches the filter.
Get run statistics
GET /v1/test-runs/statsReturns aggregate pass/fail/skip counts and average duration for the given filter scope.
Query parameters
Same as Get latest run: testId, scheduleId, branchId.
Response
{
"data": {
"totalRuns": 38,
"successRate": 89,
"avgDuration": 245000,
"lastRun": "2026-09-21T09:00:00.000Z",
"passed": 34,
"failed": 3,
"skipped": 1
}
}| Field | Notes |
|---|---|
successRate | Integer 0–100. Computed as passed / (passed + failed) * 100, rounded. |
avgDuration | Average run duration in milliseconds. 0 when no completed runs exist. |
lastRun | ISO 8601 timestamp of the most recent run. null when no runs exist. |
Get a run
GET /v1/test-runs/:runIdReturns the full run record including branch and revision metadata. For
completed and failed runs, a report field is included inline with
summary data used to generate the email report.
Response
{
"data": {
"id": "run-uuid",
"name": "Login flow",
"status": "completed",
"testId": "test-uuid",
"testRevisionId": "rev-uuid",
"projectId": "proj-uuid",
"branchId": "branch-uuid",
"testName": "Login flow",
"branchName": "main",
"scheduleId": null,
"config": {
"use": { "browserName": "chromium" },
"workers": 2,
"timeout": 30000
},
"vars": null,
"parameters": null,
"metadata": {},
"stats": null,
"createdAt": "2026-09-20T10:00:00.000Z",
"startedAt": "2026-09-20T10:00:05.000Z",
"completedAt": "2026-09-20T10:04:12.000Z",
"cancelledAt": null,
"duration": 247000,
"report": null
}
}report is null while a run is in progress, when generation fails, or when
the status is cancelled. It is populated for completed and failed runs
and includes: status, testName, runName, runId, duration,
completedAt, branchId, branchName, scheduleName, and runTypeInfo
(with type, name, testResults, and stats).
Status codes
| Status | Meaning |
|---|---|
200 | Run found |
404 | Run not found in this project |
Get run tests
GET /v1/test-runs/:runId/testsReturns the list of tests that were executed (or scheduled to execute) in this run. For a single-test run this is one entry; for directory and bulk runs the full leaf-test list is returned.
Response
{
"data": [
{ "testId": "test-uuid-1", "testName": "Login flow" },
{ "testId": "test-uuid-2", "testName": "Checkout flow" }
]
}Get run artifacts
GET /v1/test-runs/:runId/artifactsReturns presigned download URLs (valid for 60 minutes) for all artifacts produced by the run. Only artifacts that already exist are returned, so the list can be empty while the run is still in progress.
Response
{
"data": [
{
"key": "bundle.tgz",
"label": "Test Bundle - Code and Dependencies",
"type": "archive",
"url": "https://..."
},
{
"key": "playwright-report.tar.gz",
"label": "Playwright Report Archive",
"type": "archive",
"url": "https://..."
},
{
"key": "test-results.json",
"label": "Test Results JSON Report",
"type": "json",
"url": "https://..."
},
{
"key": "test-run.log",
"label": "Test Run Log",
"type": "log",
"url": "https://..."
},
{
"key": "tests/Login flow/trace.zip",
"label": "Login flow - Trace",
"type": "trace",
"testName": "Login flow",
"url": "https://..."
}
]
}Only artifacts that exist in storage are included. If a file was not produced
(e.g. trace is off in the config), its entry is absent from the array.
Per-test artifacts (traces, images, videos) appear alongside the run-level
files and include a testName field.
Get run report
GET /v1/test-runs/:runId/reportReturns an HTML email report for a completed or failed run. The response
Content-Type is text/html.
Returns 400 unless the run's status is completed or failed. Runs in
pending, queued, running, or cancelled status return 400.
Cancel a run
POST /v1/test-runs/:runId/cancelRequires testRuns:read and tests:cancel. Cancels a run that is in pending,
queued, or running state. Returns 400 if the run is already in a
terminal state.
Response
{
"data": {
"success": true,
"message": "Cancelled 1 task(s)"
}
}Status codes
| Status | Meaning |
|---|---|
200 | Cancellation succeeded (or was partially successful — check the message) |
400 | Run is already completed, failed, or cancelled |
403 | Missing tests:cancel scope, or no active subscription ({ "message": "LICENSE_REQUIRED" }) |
404 | Run not found in this project |