---
title: Update Plan (Appium2)
slug: suite-documentation/update-plan-appium2
docTags: 
createdAt: 2026-08-26T08:43:39.272Z
---

This endpoint updates an existing Appium2 test plan.

Most fields are optional. Only non-null fields are copied to the existing plan. However, mobile app fields should be handled carefully: if `androidMobileApp` or `iosMobileApp` is sent as `null` or omitted, the related mobile app selection may be cleared by the current backend flow.

***

### Endpoint Information

- **URL**: `{gateway-url}/plans/{planId}`
- **Method**: `PUT`
- **Authentication**: Required (`Bearer Token`)

### Request Headers

| Header          | Required | Description                                                                 |
| --------------- | -------- | --------------------------------------------------------------------------- |
| `Authorization` | Yes      | Bearer token used for authentication. Example: `Bearer <your_access_token>` |
| `Content-Type`  | Yes      | Must be `application/json`.                                                 |
| `X-Company-Id`  | Yes      | The company ID used by the gateway to authorize and route the request.      |

### Path Variables

| Parameter | Type | Required | Description                                         |
| --------- | ---- | -------- | --------------------------------------------------- |
| `planId`  | Long | Yes      | The ID of the test plan. Must be a positive number. |

### Request Body

```json
{
  "planName": "Updated Appium2 Test Plan",
  "groupPlan": false,
  "description": "Updated description for the Appium2 test plan.",
  "type": "APPIUM",
  "enabled": true,
  "deleted": false,
  "planParallelTestLimit": 5,
  "projectId": 913,
  "userId": 1,
  "failedTestRetryCount": 2,
  "maxExecutionTime": 3600,
  "testRunType": "CROSS",
  "screenShotType": "YES",
  "videoEnabled": true,
  "uninstallApp": false,
  "clearAppData": false,
  "androidMobileApp": 134,
  "iosMobileApp": null,
  "isSigned": true,
  "alertsEnabled": true,
  "testDispatchMethodType": "ONE_BY_ONE",
  "forceSave": false
}
```

### Request Body Parameters

| Field                     | Type             | Required | Description                                                                                            |
| ------------------------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `planName`                | String           | No       | Updated name of the test plan.                                                                         |
| `groupPlan`               | Boolean          | No       | Indicates whether the plan is a group plan.                                                            |
| `description`             | String           | No       | Updated description of the test plan.                                                                  |
| `type`                    | String           | No       | Plan type. For Appium2 plans, send `APPIUM`.                                                           |
| `enabled`                 | Boolean          | No       | Indicates whether the plan is enabled.                                                                 |
| `deleted`                 | Boolean          | No       | Indicates whether the plan is marked as deleted.                                                       |
| `planParallelTestLimit`   | Integer          | No       | Maximum parallel test limit for this plan.                                                             |
| `period`                  | Object           | No       | Period configuration to update together with the plan, if needed.                                      |
| `projectId`               | Long             | No       | Project ID related to the plan.                                                                        |
| `userId`                  | Long             | No       | User ID related to the plan.                                                                           |
| `failedTestRetryCount`    | Integer          | No       | Number of retries for failed tests.                                                                    |
| `maxExecutionTime`        | Integer          | No       | Maximum execution time in seconds.                                                                     |
| `testRunType`             | String           | No       | Test run mode. Supported values: `CROSS`, `SEQUENCE`.                                                  |
| `screenShotType`          | String           | No       | Screenshot behavior. Supported values: `YES`, `NO`, `ONLY_FAILURE`.                                    |
| `videoEnabled`            | Boolean          | No       | Indicates whether video recording is enabled.                                                          |
| `uninstallApp`            | Boolean          | No       | Indicates whether the mobile app should be uninstalled after execution.                                |
| `clearAppData`            | Boolean          | No       | Indicates whether app data should be cleared before execution.                                         |
| `androidMobileApp`        | Long             | No       | Android mobile app ID. Send the current ID again if you want to keep the selected Android app.         |
| `iosMobileApp`            | Long             | No       | iOS mobile app ID. Send the current ID again if you want to keep the selected iOS app.                 |
| `isSigned`                | Boolean          | No       | Indicates whether the selected iOS app is signed.                                                      |
| `alertsEnabled`           | Boolean          | No       | Indicates whether alerts are enabled for this plan.                                                    |
| `parentId`                | Long             | No       | Parent plan ID, if this is a child plan.                                                               |
| `planEnvironmentsRequest` | Array of objects | No       | Appium2 environment list to upsert together with the plan.                                             |
| `testDispatchMethodType`  | String           | No       | Dispatch strategy. Supported values: `ONE_BY_ONE`, `ALL_IN_ONE`.                                       |
| `forceSave`               | Boolean          | No       | If `true`, skips Appium2 environment registration validation while updating `planEnvironmentsRequest`. |

