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

# API regression testing

> Run a test plan from any system that can send an HTTP request, including a CI QA.tech has no plugin for.

Start from a [test plan](/core-concepts/test-plans). Use the API when you do not run GitHub Actions, GitLab CI, Bitrise, or Envoyer. Bitbucket, Azure DevOps, CircleCI, Jenkins, and a script on a server all work.

## Set it up

<CardGroup cols={2}>
  <Card title="Start Run API" icon="code" href="/api-reference/runs/start-test-run">
    `POST /v1/run` with `testPlanShortId`, plus URL or device overrides.
  </Card>

  <Card title="Wait for the result" icon="hourglass-half" href="#blocking">
    Poll the run and fail the job when the result is not passed.
  </Card>

  <Card title="CLI" icon="terminal" href="/cli/commands/run">
    `qatech run` calls the same API. `qatech status` waits for the result.
  </Card>
</CardGroup>

<Steps>
  <Step title="Create an API key">
    Go to **Organization Settings → API Keys**. Create a key and copy it when it is shown. It is not displayed again. Store it as a masked secret in your CI, for example `QATECH_API_TOKEN`.

    A project-scoped key is bound to one project, so requests can omit `projectShortId`. An organization-scoped key needs `projectShortId` on project-scoped endpoints. See [Authentication](/api-reference/introduction#authentication).
  </Step>

  <Step title="Send an authenticated request">
    Every request goes to `https://api.qa.tech/v1` with the key as a Bearer token:

    ```bash theme={null}
    curl https://api.qa.tech/v1/applications \
      -H "Authorization: Bearer $QATECH_API_TOKEN"
    ```

    A list of your applications means the key works. A `401` means the key is missing, mistyped, or revoked.
  </Step>

  <Step title="Get the project short ID">
    Copy `proj_…` from the project URL or Settings (for example `proj_abc123`).
    Org-scoped keys need this on `POST /v1/run`. See [Understanding Different
    IDs](/api-reference/introduction#understanding-different-ids).
  </Step>

  <Step title="Get the test plan short ID">
    Open the plan under [Test Plans](https://app.qa.tech/current-project/test-plans) and copy `pln_…` from the URL (for example `pln_abc123`). See [Find the test plan short ID](/core-concepts/test-plans#find-the-test-plan-short-id).
  </Step>
</Steps>

### Find the IDs you need

| ID | Example | Used for | Where to find it |
| :- | :- | :- | :- |
| Project short ID | `proj_abc123` | Organization-scoped keys | Project URL or Settings |
| Test plan short ID | `pln_abc123` | Running a test plan | [Find the test plan short ID](/core-concepts/test-plans#find-the-test-plan-short-id) |
| Application short ID | `app_gXeBl2` | Pointing a run or a review at a preview URL or build | [Finding Short IDs](/core-concepts/applications-and-environments#finding-short-ids-for-api-usage) |
| Environment short ID | `env_aB3xY9` | Targeting an existing environment instead of a URL | [Finding Short IDs](/core-concepts/applications-and-environments#finding-short-ids-for-api-usage) |

The full list of ID types is in [Understanding Different IDs](/api-reference/introduction#understanding-different-ids).

## What works over the API

| Capability | API |
| :- | :- |
| Review on a preview URL, before merge | Not this endpoint. A test plan run does not post a review. See the [pull request API](/pr-testing/api). |
| Review after merge, with no preview URL | Not this endpoint. |
| Run a regression test plan from CI | Yes. `POST /v1/run` with `testPlanShortId`. You can override the URL or device for that run. |
| Run that plan against a mobile build | Yes. Upload the build, then pass `applicationBuildShortId`. See [Application builds](/api-reference/application-builds). |
| Block the pipeline until the plan finishes | Yes. Poll [Get run](/api-reference/runs/get-run) and fail the job when the result is not passed. |
| Schedule | On the test plan, with **Manage Schedules**. See [Manual and scheduled runs](/best-practices/running-tests#trigger-a-run-on-a-schedule). |

## Patterns

### Start a test plan

```bash theme={null}
curl -X POST https://api.qa.tech/v1/run \
  -H "Authorization: Bearer $QATECH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "testPlanShortId": "pln_abc123"
  }'
```

### Mobile build

Upload the APK or simulator `.app`, then pass `applicationBuildShortId` instead of a URL. How application builds work is on [Mobile regression testing](/regression-testing/agents/mobile). The shared upload script is on [API pull request testing](/pr-testing/api#upload-the-pr-build).

```bash theme={null}
curl -X POST https://api.qa.tech/v1/run \
  -H "Authorization: Bearer $QATECH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "testPlanShortId": "pln_abc123",
    "applications": [{
      "applicationShortId": "app_gXeBl2",
      "environment": {
        "applicationBuildShortId": "bld_abc123"
      }
    }]
  }'
```

### Blocking

Poll the run and fail the job when the result is not passed:

```bash theme={null}
RESPONSE=$(curl -sSf -X POST "https://api.qa.tech/v1/run" \
  -H "Authorization: Bearer $QATECH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"testPlanShortId": "pln_abc123"}')
SHORT_ID=$(echo "$RESPONSE" | jq -r '.run.shortId')

while true; do
  STATUS_RESPONSE=$(curl -sSf "https://api.qa.tech/v1/run/$SHORT_ID" \
    -H "Authorization: Bearer $QATECH_API_TOKEN")
  STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.status')
  if [[ "$STATUS" == "COMPLETED" || "$STATUS" == "ERROR" || "$STATUS" == "CANCELLED" ]]; then
    RESULT=$(echo "$STATUS_RESPONSE" | jq -r '.result')
    [[ "$RESULT" == "PASSED" ]] && exit 0 || exit 1
  fi
  sleep 30
done
```

See [Get run](/api-reference/runs/get-run) for polling details.

## What you can override on a run

* **Preview or staging URL**: set `applications[].environment.url`. See [Preview Environments](/core-concepts/applications-and-environments#preview-environments).
* **Environment custom headers**: attach auth or protection-bypass headers with `customHeaders`. See [Environment custom headers](/core-concepts/applications-and-environments#custom-headers).
* **Device preset**: pass `devicePresetShortId` to test mobile, tablet, or desktop without another test plan. See [Start Run API](/api-reference/runs/start-test-run).
* **Slack channel**: send results for one run to a different channel. See [Per-run overrides](/core-concepts/notifications#per-run-overrides).
* **Post-run automation**: poll [Get run](/api-reference/runs/get-run) to update a status page, call a webhook, or send an alert when the run finishes.

## What this does not do

* It does not post a pull request review. Use [API pull request testing](/pr-testing/api) for that.
* It does not require GitHub, GitLab, Bitrise, or Envoyer. Those guides are convenience wrappers around this call.
* It does not schedule itself. **Manage Schedules** on the test plan runs it with no CI at all. See [Manual and scheduled runs](/best-practices/running-tests).


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