> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knowlify.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Revert edit

> Undo the most recent completed edit on a video

## Overview

`POST /v1/edits/{edit_id}/revert` restores the planner snapshot saved before this edit was applied, rewinds the video clips and timestamps, and updates the edit's `status` to `reverted`. Strict LIFO — only the most recent completed external edit on a video can be reverted; older edits must wait for any newer ones to be reverted first.

<Info>
  Revert runs three preconditions. All three must pass before the snapshot is restored:

  1. **No active edits.** Nothing on the video is `processing` or `queued`.
  2. **Strict LIFO.** No newer external edit (non-error, non-reverted) exists for this video.
  3. **Snapshot correlation.** The top of the video's `planner_history` was saved by this edit — guards against a frontend edit landing in between.

  If any guard fails, the response is `409` with a `detail` that names the violated rule.
</Info>

## Endpoint

```
POST {API_BASE}/v1/edits/{edit_id}/revert
```

<Note>
  Your `API_BASE` is shown in the Developer tab of your dashboard. The default production base is `https://api.knowlify.com`.
</Note>

## Authentication

Send your key in the `X-API-Key` header. Only the API key that submitted the edit (or another active key in the same organization) may revert it.

```bash theme={null}
X-API-Key: kn_<64 hex chars>
```

See [Authentication](/api-reference/authentication) for details on key issuance, rotation, and JWT alternatives.

## Path parameters

<ParamField path="edit_id" type="string" required>
  The edit ID returned by `POST /v1/edits`. The edit must be in `status: "complete"`.
</ParamField>

## Request body

No body. The path parameter fully specifies the operation.

## Code examples

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://api.knowlify.com/v1/edits/e942890a-7776-4029-82d6-ce733d0a2cb2/revert" \
    -H "X-API-Key: kn_YOUR_KEY_HERE"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch(
    `https://api.knowlify.com/v1/edits/${editId}/revert`,
    {
      method: "POST",
      headers: { "X-API-Key": "kn_YOUR_KEY_HERE" },
    },
  );
  const edit = await res.json();
  console.log(edit.status, edit.result.revert_diff);
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      f"https://api.knowlify.com/v1/edits/{edit_id}/revert",
      headers={"X-API-Key": "kn_YOUR_KEY_HERE"},
      timeout=30,
  )
  resp.raise_for_status()
  edit = resp.json()
  print(edit["status"], edit["result"]["revert_diff"])
  ```
</CodeGroup>

## Response

A successful revert returns `200` with the same shape as [`GET /v1/edits/{edit_id}`](/api-reference/poll-edit), now reflecting the reverted state:

* `status` is `"reverted"`.
* `is_complete` is `true`.
* `result` keeps the original `link` / scene-number arrays from the completed edit, plus a new `revert_diff` describing what the restore changed.

<ResponseField name="result.revert_diff" type="object">
  <Expandable title="revert_diff fields">
    <ResponseField name="changed_scene_numbers" type="integer[]">
      Scenes whose content the revert restored from the snapshot.
    </ResponseField>

    <ResponseField name="added_scene_numbers" type="integer[]">
      Scenes that the original edit had deleted and the revert brought back.
    </ResponseField>

    <ResponseField name="deleted_scene_numbers" type="integer[]">
      Scenes that the original edit had added and the revert removed.
    </ResponseField>
  </Expandable>
</ResponseField>

All other response fields are identical to the poll endpoint.

### Failure modes

| Code  | `detail`                                                                                  | Cause                                                                                                                                                 |
| ----- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `404` | `edit not found`                                                                          | No `external_edits` row matches `edit_id`.                                                                                                            |
| `403` | `API key does not own this edit`                                                          | The caller is neither the submitter nor an active member of the submitter's org.                                                                      |
| `409` | `edit is not in a revertable state (status=…)`                                            | The edit is still `processing` / `applying`, already `reverted`, or `error`.                                                                          |
| `409` | `cannot revert while another edit is processing or queued`                                | Another edit on the same video is in flight. Wait for it to finish.                                                                                   |
| `409` | `a newer external edit exists on this video; revert the most recent edit first`           | LIFO violation. Revert the newer edit first.                                                                                                          |
| `409` | `snapshot at the top of planner_history was not saved by this edit; cannot safely revert` | A frontend-initiated edit landed after this one, pushing a different snapshot on top. The revert cannot proceed without undoing somebody else's work. |
| `409` | `no snapshot available to revert`                                                         | The video's `planner_history` is empty (rare; suggests the edit ran but the snapshot was never saved).                                                |

All non-2xx responses share the standard envelope: `{ "detail": "<message>" }`. See [Errors](/api-reference/errors) for the full reference.

#### Example success response

```json theme={null}
{
  "edit_id": "e942890a-7776-4029-82d6-ce733d0a2cb2",
  "video_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "status": "reverted",
  "is_complete": true,
  "is_failed": false,
  "progress": { "stage": "done", "percent": 100 },
  "result": {
    "link": "https://animation-encoder-videos.s3.us-west-2.amazonaws.com/<uuid>.mp4",
    "changed_scene_numbers": [2],
    "added_scene_numbers": [],
    "deleted_scene_numbers": [],
    "regenerated_scenes": [2],
    "kept_scenes": [1, 3, 4, 5],
    "video_synced": true,
    "revert_diff": {
      "changed_scene_numbers": [2],
      "added_scene_numbers": [],
      "deleted_scene_numbers": []
    }
  },
  "error_message": null,
  "created_at": "2026-05-25T15:30:01.000000+00:00",
  "updated_at": "2026-05-25T15:45:11.000000+00:00"
}
```

## Limits & errors

* Revert is synchronous from the caller's perspective — the response returns once the planner has been restored. There is no separate polling step.
* Frame regeneration after a revert is triggered automatically when the restored planner differs from the current one (the internal `/revert-edit` pipeline handles this).
* Full status code reference: [Errors](/api-reference/errors).
