---
search:
  tags:
    - Apps
    - POST
seo:
  description: >-
    Requires a personal access token or session cookie and… Reference for the
    POST /api/v1/apps/{appId}/revisions/{revision}/restore endpoint in the
    Charming API.
sidebar:
  label: Restore an App revision
  badge: POST
title: Restore an App revision
type: openapi-operation
---
Requires a personal access token or session cookie and permission to change the App. Saves the selected revision’s source as a new revision; History keeps every revision, including the one restored over. Send the desired revision from the list as `If-Match: "<N>"` (or as `expectedRevision` in the body) and an `Idempotency-Key`. A module-contract revision publishes at once and answers 200. A package revision is rebuilt from its retained build and answers 202 with the build; poll its `statusUrl` until it publishes. Restoring a module-contract revision into an App now on the package contract moves the App back to that contract. Connector approvals the restored source does not declare are removed. A revision older than the plan’s History window answers 429 `version_limit_exceeded`. Live App data does not change.

`POST /api/v1/apps/{appId}/revisions/{revision}/restore`

**Request body** (`application/json`)

- `expectedRevision` (integer)

Request body example:

```json
{
  "expectedRevision": 0
}
```

**Responses**

- `200` — Revision restored, or the build that restored it already published.
- `202` — Restore accepted as a build. Poll the build status URL.
- `400` — Invalid app id, revision, body, or If-Match, or a missing Idempotency-Key.
- `401` — Sign-in required.
- `403` — The caller can open the App but cannot change it, or a cookie-backed request came from another origin.
- `404` — App not found, or the caller cannot open it.
- `409` — The App has no History that can be restored, or the Idempotency-Key was used for a different restore.
- `412` — The desired revision moved. The ETag header carries the current one; list History again.
- `422` — The revision cannot be restored, or its build failed.
- `428` — Neither If-Match nor expectedRevision was sent.
- `429` — The revision is older than the plan’s History window, or the build service is at capacity.
- `503` — The build service is unavailable.

Response example, 200:

```json
{
  "ok": true,
  "appId": "28c365d5-df94-4a54-8217-3ce51d068868",
  "sourceRevision": 1,
  "revision": 0,
  "manifestVersion": "string"
}
```

Found a bug or need a feature? [Tell us](/docs/capabilities/feedback) with `submit_feedback` or `POST /app/{id}/feedback`. Your feedback shapes what we build next.
