---
title: Maestro REST API | TestingBot
description: 'REST API reference for running and managing Maestro mobile tests on
  TestingBot: upload apps and flows, start test runs, list projects, fetch results
  and JUnit reports.'
source_url:
  html: https://testingbot.com/support/app-automate/maestro/api
  md: https://testingbot.com/support/app-automate/maestro/api/index.md
---
# Maestro API Overview

TestingBot provides a REST API to upload apps, run Maestro flows, and retrieve information about your [Maestro projects and runs](https://testingbot.com/support/app-automate/maestro).

In the documentation below, a Maestro project using a `:project_id` consists of a mobile application that was uploaded together with a zipped set of Maestro flow files.

A Maestro project can have multiple test runs, depending on how many device configurations (capabilities) you specified when you [started the tests](https://testingbot.com/support/app-automate/maestro/api#run).

All API endpoints require authentication using your TestingBot API key and secret, which you can obtain from the Member area.

| Base URL | Authentication |
| --- | --- |
| `https://api.testingbot.com/v1/app-automate/maestro` | HTTP Basic Auth (API key:secret) |

## CLI Alternative

For most use cases, we recommend using the [TestingBot CLI](https://testingbot.com/support/app-automate/maestro#cli) instead of the REST API directly. The CLI handles uploading your app, flows and running tests in a single command:

    # Install the CLI
    npm install -g @testingbot/cli
    
    # Authenticate
    testingbot login
    
    # Run Maestro tests (handles upload + run automatically)
    testingbot maestro app.apk ./flows --device "Pixel 8" --deviceVersion "14"

The CLI provides:

- Automatic app and flow uploads
- Real-time progress and streaming output
- Automatic report downloads
- Simpler authentication

Use the REST API directly when you need programmatic access or custom integration workflows.

## Upload App

Upload your Android (.apk/.aab) or iOS (.ipa/.app) application to TestingBot. This creates a new Maestro project and returns a project ID.

| Method | Endpoint |
| --- | --- |
| `POST` | `/app-automate/maestro/app` |

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `file` | file | Yes | The app file to upload (.apk, .aab, .ipa, .app or .zip) |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    -X POST "https://api.testingbot.com/v1/app-automate/maestro/app" \
    -F "file=@/path/to/your/app.apk"

### Response

    {
      "id": 17876,
      "app": {
        "app_url": "https://...",
        "icon_url": "https://...",
        "app_version": "1.0.0",
        "bundle_id": "com.example.app"
      }
    }

Save the returned `id` - you'll need it for uploading flows and running tests.

## Upload Maestro Flows

Upload your Maestro flow files (as a .zip archive) to an existing project. This replaces any previously uploaded flows.

| Method | Endpoint |
| --- | --- |
| `POST` | `/app-automate/maestro/:id/tests` |

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | Yes | The project ID returned from the app upload |
| `file` | file | Yes | A .zip file containing your Maestro flow YAML files |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    -X POST "https://api.testingbot.com/v1/app-automate/maestro/:id/tests" \
    -F "file=@/path/to/flows.zip"

### Response

    {
      "id": 17876,
      "flows": [
        {
          "id": 123,
          "name": "login_flow"
        }
      ]
    }

## Run Maestro Tests

Start running your Maestro flows on one or more devices. You can specify multiple device configurations to run tests in parallel.

| Method | Endpoint |
| --- | --- |
| `POST` | `/app-automate/maestro/:id/run` |

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | Yes | The project ID |
| `capabilities` | array | Yes | Array of device configurations to run tests on |
| `maestroOptions` | object | No | Additional Maestro options (version, env, flows, tags). See [Test Options](https://testingbot.com/support/app-automate/maestro/options). |
| `shardSplit` | integer | No | Group flows into N chunks, each chunk running on a separate device.  
When omitted, each flow runs in its own session on the same device. |
| `metadata` | object | No | CI/CD metadata stored with the run (e.g. `commitSha`, `pullRequestId`, `repoOwner`, `repoName`, `branch`). Displayed in the TestingBot dashboard. |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    -X POST "https://api.testingbot.com/v1/app-automate/maestro/:id/run" \
    -d '{"capabilities":[{"platformName":"Android","version":"14","deviceName":"Pixel 8"}]}' \
    -H "Content-Type: application/json"

### Response

    {
      "success": true,
      "id": 17876,
      "runs": [
        {
          "id": 18809,
          "capabilities": {
            "platformName": "Android",
            "version": "14",
            "deviceName": "Pixel 8"
          },
          "flows": [
            {
              "id": 123,
              "name": "login_flow",
              "report": "...",
              "requested_at": "2025-11-28T09:15:00.000Z",
              "completed_at": "2025-11-28T09:16:00.000Z",
              "status": "DONE",
              "test_case_id": 456
            }
          ]
        }
      ]
    }

### Error Responses

| Status Code | Description |
| --- | --- |
| `429` | Insufficient minutes available. Please upgrade your account to continue running Maestro tests. |

## List Maestro Projects

Retrieve a paginated list of all your Maestro projects.

| Method | Endpoint |
| --- | --- |
| `GET` | `/app-automate/maestro` |

### Query Parameters

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `offset` | integer | 0 | Number of records to paginate |
| `count` | integer | 10 | Number of records to return |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    "https://api.testingbot.com/v1/app-automate/maestro"

### Response

    {
      "data": [
        {
          "id": 17876,
          "name": "Maestro Project 17876",
          "created_at": "2025-11-28T08:12:31.000Z",
          "updated_at": "2025-11-28T08:12:31.000Z",
          "completed": false,
          "app": {
            "app_url": "https://...",
            "icon_url": "https://...",
            "app_version": "2.7.50420",
            "bundle_id": "org.wikipedia"
          },
          "flows_url": "https://...",
          "flows": [
            {
              "id": 123,
              "name": "login_flow",
            }
          ],
          "runs": [18809, 18854, 18863, 18866]
        }
      ],
      "meta": {
        "offset": 0,
        "count": 10,
        "total": 25
      }
    }

## Get Maestro Project Info

Retrieve details about a specific Maestro project, including all its runs.

| Method | Endpoint |
| --- | --- |
| `GET` | `/app-automate/maestro/:id` |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    "https://api.testingbot.com/v1/app-automate/maestro/:id"

### Response

    {
      "runs": [
        {
          "id": 18809,
          "status": "DONE",
          "capabilities": {
            "version": "16",
            "deviceName": "Pixel 9",
            "platformName": "Android"
          },
          "success": 1,
          "report": "",
          "options": {},
          "flows": [
            {
              "id": 123,
              "name": "login_flow",
              "report": "...",
              "requested_at": "2025-11-28T09:15:00.000Z",
              "completed_at": "2025-11-28T09:16:00.000Z",
              "status": "DONE",
              "test_case_id": 456
            }
          ]
        }
      ],
      "success": true,
      "completed": true
    }

### Run Status Values

| Status | Description |
| --- | --- |
| `WAITING` | Run is queued and waiting for a device |
| `READY` | The test is running on the device |
| `DONE` | Run has completed |
| `FAILED` | Run failed to complete |

## Get Run Info

Retrieve detailed information about a specific Maestro run. Use this to poll for completion status.

| Method | Endpoint |
| --- | --- |
| `GET` | `/app-automate/maestro/:project_id/:run_id` |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    "https://api.testingbot.com/v1/app-automate/maestro/:project_id/:run_id"

Replace `:project_id` with your project ID and `:run_id` with the run ID.

### Response

    {
      "id": 18809,
      "status": "DONE",
      "capabilities": {
        "version": "16",
        "deviceName": "Pixel 9",
        "platformName": "Android"
      },
      "flows": [
        {
          "id": 123,
          "name": "login_flow",
          "report": "...",
          "requested_at": "2025-11-28T09:15:00.000Z",
          "completed_at": "2025-11-28T09:16:00.000Z",
          "status": "DONE",
          "test_case_id": 456
        }
      ],
      "success": 1,
      "report": "",
      "options": {},
      "completed": true
    }

Poll this endpoint to check if the test has finished. The `completed` field will be `true` when the run has completed.

## JUnit Report

Retrieve the JUnit XML report for a completed Maestro run. This is useful for CI/CD integration.

| Method | Endpoint |
| --- | --- |
| `GET` | `/app-automate/maestro/:project_id/:run_id/junit_report` |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    "https://api.testingbot.com/v1/app-automate/maestro/:project_id/:run_id/junit_report"

### Response

    {
      "junit_report": "<?xml version=\"1.0\"?><testsuites>...</testsuites>"
    }

The `junit_report` field contains the XML-formatted JUnit report generated by Maestro.

## Stop Maestro Run

Stop a currently running Maestro test.

| Method | Endpoint |
| --- | --- |
| `POST` | `/app-automate/maestro/:project_id/:run_id/stop` |

[cURL](https://testingbot.com#)

    curl -u api_key:api_secret \
    -X POST "https://api.testingbot.com/v1/app-automate/maestro/:project_id/:run_id/stop"

### Response

    {
      "success": true
    }

## Frequently asked questions

Do I have to use the REST API or can I just use the TestingBot CLI?

For most workflows the [TestingBot CLI](https://testingbot.com/support/app-automate/maestro) is simpler since it handles upload, run and result polling in one command. The REST API is the right choice when you want fine-grained control, are integrating from a non-Node environment, or need to fetch artifacts asynchronously.

How do I upload my app and Maestro flows via the API?

POST your binary to the `/maestro/app` endpoint and your flow ZIP to `/maestro/:id/tests` with HTTP basic auth (API key and secret). The response returns IDs you use when starting the run. See the [Upload App](https://testingbot.com#uploadApp) and [Upload Maestro Flows](https://testingbot.com#uploadFlows) sections.

How do I start a Maestro test run via the API?

POST to the run endpoint with the app and flow IDs from the upload step, plus your device target and any options. See the [Run Maestro Tests section](https://testingbot.com#run) for the request body and response shape.

How do I fetch JUnit-style reports for CI?

GET the run's JUnit endpoint to receive a JUnit XML file with per-flow pass and fail results. Most CI runners can consume this format directly. See the [JUnit Report section](https://testingbot.com#report).

How do I cancel a running Maestro test?

POST to the stop endpoint with the run ID. See the [Stop Maestro Run section](https://testingbot.com#stop) for details.

### Looking for more help?

Have questions or need more information? Reach out via email or Slack.

[Email us](https://testingbot.com/contact/new)[Slack Join our Slack](https://join.slack.com/t/testingb0t/shared_invite/zt-3bcw9xch-jk19~6XPs_xBrsAgAedkCw)
