Skip to main content

Start Run API

The Start Run API allows you to programmatically trigger test runs for your projects. This endpoint is particularly useful for integrating QA.tech testing into your CI/CD pipelines and custom automation workflows. The Start Run API provides a single endpoint to create new test runs:
  • Endpoint: POST /projects/{projectUuid}/runs
  • Authentication: Bearer token (JWT) or Netlify webhook signature
  • Content-Type: application/json

Authentication

The Start Run API supports two authentication methods:

Bearer Token Authentication

Include your project’s API token in the Authorization header:
Authorization: Bearer YOUR_API_TOKEN
You can obtain your project’s API token through the QA.tech dashboard in the project settings under “API & Integrations”.

Netlify Webhook Authentication

For Netlify webhook integrations, you can use webhook signature authentication instead of a Bearer token. Include the signed JWT token in the X-Webhook-Signature header:
X-Webhook-Signature: YOUR_SIGNED_JWT_TOKEN
The token is verified using your project’s API token as the secret. Either authentication method is valid - use Bearer token for general API access or Netlify signature for webhook integrations.

Finding Your Project UUID

Your project UUID is required in the URL path. Find it in your dashboard: Settings → Integrations → API - Look at the code examples, your UUID is embedded in the URL between /projects/ and /runs (36-character UUID format) Or if using GitHub Actions: Settings → Integrations → GitHub Actions - Copy from the QATECH_PROJECT_ID field For detailed instructions, see Finding Your Project UUID.

Request Parameters

Path Parameters

ParameterTypeRequiredDescription
projectUuidstring (UUID)YesYour project’s UUID (36-character format, NOT the short ID from URLs)

Headers

HeaderValueRequiredDescription
Content-Typeapplication/jsonYesMedia type of the request body
AuthorizationBearer YOUR_API_TOKENYes*Bearer token authentication (required if not using Netlify webhook signature)
X-Webhook-SignatureYOUR_SIGNED_JWT_TOKENYes*Netlify webhook signature authentication (required if not using Bearer token)
* Either Authorization Bearer token OR X-Webhook-Signature header is required for authentication.

Request Body

The request body is optional and can contain the following fields:
{
  "integrationName": "CircleCI",
  "testPlanShortId": "abc123"
}

Optional Fields

  • integrationName (string): Human-readable name of what triggered this test (defaults to “API”)
  • testPlanShortId (string): The short ID of the test plan to execute (this is the 6-character ID visible in test plan URLs)
  • applications (object): Optional application environment overrides for testing specific environments. Each application can specify either a new environment (with url and name) or reference an existing environment (with short_id).
Device Preset Limitation: Environment overrides are supported via API, but device preset overrides are not. To test with different device configurations, create separate test plans with different device preset settings in the UI.
  • notifications (array): Slack notification overrides for this run. Provide one or more channel objects to send run updates to specific channels instead of the project’s default Slack channel. Details below.

Slack Notification Overrides

Use the notifications array to send per-run Slack updates without changing your default integration settings. Each object must describe a Slack destination:
FieldTypeRequiredDescription
typestringYesMust be slack (currently the only supported notification type)
channelstringYesSlack channel ID (e.g., C0478ABCDEF). The QA.tech bot must already have access to this channel.
notifyOnstringNoControls when notifications are sent for this channel. See options below.
notifyOn options:
  • always (default): Sends both a “run started” message when the run begins and the final result summary when it completes
  • failure: Only sends the final summary when the run result is not PASSED (i.e., when result is FAILED, SKIPPED, or null)
The run result values (PASSED, FAILED, SKIPPED, or null) are determined when the run completes.
Slack notification overrides currently do not work for projects with SSH Tunnel Proxy enabled.
1

Connect Slack to the project

Go to Project Settings → Integrations → Slack, connect your workspace, and invite the QA.tech bot to every channel you plan to target.
2

Send per-run overrides

Include a notifications array in the Start Run API request body:
{
  "notifications": [
    { "type": "slack", "channel": "C0478ABCDEF", "notifyOn": "always" },
    { "type": "slack", "channel": "C0123FAIL42", "notifyOn": "failure" }
  ]
}
Behavior
  • Start notifications: When at least one override uses notifyOn: "always" (or omits notifyOn, which defaults to always), QA.tech emits the slack/run-created event and posts Run #<shortId> started to all channels in the override list as soon as the API call succeeds. If all channels have notifyOn: "failure", no start notification event is triggered.
  • Finish notifications: Each channel is evaluated independently based on its own notifyOn value:
    • Channels with notifyOn: "always" (or default) receive finish notifications regardless of run result.
    • Channels with notifyOn: "failure" only receive finish notifications when the run result is not PASSED (i.e., when result is FAILED, SKIPPED, or null).
  • Default channel override: As soon as overrides are provided, QA.tech skips the default Slack channel configured in the integration and only uses the channels listed in the request.
