Runs

Start a run

Operation ID: createRun

POST
/runs

Give exactly one of suite, test_ids or tag. A suite or tag runs at most 100 tests; test_ids holds at most 100. The response is the run (status queued) with its url; list its tests with GET /runs/{runId}, which returns at most 100 tests. Send an Idempotency-Key header to make a retry safe. Errors: 409 conflict when a suite or environment name matches more than one, or a request with the same Idempotency-Key is still running; 422 no_tests when the suite or tag has no tests; 422 invalid_base_url when base_url is not on the environment's host or an allowed domain, or is a private address; 422 unprocessable when more than 100 tests match or the organisation's monthly budget is reached; 422 idempotency_mismatch for a reused Idempotency-Key.

Needs an API key with the trigger scope.

Authorization

apiKey
headerAuthorizationBearer <oq_ followed by 43 letters and digits>

An Outqube API key, made in the app's settings. It belongs to one app and has the scope read, trigger or manage; a higher scope includes the lower ones. A revoked or expired key is a 401.

Header Parameters

idempotency-key?string

Any unique string. The request hash covers the method, the path parameters and the body: the same key with the same request returns the same run for 24 hours; the same key with another request is a 422 idempotency_mismatch.

Match^[\x21-\x7e]+$
Length8 <= length <= 200

Request Body

application/json
  1. body

Give exactly one of suite, test_ids or tag, and any of base_url, environment and metadata.

suite*string

A suite's id or its name.

Length1 <= length <= 200
base_url?string

Test this URL instead of the environment's. It must be on the environment's host or one of its allowed domains, and not a private address (422 invalid_base_url). A wildcard allowed domain over shared hosting, such as *.vercel.app, doesn't allow it: allow the exact host.

Formaturi
Lengthlength <= 2000
environment?string

An environment's name or id. A name that matches more than one is a 409 conflict.

Length1 <= length <= 200
metadata?

Where a run came from. Every field is optional; send what your CI knows.

Response Body

Created

application/json
  1. response

One start of a suite, a list of tests or a tag. GET /runs/{runId} adds its tests.

id*string

The run's id.

Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
app_id*string

The app the run belongs to.

Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
status*|

queued, running, completed or cancelled; it never goes back. More values may be added: treat an unknown one as not finished.

outcome*||

What a finished run says about the app: passed, failed (a verdict against the app) or error (anything that is not a verdict). Null while running and when cancelled. More values may be added: treat an unknown one as not passed.

counts*

Test runs by state. A retried test counts its final attempt only.

metadata*

Where the run came from.

suite_id*|

The suite the run started, or null.

environment_id*|

The environment the run used, or null.

base_url*|

The base_url override, or null for none.

rerun_of*|

The run this one reruns, or null.

url*string

The run's page in the Outqube app.

Formaturi
created_at*string

When the run was created.

Match^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
Formatdate-time
started_at*|

When the first test started, or null.

completed_at*|

When the run ended, or null.

duration_ms*|

Milliseconds from start to end, or null.

Example Request
curl -X POST 'https://app.outqube.com/api/v1/runs' \  -H 'Content-Type: application/json' \  -d '{  "suite": "Smoke",  "environment": "Staging",  "metadata": {    "source": "api",    "commit_sha": "4f1c2a9d7e3b",    "branch": "feature/login",    "pr_number": 42,    "repo": "acme/web"  }}'
Example Response
{  "id": "3f8a6c1e-5b2d-4e7a-8c19-0d4b7e2a9f61",  "app_id": "9b1d2f4e-7a3c-4c58-9e0b-6f3a1d2c4b5a",  "status": "queued",  "outcome": null,  "counts": {    "total": 2,    "queued": 2,    "running": 0,    "passed": 0,    "failed": 0,    "error": 0,    "cancelled": 0  },  "metadata": {    "source": "api",    "commit_sha": "4f1c2a9d7e3b",    "branch": "feature/login",    "pr_number": 42,    "repo": "acme/web"  },  "suite_id": "7c2a4e6b-8d1f-4a35-b97c-2e4a6c8d0f13",  "environment_id": "1a3c5e7b-9d2f-4b46-a8c0-4e6a8c0d2f57",  "base_url": "https://staging.acme.test",  "rerun_of": null,  "url": "https://app.outqube.com/acme/runs?execution=3f8a6c1e-5b2d-4e7a-8c19-0d4b7e2a9f61",  "created_at": "2026-10-30T12:00:00.000Z",  "started_at": null,  "completed_at": null,  "duration_ms": null}