> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vikingqa.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Run tests from a pipeline

> Start a batch from any CI system with one call, then wait for the outcome and block a release on it.

Your pipeline makes one HTTP call and vikingQA runs your suite. A later step
can wait for the result and fail the build when a test fails. It works from
any CI system, and your repository needs nothing installed.

The API has two endpoints:

| Method | Path | What it does |
| - | - | - |
| `POST` | `/api/v1/batches` | Start a batch: one run of your suite, or of the tests you tag |
| `GET` | `/api/v1/batches/{key}` | Read a batch, to see whether it has finished and how it went |

Both are served from `https://app.vikingqa.io` and return the same JSON shape.

## Authenticate

Every request carries a project API token:

```http theme={null}
Authorization: Bearer vqa_…
```

An organisation admin creates tokens in **Project settings → API tokens**. A
token is shown once, when you create it, so copy it straight into your CI
system's secret store. The examples below read it from `VIKINGQA_TOKEN`.

* A token belongs to one project. It can start batches in that project and
  read that project's batches, and nothing else.
* A project can have as many tokens as you like. Create one per pipeline, so
  that if one leaks you revoke it without touching the others.
* **Revoke** takes effect at once. A revoked token gets `401`, exactly like a
  token that never existed.
* The API tokens page shows when each token was last used, so you can check
  nothing still depends on one before you revoke it.

## Start a batch

```http theme={null}
POST /api/v1/batches
Content-Type: application/json
```

The body has exactly these fields. Any other field is refused with `400`.

| Field | Required | What it is |
| - | - | - |
| `environment` | Yes | The environment's name, as it appears in vikingQA. Upper and lower case are treated the same, so `Staging` and `staging` match. |
| `appVersion` | Yes | Your own version string for the application under test: a release tag, a build number, a commit SHA. vikingQA records it on the batch and shows it back to you. |
| `name` | No | A label for the batch, such as `Deploy #812`. |
| `tags` | No | Run only the tests that carry one of these Playwright tags. Leave it out to run every test on the branch. |

There is no default environment. A request without `environment`, or naming
one the project doesn't have, is refused rather than run somewhere else.

Each of `environment`, `appVersion`, `name` and every tag is text of **200
characters or fewer**, and none of them may be empty or only spaces. `tags` may
name at most **20 tags** — a pipeline selects a handful, and a longer list is a
runaway loop in a script rather than a selection. Anything over a limit is
refused with `400`, and the message names the field.

```bash theme={null}
curl -sS -X POST https://app.vikingqa.io/api/v1/batches \
  -H "Authorization: Bearer $VIKINGQA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"environment": "staging", "appVersion": "1.4.2"}'
```

The call returns `202 Accepted` straight away, with the new batch:

```json theme={null}
{
  "key": "SHOP-B-42",
  "name": null,
  "status": "PENDING",
  "finished": false,
  "environment": "staging",
  "tags": [],
  "appVersion": "1.4.2",
  "commitSha": null,
  "url": "https://app.vikingqa.io/org/…/projects/SHOP/env/staging/test-results/SHOP-B-42",
  "error": null,
  "createdAt": "2026-09-22T10:00:00.000Z",
  "finishedAt": null
}
```

### Run only some of the tests

Give `tags` to run a part of your suite — a smoke set on every deploy, and the
whole suite once a night:

```bash theme={null}
curl -sS -X POST https://app.vikingqa.io/api/v1/batches \
  -H "Authorization: Bearer $VIKINGQA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"environment": "staging", "appVersion": "1.4.2", "tags": ["@smoke"]}'
```

* A test runs when it carries **at least one** of the tags you name.
* Write a tag as it is in your code, `@smoke`, or without the `@`, `smoke`.
  Both select the same tests. vikingQA shows tags without the `@`, which is how
  Playwright reports them.
* Upper and lower case are **not** the same here: `@Smoke` and `@smoke` are two
  different tags, in your code and in this field.
* Leave `tags` out, or send `[]`, to run every test on the branch.
* You cannot select tests by folder or by name. Tags are the one way.

If no test carries the tags you name, the batch **fails** with
`empty_selection` instead of passing with nothing tested. vikingQA can only
know that after it has read your branch, so it appears on the batch and not as
an error on this call.

`PENDING` means the batch exists and nothing has run yet. Behind the response,
vikingQA first reads the environment's branch **as it is now**, then runs the
suite at that commit. A pipeline usually fires right after a push, so this is
what makes the batch test the code you just pushed, not an older copy. The
commit that ran appears as `commitSha` once it has been read.

Two calls a second apart start two batches, and both run. There is no rate
limit and no limit on how many batches run at once. The one wait is the read
of the branch: vikingQA reads one branch one step at a time, so a batch started
while that branch is already being read waits for that read to finish, usually
a few seconds and at most a few minutes, before it starts.

## Read a batch

