---
title: "Get a test plan"
method: GET
path: "/api/plans/{planId}"
tags: ["Test Plans"]
---

# Get a test plan

`GET /api/plans/{planId}`

## Request

- Base URL: `https://aximo.autify.com`
- URL: `https://aximo.autify.com/api/plans/{planId}`
- Auth: API key in header `x-api-key`
- TypeScript: <https://skmtc.dev/autify/apis/aximo-api/docs/api/plans/:planId/get.ts> (a function with typed inputs; its response is checked against the schema)

Returns a plan's full detail: settings, plan variables (secret values
are masked as `***` and flagged with `isSecret`), and its cases in
execution order.

## Path parameters

- `planId` string, uuid, required

## Response `200`

Plan detail.

- PlanDetail
  - `id` string, uuid, required
  - `projectId` string, uuid, required
  - `title` string, required
  - `description` string, nullable
  - `apiEnabled` boolean, required: Whether the plan can be triggered through the API.
  - `executionMode` 'parallel' | 'sequential', required
  - `stopOnFailure` boolean, required
  - `deviceMode` 'pool' | 'matrix', required: pool: each case runs once on whichever configured device is free. matrix: each case runs on every configured device.
  - `mobileConfig` PlanMobileConfig, required: Per-platform target devices and app for a plan's mobile cases, as saved on the plan settings page. Omit a platform (or set it to `null`) to run that platform's cases with no plan-level device; an empty object clears both. A single app given through the flat fields is stored as `apps[0]` too, so `GET` returns both forms. Unknown keys are rejected: this is not the single-device `mobileConfig` of the trigger endpoint.
    - `ios` PlanMobilePlatformConfig: Devices and app for one platform. The app fields are the same as `CaseMobileConfig`: a single app via `uploadArn`/`uploadType`/`appName`/`bundleId`, or up to three via `apps`. When `apps` is given, `apps[0]` is stored as the primary app and takes precedence over the single-app fields; a `bundleId` that contradicts `apps[0].bundleId` is rejected. The app is installed and launched on every device listed here, Device Farm or local; a local phone whose platform has no plan app installs and launches the case's own app; its run case fails at dispatch when neither names an app for it.
      - `devices` PlanMobileDevice[], required
        - `deviceArn` string: Encrypted device identifier token from `GET /api/devices`. Not set for a local phone.
        - `deviceName` string
        - `os` string, nullable
        - `formFactor` string
        - `userDeviceId` string, uuid: Registered local phone to run on instead of Device Farm.
      - `uploadArn` string: Encrypted upload identifier token from `GET /api/uploads`. The upload must have status `succeeded` and match the platform.
      - `uploadType` 'own_app' | 'existing' | 'sample'
      - `appName` string
      - `bundleId` string
      - `apps` CaseAppInfo[]
        - `uploadArn` string, required: Encrypted upload identifier token.
        - `uploadType` 'own_app' | 'existing' | 'sample', required
        - `appName` string, nullable, required
        - `bundleId` string
    - `android` PlanMobilePlatformConfig: Devices and app for one platform. The app fields are the same as `CaseMobileConfig`: a single app via `uploadArn`/`uploadType`/`appName`/`bundleId`, or up to three via `apps`. When `apps` is given, `apps[0]` is stored as the primary app and takes precedence over the single-app fields; a `bundleId` that contradicts `apps[0].bundleId` is rejected. The app is installed and launched on every device listed here, Device Farm or local; a local phone whose platform has no plan app installs and launches the case's own app; its run case fails at dispatch when neither names an app for it.
      - `devices` PlanMobileDevice[], required
        - `deviceArn` string: Encrypted device identifier token from `GET /api/devices`. Not set for a local phone.
        - `deviceName` string
        - `os` string, nullable
        - `formFactor` string
        - `userDeviceId` string, uuid: Registered local phone to run on instead of Device Farm.
      - `uploadArn` string: Encrypted upload identifier token from `GET /api/uploads`. The upload must have status `succeeded` and match the platform.
      - `uploadType` 'own_app' | 'existing' | 'sample'
      - `appName` string
      - `bundleId` string
      - `apps` CaseAppInfo[]
        - `uploadArn` string, required: Encrypted upload identifier token.
        - `uploadType` 'own_app' | 'existing' | 'sample', required
        - `appName` string, nullable, required
        - `bundleId` string
  - `desktopConfig` PlanDesktopConfig, required: Registered BYOD desktop devices the plan's desktop cases run on.
    - `devices` PlanDesktopDevice[], required
      - `userDeviceId` string, uuid, required
      - `name` string, required
      - `platform` 'windows' | 'macos' | 'linux', required
      - `os` string, nullable, required
  - `variables` object[], required: Plan variables. Secret values are always masked as `***`.
    - `name` string, required
    - `value` string, required
    - `isSecret` boolean, required
  - `caseCount` integer, required
  - `archivedAt` string, date-time, nullable: Set when the plan was archived (soft-deleted). Archived plans are excluded from lists but stay readable by id.
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `createdBy` object, nullable
    - `id` string
    - `name` string, nullable
    - `email` string
  - `project` object, nullable
    - `id` string, uuid
    - `name` string
  - `cases` object[], required: The plan's cases in execution order.
    - `id` string, uuid, required
    - `order` integer, required
    - `type` 'web' | 'mobile' | 'desktop' | 'multi_device', required
    - `title` string, nullable, required
    - `lastStatus` string, nullable

## Other responses

- `400`: Invalid plan id.
- `401`: Missing or invalid API key.
- `404`: Test plan not found.
- `429`: Rate limit exceeded — e.g. the daily session limit was reached for the organization, or too many API requests were sent in a short window (retry after the number of seconds in the `Retry-After` header).
- `500`: Unexpected server error.

---

[API](https://skmtc.dev/autify/apis/aximo-api.md) - [All operations](https://skmtc.dev/autify/apis/aximo-api/llms.txt) - [OpenAPI document](https://skmtc.dev/autify/apis/aximo-api/revisions/590722011284?raw)