Validation & Errors
  • The notifications array must contain at least one object. Empty arrays are rejected with 400 Bad Request and a schema validation error message.
  • The API rejects overrides (400 Bad Request) if Slack is not connected for the project. Error message: "Slack integration is not configured for this project. Configure Slack before overriding notification channels."
  • QA.tech fetches your accessible channel IDs and returns 400 Bad Request when a requested channel is not found or the bot is not a member. The error message includes the specific inaccessible channel IDs: "Slack channel override failed. Ensure the QA.tech bot has access to: C0478ABCDEF, C0123FAIL42" (channel IDs are listed in the error).
  • Schema validation errors include detailed Zod error messages when the request structure is invalid (e.g., missing required fields, invalid enum values).

Example Requests

Basic Test Run

curl -X POST https://app.qa.tech/api/projects/YOUR_PROJECT_UUID/runs \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "integrationName": "API",
    "testPlanShortId": "abc123"
  }'

Test Run with Preview Environment

curl -X POST https://app.qa.tech/api/projects/YOUR_PROJECT_UUID/runs \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "integrationName": "Vercel Preview",
    "testPlanShortId": "abc123",
    "applications": {
      "frontend-app": {
        "environment": {
          "url": "https://pr-123-frontend.vercel.app",
          "name": "PR-123-Frontend"
        }
      },
      "backend-api": {
        "environment": {
          "short_id": "existing-env-456"
        }
      }
    }
  }'

Test Run with Slack Notification Override

curl -X POST https://app.qa.tech/api/projects/YOUR_PROJECT_UUID/runs \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "integrationName": "GitHub Actions",
    "testPlanShortId": "abc123",
    "notifications": [
      { "type": "slack", "channel": "C0478ABCDEF", "notifyOn": "always" },
      { "type": "slack", "channel": "C0123FAIL42", "notifyOn": "failure" }
    ]
  }'

Response Format

Success Response (200)

{
  "success": true,
  "run": {
    "id": "run_abc123def456",
    "shortId": "abc123",
    "url": "https://app.qa.tech/projects/project-123/results/abc123",
    "testCount": 5,
    "testPlan": {
      "name": "API Integration Tests",
      "short_id": "xyz789"
    }
  }
}

Error Responses

Bad Request (400)

Returned when the request body is malformed, missing required fields, or validation fails. Examples: Empty notifications array:
{
  "statusText": "Failed to parse notifications in request: Array must contain at least 1 element(s)"
}
Slack integration not configured:
{
  "statusText": "Slack integration is not configured for this project. Configure Slack before overriding notification channels."
}
Inaccessible Slack channels:
{
  "statusText": "Slack channel override failed. Ensure the QA.tech bot has access to: C0478ABCDEF, C0123FAIL42"
}
Invalid test plan or malformed request:
{
  "statusText": "Invalid test plan ID or malformed applications config"
}

Forbidden (403)

Returned when the bearer token is invalid or expired, when Netlify webhook signature verification fails, or when the organization is suspended. Examples: Invalid token:
{
  "statusText": "Unknown Error"
}
Organization suspended:
{
  "statusText": "Organization is suspended"
}

Payment Required (402)

Returned when the organization has reached its usage limit. Example:
{
  "statusText": "Organization has reached usage limit. Upgrade your account to continue."
}

Not Found (404)

Returned when the specified project ID doesn’t exist. Example:
{
  "statusText": "Unknown Error"
}

Internal Server Error (500)

Returned when there’s an internal server error. Example:
{
  "statusText": "API Error"
}

Use Cases

CI/CD Integration

Integrate test runs into your deployment pipeline to automatically test changes before they reach production.

Preview Environment Testing

Test pull request changes in isolated environments before merging.

Scheduled Testing

Set up recurring test runs to ensure ongoing quality assurance.

Custom Workflows

Trigger tests based on custom business logic or external events.

Integration Examples

GitHub Actions

name: QA.tech Test Run
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  deploy:
    runs-on: ubuntu-latest
    outputs:
      preview_url: ${{ steps.deploy.outputs.url }}
    steps:
      - name: Deploy to Preview
        id: deploy
        run: |
          # Your deployment logic
          echo "url=https://preview-${{ github.event.pull_request.number }}.vercel.app" >> $GITHUB_OUTPUT

  test:
    runs-on: ubuntu-latest
    needs: deploy
    steps:
      - name: Trigger QA.tech Test
        run: |
          curl -X POST https://app.qa.tech/api/projects/${{ secrets.QATECH_PROJECT_ID }}/runs \
            -H "Authorization: Bearer ${{ secrets.QATECH_API_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{
              "integrationName": "GitHub Actions",
              "testPlanShortId": "abc123",
              "applications": {
                "frontend-app": {
                  "environment": {
                    "url": "${{ needs.deploy.outputs.preview_url }}",
                    "name": "PR-${{ github.event.pull_request.number }}"
                  }
                }
              }
            }'
This API endpoint works with any CI/CD system. For platform-specific guides and examples:

OpenAPI Specification

For detailed API schema and additional examples, refer to the OpenAPI specification.