### Important Notes

- This endpoint updates the plan using `PUT`.
- Most null fields are ignored during update.
- `androidMobileApp` and `iosMobileApp` are exceptions in practice: send the current app ID again if the app selection should be preserved.
- For Appium2 group plans, the number of selected environments cannot be greater than `planParallelTestLimit`.
- If `testDispatchMethodType` is `ALL_IN_ONE`, `planParallelTestLimit` must not be greater than `1`, `failedTestRetryCount` must be `0`, and only one environment is allowed.
- If `planEnvironmentsRequest` is provided and `forceSave` is not `true`, environments are validated against registered healthy DevicePark devices.

### Response Body

```json
{
  "data": {
    "id": 316,
    "planName": "Updated Appium2 Test Plan",
    "groupPlan": false,
    "description": "Updated description for the Appium2 test plan.",
    "enabled": true,
    "deleted": false,
    "planParallelTestLimit": 5,
    "periodId": 318,
    "projectId": 913,
    "projectName": "Demo",
    "projectTestFramework": "APPIUM2",
    "userId": 1,
    "companyId": 2,
    "failedTestRetryCount": 2,
    "maxExecutionTime": 3600,
    "testRunType": "CROSS",
    "screenShotType": "YES",
    "videoEnabled": true,
    "uninstallApp": false,
    "clearAppData": false,
    "iosMobileApp": null,
    "androidMobileApp": {
      "id": 134,
      "mobileAppName": "Demo.apk",
      "mobileAppHash": "Demo",
      "mobileAppMetadata": "{}",
      "operatingSystem": "ANDROID",
      "createdAt": "2026-08-18T12:08:41.165927056Z"
    },
    "isSigned": true,
    "testFileType": "APPIUM_GAUGE",
    "testRunnerTool": "MAVEN",
    "testDispatchMethodType": "ONE_BY_ONE",
    "alertsEnabled": true,
    "gridType": "TESTINIUM_ENTERPRISE",
    "isParent": false,
    "parentId": null
  }
}
```

### Response Fields

| Field                         | Type    | Description                                                             |
| ----------------------------- | ------- | ----------------------------------------------------------------------- |
| `data`                        | Object  | Updated test plan payload.                                              |
| `data.id`                     | Long    | Unique identifier of the test plan.                                     |
| `data.planName`               | String  | Name of the test plan.                                                  |
| `data.groupPlan`              | Boolean | Indicates whether the plan is a group plan.                             |
| `data.description`            | String  | Description of the test plan.                                           |
| `data.enabled`                | Boolean | Indicates whether the plan is enabled.                                  |
| `data.deleted`                | Boolean | Indicates whether the plan is marked as deleted.                        |
| `data.planParallelTestLimit`  | Integer | Maximum parallel test limit for this plan.                              |
| `data.periodId`               | Long    | ID of the period configuration.                                         |
| `data.projectId`              | Long    | ID of the project that owns the plan.                                   |
| `data.projectName`            | String  | Name of the project.                                                    |
| `data.projectTestFramework`   | String  | Project framework. For Appium2 plans, this value is `APPIUM2`.          |
| `data.userId`                 | Long    | ID of the user associated with the plan.                                |
| `data.companyId`              | Long    | ID of the company that owns the plan.                                   |
| `data.failedTestRetryCount`   | Integer | Number of retries for failed tests.                                     |
| `data.maxExecutionTime`       | Integer | Maximum execution time in seconds.                                      |
| `data.testRunType`            | String  | Test run mode.                                                          |
| `data.screenShotType`         | String  | Screenshot behavior.                                                    |
| `data.videoEnabled`           | Boolean | Indicates whether video recording is enabled.                           |
| `data.uninstallApp`           | Boolean | Indicates whether the mobile app should be uninstalled after execution. |
| `data.clearAppData`           | Boolean | Indicates whether app data should be cleared before execution.          |
| `data.iosMobileApp`           | Object  | Selected iOS mobile app summary, if available.                          |
| `data.androidMobileApp`       | Object  | Selected Android mobile app summary, if available.                      |
| `data.isSigned`               | Boolean | Indicates whether the selected iOS app is signed.                       |
| `data.testFileType`           | String  | Type of test files used by the project.                                 |
| `data.testRunnerTool`         | String  | Test runner tool used by the project.                                   |
| `data.testDispatchMethodType` | String  | Dispatch strategy.                                                      |
| `data.alertsEnabled`          | Boolean | Indicates whether alerts are enabled for this plan.                     |
| `data.gridType`               | String  | Grid type used for execution.                                           |
| `data.isParent`               | Boolean | Indicates whether this plan is a parent plan.                           |
| `data.parentId`               | Long    | Parent plan ID, if this is a child plan.                                |