```bash theme={null}
curl -sS https://app.vikingqa.io/api/v1/batches/SHOP-B-42 \
  -H "Authorization: Bearer $VIKINGQA_TOKEN"
```

It returns `200` and the same shape as above. `key` is the batch key vikingQA
shows in the interface, and `url` opens that batch's page.

## The batch

| Field | Type | What it is |
| - | - | - |
| `key` | string | The batch's key, such as `SHOP-B-42`. |
| `name` | string or null | The name you gave it. |
| `status` | string | Where the batch is. See below. |
| `finished` | boolean | `true` once the batch will not change again. |
| `environment` | string | The environment it ran in. |
| `tags` | array | The tags it selected its tests by, without the `@`. Empty for the whole suite. |
| `appVersion` | string or null | The version you sent. `null` for batches started from the interface or a schedule. |
| `commitSha` | string or null | The commit of your test repository that ran. `null` until the branch has been read. |
| `url` | string | The batch's page in vikingQA. |
| `error` | object or null | Why the batch failed as a whole, when it did: `{ "code", "message" }`. |
| `createdAt` | string | When it was accepted (ISO 8601). |
| `finishedAt` | string or null | When it finished. |

**Wait on `finished`, not on a list of statuses.** vikingQA may add status
values later. `finished` will stay correct when it does, and a script that
lists the final statuses itself would not.

Once `finished` is `true`, read `status`:

| Status | Meaning |
| - | - |
| `PASSED` | Every test passed. |
| `FAILED` | At least one test failed, or the branch holds no automated tests. |
| `ERRORED` | The batch could not run properly. `error`, or the batch's page, says why. |
| `STOPPED` | Someone stopped it in vikingQA. |
| `SKIPPED` | Every test was skipped, so nothing was checked. |

While it is not finished, `status` is `PENDING` or `RUNNING`.

When `error` is set, its `code` says what went wrong:

| Code | Meaning |
| - | - |
| `sync_failed` | vikingQA could not read the environment's branch, so nothing ran. The message says why. The project's repository settings show the same problem. |
| `environment_changed` | The environment was deleted or moved to another branch before the batch started. |
| `empty_suite` | The branch holds no automated tests. The batch fails rather than passing with nothing checked. |
| `empty_selection` | No test on the branch carries the tags you asked for. Check the tags, or whether they were renamed in your repository. |
| `repository_unbound` | The project has no test repository connected, so there is no suite to run. Connect one in the project's repository settings. |
| `repository_access_lost`, `repository_access_denied` | vikingQA can no longer read your test repository: the GitHub App was uninstalled, the repository was taken out of it, or a permission was withdrawn. Reconnect it in the project's repository settings. |
| `no_pinned_commit` | The environment's branch has never been read, so there is no commit to run. Open the project's repository settings and read the branch once. |
| `manifest_unreadable` | There is no `package.json` at the commit that was about to run, so vikingQA cannot tell which Playwright to install. |
| `toolchain_unresolvable` | Your `package.json` and lockfile do not name a Playwright version vikingQA can run. The message says which version it read. |
| `selection_unresolvable` | The commit that was about to run does not hold every test the batch selected — the message names them. Nothing ran. Read the branch again, then start a new batch. |
| `start_failed`, `dispatch_failed` | vikingQA could not start the run. Start a new batch. |
| `batch_watchdog_timeout` | The batch ran for longer than a batch is allowed and was stopped. Tests that had not finished are reported as not run. |

**Treat a `code` you don't recognise as a failure to look at, not as a
success.** vikingQA adds codes as it learns to report new failures, so match on
the ones your pipeline handles specially and send everything else to the
batch's `url`, which always says more than this field can.

## Errors

A refused request returns a code you can check and a message for your log:

```json theme={null}
{
  "error": {
    "code": "environment_not_found",
    "message": "This project has no environment named \"stagign\"."
  }
}
```

| Status | Code | When |
| - | - | - |
| `400` | `invalid_request` | The body is not JSON; a field is missing, empty, longer than 200 characters, or of the wrong type; `tags` names more than 20 tags; or there is a field the API doesn't take. |
| `401` | `unauthorized` | No token, an unknown token, or a revoked one. |
| `404` | `environment_not_found` | The project has no environment with that name. |
| `404` | `batch_not_found` | The project has no batch with that key. |
| `409` | `environment_not_runnable` | The project can't run anything right now: it has no repository connected, or vikingQA has lost access to it. Reconnect it in the project's repository settings. |
| `413` | `request_too_large` | The body is far larger than any valid request. |
| `500` | `internal_error` | Something failed on our side. Try again. |

`409` is never about other batches that are running.

## Use it from a pipeline

[Run your tests from GitHub Actions](/ci/github-actions) is the whole setup —
the token, the secret, and a workflow file to copy, with variations for gating
a deploy, running a tagged subset, and commenting on a pull request.

The same two calls work from any CI system that has a shell, such as AWS
CodeBuild or GitLab CI.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.