# Update a lifecycle

Source: https://www.jawsdeploy.net/rest-api/lifecycles-update | Section: Lifecycles

Update a lifecycle's name, description, or phase list.

`PUT /api/lifecycle`

Update lifecycle metadata. If `phases` is provided it fully replaces the existing phase list (and validates each environment ID against the workspace). Send `knownPhaseIds` alongside it to be told when somebody else changed the phases first, rather than overwriting their work - see below.

## Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `lifecycleId` | body | string | yes | ID of the lifecycle. |
| `name` | body | string | no | New name. |
| `description` | body | string | no | New description. |
| `phases` | body | array<object> | no | Replacement phase list (optional). |
| `knownPhaseIds` | body | array<string> | no | The phase IDs you believe the lifecycle currently has. Send it to be told about a concurrent change instead of silently overwriting it. Omit it to skip the check. See below. |

### Not overwriting somebody else's phases

Sending `phases` replaces the **whole** list, so a stored phase you leave out is deleted. That is right when you meant to remove it, and destructive when you simply never knew it was there - a caller that read the lifecycle before somebody else added a phase looks exactly like a caller that deleted one.

`knownPhaseIds` tells the two apart. Send back the phase IDs you got when you read the lifecycle, and the update is refused if the stored set has moved on - phases added by somebody else since you read it, and phases they removed, both count.

A mismatch returns `409` with an `errorcode` of `ConcurrentModification` and a message saying how many phases were added and how many removed. **Nothing is written.** The comparison runs inside the same transaction as the write, so it cannot race the thing it guards. Re-read the lifecycle with [Get lifecycle details](https://www.jawsdeploy.net/rest-api/lifecycles-details), apply your change to what is actually there, and send it again with the fresh IDs.

Omitting `knownPhaseIds` skips the check and last write wins. That is a fair choice for a pipeline that owns its lifecycle outright, and the wrong one anywhere a person might be editing the same lifecycle in the UI at the same time.

IDs are compared as GUIDs, so casing and surrounding braces do not matter - `{A1B2...}` and `a1b2...` are the same phase. Send them back as you received them and this never arises.

This is the only endpoint that replaces the whole phase list, so it is the only one that needs a baseline from the caller. [Add](https://www.jawsdeploy.net/rest-api/lifecycle-phase-add), [update](https://www.jawsdeploy.net/rest-api/lifecycle-phase-update) and [delete](https://www.jawsdeploy.net/rest-api/lifecycle-phase-delete) each name a single phase by ID and build their own baseline server-side, so none of them can remove a phase you never knew about.

## Errors

| Status | Meaning |
|---|---|
| 400 | Invalid `lifecycleId` or validation failure. |
| 401 | Missing or invalid Basic auth credentials, or the service account lacks the required role. |
| 409 | `knownPhaseIds` no longer matches the lifecycle's stored phases. `errorcode` is `ConcurrentModification` and the message says how many phases were added and how many removed. Nothing is written - re-read the lifecycle and send the change again. |

Example request:

```
PUT /api/lifecycle HTTP/1.1
Host: app.jawsdeploy.net
Authorization: Basic <base64(serviceAccountId:apiKey)>
Content-Type: application/json

{
  "lifecycleId": "lc_1",
  "description": "Default flow",
  "knownPhaseIds": ["lph_1", "lph_2"]
}
```

Example response:

```
{}
```