### Error Response Format

```json
{
  "instance": "/plans/999999",
  "status": 404,
  "title": "Not Found",
  "type": "https://errors.testinium.com/exception",
  "timestamp": "2026-08-18T12:08:41.165927056Z",
  "errorType": "EXCEPTION",
  "errors": {
    "code": 10003,
    "message": "Plan with id 999999 not found!"
  }
}
```

### HTTP Error Codes

| HTTP Code | Error Message           | Description                                                                                     |
| --------- | ----------------------- | ----------------------------------------------------------------------------------------------- |
| `400`     | `Bad Request`           | Request body is invalid, malformed, contains invalid enum values, or Appium2 validation failed. |
| `401`     | `Unauthorized`          | Authentication is missing or invalid.                                                           |
| `403`     | `Forbidden`             | User does not have permission for this operation or company.                                    |
| `404`     | `Not Found`             | Plan or selected mobile app was not found.                                                      |
| `405`     | `Method Not Allowed`    | The endpoint was called with an unsupported HTTP method.                                        |
| `422`     | `Unprocessable Entity`  | Appium2 environment registration confirmation is required.                                      |
| `500`     | `Internal Server Error` | An unexpected error occurred on the server side.                                                |
| `503`     | `Service Unavailable`   | Project service or another downstream service is unavailable.                                   |

### Application Error Codes

| Code    | HTTP Status | Source            | Description                                                                                |
| ------- | ----------- | ----------------- | ------------------------------------------------------------------------------------------ |
| `10003` | `404`       | Project           | Test plan not found.                                                                       |
| `10008` | `422`       | Project           | One or more Appium2 environments are not registered.                                       |
| `10009` | `404`       | Project           | Mobile app not found.                                                                      |
| `10012` | `400`       | Project           | For Appium2 group plans, environment count cannot be greater than `planParallelTestLimit`. |
| `10001` | `401`       | Gateway           | Authentication is required.                                                                |
| `10002` | `401`       | Gateway           | Token is invalid or cannot be verified.                                                    |
| `10003` | `403`       | Gateway           | Authorization failed for the requested resource.                                           |
| `10004` | `400`       | Gateway           | A required header, such as `X-Company-Id`, is missing or invalid.                          |
| `10008` | `503`       | Gateway           | Routed service is unavailable.                                                             |
| `10007` | `503`       | Common            | Downstream service is unavailable.                                                         |
| `20005` | `400`       | Common Validation | Request body or path variable validation failed.                                           |
| `20007` | `400`       | Common Validation | Invalid enum value.                                                                        |
| `20008` | `400`       | Common Validation | Path variable type is invalid.                                                             |
| `20009` | `405`       | Common Validation | HTTP method is not supported.                                                              |

### Example Request

```bash
curl --location --request PUT '{gateway-url}/plans/{planId}' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer <your_access_token>' \
  --header 'X-Company-Id: <company_id>' \
  --data '{
    "planName": "Updated Appium2 Test Plan",
    "groupPlan": false,
    "description": "Updated description for the Appium2 test plan.",
    "type": "APPIUM",
    "enabled": true,
    "deleted": false,
    "planParallelTestLimit": 5,
    "projectId": 913,
    "userId": 1,
    "failedTestRetryCount": 2,
    "maxExecutionTime": 3600,
    "testRunType": "CROSS",
    "screenShotType": "YES",
    "videoEnabled": true,
    "uninstallApp": false,
    "clearAppData": false,
    "androidMobileApp": 134,
    "iosMobileApp": null,
    "isSigned": true,
    "alertsEnabled": true,
    "testDispatchMethodType": "ONE_BY_ONE",
    "forceSave": false
  }'
```

