> ## 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 pull request testing

> Start a pull request review from any CI that can send an HTTP request.

Use the API when the pipeline is not GitHub Actions, GitLab CI, or Bitrise. Bitbucket, Azure DevOps, CircleCI, Jenkins, and any other system that can send an HTTPS request can start the same review.

## Set it up

<CardGroup cols={2}>
  <Card title="Start a change review" icon="code" href="/api-reference/chat/start-change-review-chat">
    `POST /v1/chat/change-review` with `mode: "pr"` and the request URL.
  </Card>

  <Card title="Upload a mobile build" icon="mobile" href="#upload-the-pr-build">
    Upload the binary, then pass `applicationBuildShortId`.
  </Card>

  <Card title="Get the results" icon="chart-line" href="#get-the-results">
    Poll the conversation and open runs in the dashboard.
  </Card>

  <Card title="Slack, Teams, and email" icon="bell" href="#slack-teams-and-email">
    Project defaults and per-run notification overrides.
  </Card>
</CardGroup>

Create the API key and find the IDs on [API regression testing](/regression-testing/api#set-it-up). To read the PR/MR diff and post a review comment, connect the [GitHub App](/configuration/github-app) or [GitLab MR reviews](/pr-testing/gitlab#set-up-gitlab-mr-reviews) first. A test plan run does not need either. See the [regression API](/regression-testing/api).

## What works over the API

| Capability | API |
| :- | :- |
| Review on a preview URL, before merge | Yes. Send the request URL and the preview URL in the body. |
| Review after merge, with no preview URL | Yes. Send the merged request URL after the deploy, and target the deployed environment. |
| Review a mobile build for that pull request | Yes. Upload the build, then pass `applicationBuildShortId`. See [Upload the PR build](#upload-the-pr-build). |
| Run a regression test plan | Not this endpoint. Use the [regression API](/regression-testing/api). |
| Block the pipeline until the review finishes | No built-in check. The request starts the review. GitHub's Change Review Action is the one that waits for you. |

## What this does not do

* It does not replace the GitHub App or the GitLab connection. Those are what allow the review to be posted.
* It does not schedule runs. Schedules belong on a [test plan](/core-concepts/test-plans).
* Envoyer is not a substitute. Envoyer cannot start a change review.

## Pass extra context

When you call `POST /v1/chat/change-review`, include a `context` string with testing guidance the PR body may not have: acceptance criteria from a ticket, a short summary of what to exercise, or out-of-scope notes.

GitHub's [Change Review Action](/pr-testing/github#change-review-action) accepts the same text as its `context` input. You can generate that string in an earlier CI step (for example with a coding agent) and pass it through. The agent sees both the PR description and this `context`.

See [Writing PR Descriptions](/best-practices/pr-testing) for what to put in the description versus `context`.

## Upload the PR build

Native mobile PRs have no preview URL. Upload the simulator or emulator binary after your compile step, then pin the change review with `applicationBuildShortId`. Replace `app_gXeBl2` and the file path.

```bash theme={null}
APP_ID="app_gXeBl2"
BUILD_FILE="app/build/outputs/apk/debug/app-debug.apk"
FILE_NAME=$(basename "$BUILD_FILE")

UPLOAD_RESPONSE=$(curl -sSf -X POST "https://api.qa.tech/v1/applications/$APP_ID/builds/upload-url" \
  -H "Authorization: Bearer $QATECH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"fileName\": \"$FILE_NAME\"}")
UPLOAD_URL=$(echo "$UPLOAD_RESPONSE" | jq -r '.uploadUrl')
BUILD_TOKEN=$(echo "$UPLOAD_RESPONSE" | jq -r '.buildToken')

curl -sSf -X PUT "$UPLOAD_URL" \
  --upload-file "$BUILD_FILE" \
  -H "Content-Type: application/octet-stream"

BUILD_RESPONSE=$(curl -sSf -X POST "https://api.qa.tech/v1/applications/$APP_ID/builds" \
  -H "Authorization: Bearer $QATECH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"platform\": \"android\", \"buildToken\": \"$BUILD_TOKEN\"}")
BUILD_SHORT_ID=$(echo "$BUILD_RESPONSE" | jq -r '.applicationBuildShortId')
echo "Uploaded $BUILD_SHORT_ID"
```

For iOS, zip the `.app` first, set `"platform": "ios"`, and upload the archive:

```bash theme={null}
zip -r AppName.zip AppName.app
BUILD_FILE="$PWD/AppName.zip"
```

The presigned URL expires in about two hours. Maximum file size is 4 GB.

Then call `POST /v1/chat/change-review` with `applicationBuildShortId` on the application override. See [Mobile pull request testing](/pr-testing/agents/mobile) for when to use a test plan versus a change review, and [Application Builds API](/api-reference/application-builds) for request details.

Bitrise-specific paths (`$BITRISE_APK_PATH`, `xcode-build-for-simulator`) are on [Bitrise pull request testing](/pr-testing/bitrise#upload-the-build).

## Get the results

`POST /v1/chat/change-review` returns `202 Accepted` immediately. The review runs asynchronously.

1. Take `shortId` (or the conversation id) from the response.
2. Poll [Get Chat Conversation](/api-reference/chat/get-chat-conversation) until conversation `status` is `completed`, `failed`, or `cancelled`. Wait at least 1 second between polls; assistant message `COMPLETED` alone is not enough while a test run is still in progress.
3. Open the conversation URL in the dashboard for the review write-up.
4. Use any `runs[]` entries with [Get Run](/api-reference/runs/get-run) (`testCases: "all"`) for browser or mobile results.

See [Chat API](/api-reference/chat) for how conversations and runs relate.

## Slack, Teams, and email

Connect project notifications so your team sees run outcomes without watching the API:

* **[Slack](/integrations/slack)** — default channel under Settings → Integrations
* **[Microsoft Teams](/integrations/microsoft-teams)** — project webhook
* **Email** — recipients on the test plan or per-run override

When a change review starts test runs, those runs use the same notification rules as other runs. Configure defaults and overrides in [Notifications](/core-concepts/notifications). For CI-started test plan runs, you can also pass `notifyOn` / channel overrides on [Start Run](/api-reference/runs/start-test-run).
