> ## 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.

# Bitrise

> Trigger QA.tech test runs from Bitrise CI/CD: upload your Android or iOS build and run mobile test plans automatically

Bitrise is a mobile-focused CI/CD platform. The most common QA.tech integration is to upload the app produced by your build step and trigger a test plan against that exact build. Web applications work too, using a plain HTTP trigger.

## Prerequisites

You need three values before configuring your workflow:

* **API Token** - Your QA.tech API token (from **Settings → Organization → API Keys**)
* **Application Short ID** - Your mobile application's short ID (from **Settings → Applications & Envs**, e.g. `app_gXeBl2`)
* **Test Plan Short ID** - From your test plan (e.g. `pln_abc123`)

<Tip>
  New to mobile app testing on QA.tech? Start with [Mobile App
  Testing](/test-features/mobile-app-testing) to create your mobile application
  first.
</Tip>

### Configure a Bitrise Secret

Store your API token securely:

1. Open your app in Bitrise and go to **Workflow Editor → Secrets**
2. Add a secret:
   * **Key**: `QATECH_API_TOKEN`
   * **Value**: Your API token
   * Keep **Expose for Pull Requests** disabled unless you need it

## Test your mobile builds

Add a `script` step **after** your build step (e.g. `android-build` or `xcode-build-for-simulator`). It uploads the build to QA.tech and starts a test run against it, in four parts:

1. Get a presigned upload URL
2. Upload the build file directly to storage
3. Create the build record
4. Start a test run pinned to that build

### Android (APK)

Bitrise's `android-build` step exposes the built APK as `$BITRISE_APK_PATH`:

```yaml theme={null}
- script@1:
    title: Run QA.tech tests on this build
    inputs:
      - content: |
          #!/usr/bin/env bash
          set -euo pipefail

          APP_ID="app_gXeBl2"               # Your QA.tech application short ID
          TEST_PLAN_ID="pln_abc123"         # Your test plan short ID
          BUILD_FILE="$BITRISE_APK_PATH"    # Set by the android-build step
          FILE_NAME=$(basename "$BUILD_FILE")

          # 1. Get a presigned upload URL
          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')

          # 2. Upload the file directly to storage
          curl -sSf -X PUT "$UPLOAD_URL" \
            --upload-file "$BUILD_FILE" \
            -H "Content-Type: application/octet-stream"

          # 3. Create the build record
          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 "Build created: $BUILD_SHORT_ID"

          # 4. Start a test run against this build
          RUN_RESPONSE=$(curl -sSf -X POST "https://api.qa.tech/v1/run" \
            -H "Authorization: Bearer $QATECH_API_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{
              \"testPlanShortId\": \"$TEST_PLAN_ID\",
              \"applications\": [{
                \"applicationShortId\": \"$APP_ID\",
                \"environment\": {
                  \"applicationBuildShortId\": \"$BUILD_SHORT_ID\"
                }
              }]
            }")
          echo "Test run started: $(echo "$RUN_RESPONSE" | jq -r '.run.url')"
```

Replace `app_gXeBl2` and `pln_abc123` with your values.

### iOS (Simulator build)

QA.tech runs iOS tests on simulators, so the upload must be a **simulator build** (`.app` compressed as `.zip` or `.tar.gz`) - device and App Store `.ipa` builds cannot run on simulators. See [Mobile App Testing](/test-features/mobile-app-testing) for how to prepare a simulator build.

On Bitrise, use the `xcode-build-for-simulator` step instead of `xcode-archive`. It exposes the built `.app` directory as `$BITRISE_APP_DIR_PATH`. Zip it before the upload in the script above:

```bash theme={null}
cd "$(dirname "$BITRISE_APP_DIR_PATH")"
zip -r app-simulator.zip "$(basename "$BITRISE_APP_DIR_PATH")"
BUILD_FILE="$PWD/app-simulator.zip"
```

and use `"platform": "ios"` when creating the build record.

<Note>
  Supported file types are `.apk` and `.aab` for Android, and `.zip` or
  `.tar.gz` containing your `.app` simulator build for iOS. Maximum file size is
  4GB. See the [Application Builds API](/api-reference/application-builds) for
  full request and response details.
</Note>

## Web applications

If you use Bitrise for a web app, trigger a test plan with a single request:

```yaml theme={null}
- script@1:
    title: Trigger QA.tech tests
    inputs:
      - content: |
          #!/usr/bin/env bash
          set -euo pipefail
          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"}'
```

See the [Start Run API](/api-reference/start-run) for all available options, including environment URL overrides for staging or preview deployments.

## Blocking mode

To fail the Bitrise build when tests fail (for example as a release gate), poll the run status after starting it:

```bash theme={null}
# Start run and capture shortId
RUN_RESPONSE=$(curl -sSf -X POST "https://api.qa.tech/v1/run" \
  -H "Authorization: Bearer $QATECH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"testPlanShortId\": \"$TEST_PLAN_ID\",
    \"applications\": [{
      \"applicationShortId\": \"$APP_ID\",
      \"environment\": { \"applicationBuildShortId\": \"$BUILD_SHORT_ID\" }
    }]
  }")
SHORT_ID=$(echo "$RUN_RESPONSE" | jq -r '.run.shortId')

# Poll until completion
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 the [Run Status API](/api-reference/run-status) for polling details and error handling. If the polling step might exceed your step timeout, raise the step's timeout in the Bitrise Workflow Editor.

## Related Documentation

* **[CI/CD Integration](/configuration/ci-cd-integration)** - Overview of integration modes
* **[Application Builds API](/api-reference/application-builds)** - Full build upload reference
* **[Start Run API](/api-reference/start-run)** - Complete API documentation
* **[Mobile App Testing](/test-features/mobile-app-testing)** - Mobile testing concepts and setup
* **[Test Plans](/core-concepts/test-plans)** - Create and organize test plans
