These endpoints let a CI job trigger a suite or test run and poll it to completion. Authentication, error shapes and rate limits are covered in the REST API overview.
Headless endpoints used by the VibeView CLI and workflow template. These allocate a device, create a session, run the test or suite, and clean the session up. See CI Testing for the end-to-end flow.
Run Suite (CI)
POST /api/v1/ci/run-suite
Auth: Bearer token required (developer role or above).
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
suite_id | string | Yes | public_id of the suite |
commit_sha | string | No | Git commit SHA for GitHub status checks |
model | string | No | Model override |
provider | string | No | Provider override |
mode | string | No | hybrid, ai, or replay |
device_category | string | No | phone (default), tablet, or tv |
device_id | string | No | Pin the run to a specific device (from List Devices). Mutually exclusive with device_category. |
metadata | object | No | Arbitrary JSON object passed through unchanged to webhook payloads for this run (e.g. PR number, branch). |
build_id | int | No | Specific AppBuild id. Defaults to the suite app’s latest build. Returns 400 if no app is attached to the suite, 404 if the build does not exist, 403 if the build belongs to a different app or organization. |
Response:
{"run_id": "suite-run-public-id", "status": "pending"}
Run Test (CI)
POST /api/v1/ci/run-test
Auth: Bearer token required (developer role or above).
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
test_id | string | Yes | public_id of the test case |
commit_sha | string | No | Git commit SHA for GitHub status checks |
model | string | No | Model override |
provider | string | No | Provider override |
mode | string | No | hybrid, ai, or replay |
device_category | string | No | phone (default), tablet, or tv |
device_id | string | No | Pin the run to a specific device (from List Devices). Mutually exclusive with device_category. |
metadata | object | No | Arbitrary JSON object passed through unchanged to webhook payloads for this run (e.g. PR number, branch). |
build_id | int | No | Specific AppBuild id. Defaults to the test case app’s latest build. Returns 400 if no app is attached to the test case, 404 if the build does not exist, 403 if the build belongs to a different app or organization. |
Poll Run Status (CI)
Poll a CI-triggered run for completion. Works for both suite runs and individual test runs — pass the run_id returned by Run Suite (CI) or Run Test (CI).
GET /api/v1/ci/runs/{run_id}
Auth: Bearer token required (developer role or above).
Response: A type: "suite_run" or type: "test_run" payload with status, run_url, timing, error details, per-step/per-case results on terminal runs, live progress events while running, and a queue block while queued. See CI Testing for full payload examples.
List Suites (CI)
GET /api/v1/ci/list-suites
Auth: Bearer token required (developer role or above).
Query parameters:
| Parameter | Type | Description |
|---|---|---|
tags | string | Comma-separated tag names to filter by (e.g. ?tags=smoke,profiles) |
match | string | any (default) — suite has at least one tag; all — suite has every tag |
Response: Array of suite summaries.
[
{
"id": "suite_abc123",
"name": "Login Flow",
"platform": "ios",
"case_count": 5,
"description": "Covers email/password and SSO sign-in.",
"tags": [{"name": "smoke", "display_name": "smoke"}]
}
]
description is a string or null. tags is always an array (possibly empty); each tag has a normalized name and a display_name.
Run Multiple Suites by Tag (CI)
POST /api/v1/ci/run-suites
Auth: Bearer token required (developer role or above).
Runs every suite matching the tag filter, sequentially. Each matched suite gets its own device session and SuiteRun.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
tags | string[] | Yes | Tags to match (1–20). Each must satisfy ^[a-z0-9_-]{1,50}$. |
match | string | No | any (default) or all. |
commit_sha | string | No | Propagated to every child SuiteRun. |
model | string | No | AI model. |
provider | string | No | AI provider. |
mode | string | No | Execution mode (hybrid, ai, replay). |
device_category | string | No | phone (default), tablet, or tv. |
device_id | string | No | Pin every run to a specific device (from List Devices). Mutually exclusive with device_category. |
metadata | object | No | Arbitrary JSON object passed through unchanged to webhook payloads for these runs (e.g. PR number, branch). |
build_id | int | No | AppBuild id. Validated against every matched suite’s app upfront — 400 if any suite’s app doesn’t match. |
Response: 200 OK
{
"aggregate_id": "agg_abc123",
"matched_suite_ids": ["suite_a", "suite_b"],
"status_url": "/api/v1/ci/multi-suite-runs/agg_abc123"
}
Errors:
404— no suites matched the tag filter400—build_idis not valid for one or more matched suites (response body lists the offending suite IDs)422— invalid tag name (e.g. uppercase or special chars)
Get Multi-Suite Run Status
GET /api/v1/ci/multi-suite-runs/{public_id}
Auth: Bearer token required (developer role or above).
Returns the aggregate status and per-suite child summaries. Suitable for polling.
Response: 200 OK
{
"id": "agg_abc123",
"status": "running",
"visual_regression_status": "warn",
"suite_runs": [
{
"suite_id": "suite_a",
"suite_name": "Profiles smoke",
"run_id": "run_xyz",
"status": "passed",
"passed": 5,
"failed": 0,
"visual_regression_status": "warn",
"case_runs": [
{
"case_name": "Open profile",
"run_id": "run_pq",
"status": "passed",
"visual_regression_status": "warn",
"duration_ms": 4200,
"url": "https://vibeview.io/tests/runs/run_pq"
}
]
}
],
"started_at": "2026-04-28T12:00:00",
"completed_at": null,
"commit_sha": "abc123"
}
status is one of pending, running, passed, failed, cancelled, error. Aggregate precedence: running if any child is in-flight; else error > cancelled > failed > passed.
visual_regression_status (present at the aggregate, suite, and case levels) is one of ok, warn, fail, or null when no visual comparison ran. Suite and aggregate values roll up their children by max severity (fail > warn > ok > null). A run can be passed while carrying a warn/fail verdict — CI surfaces (e.g. the GitHub PR comment) render this as a yellow warning rather than a failure, matching the dashboard.
Errors:
404— multi-suite run not found in user’s org