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

# Installation Rollback

> Roll a specific installation back to a previous version, or resume auto-updates

# Installation Rollback

A merchant can roll an individual app installation back to any
previously published (or currently deprecated) version, independent of
the version the rest of the merchant base is on. Rollback **pins** the
installation — the next time the developer publishes a new version, this
installation is **not** auto-updated. The merchant must explicitly
resume auto-updates to opt back in.

Both endpoints require merchant or staff-admin auth
(merchant or staff-admin) and scope the
installation lookup by the caller's `storeId`.

## Endpoints

| Method | Path                                                           | Purpose                            |
| ------ | -------------------------------------------------------------- | ---------------------------------- |
| `POST` | `/apps/store/installations/:installationId/rollback`           | Pin install to a specific version. |
| `POST` | `/apps/store/installations/:installationId/resume-auto-update` | Unpin and re-enable auto-update.   |

## Installation Lifecycle States

The relevant fields on the installation are:

| Field              | Type                 | Purpose                                                                      |
| ------------------ | -------------------- | ---------------------------------------------------------------------------- |
| `installedVersion` | `string(20)`         | The version currently running for this merchant.                             |
| `pinnedVersion`    | `string(20) \| null` | If non-null, auto-update is suspended; this is the merchant's chosen target. |
| `autoUpdate`       | `boolean`            | Default `true`. Flipped to `false` on rollback.                              |

| Lifecycle                      | `installedVersion`           | `pinnedVersion` | `autoUpdate` |
| ------------------------------ | ---------------------------- | --------------- | ------------ |
| Fresh install                  | `1.0.0` (latest published)   | `null`          | `true`       |
| Developer publishes `1.1.0`    | `1.1.0` (auto-bumped)        | `null`          | `true`       |
| Merchant rolls back to `1.0.0` | `1.0.0`                      | `1.0.0`         | `false`      |
| Developer publishes `1.2.0`    | `1.0.0` (unchanged — pinned) | `1.0.0`         | `false`      |
| Merchant resumes auto-update   | `1.2.0` (latest published)   | `null`          | `true`       |

## Rollback to a Specific Version

### `POST /apps/store/installations/:installationId/rollback`

```bash theme={null}
curl -X POST "https://api.launchmystore.io/apps/store/installations/inst_abc123/rollback" \
  -H "Authorization: Bearer MERCHANT_JWT" \
  -H "Content-Type: application/json" \
  -d '{ "targetVersion": "1.0.0" }'
```

<ParamField path="installationId" type="string" required>
  The UUID of the installation to roll back. Must belong to the caller's
  `storeId`.
</ParamField>

<ParamField body="targetVersion" type="string" required>
  Semver version string to roll back (or forward) to. Must exist as an
  `AppVersion` row in either `published` or `deprecated` status — `draft`
  versions cannot be installed by merchants.
</ParamField>

Side effects on success:

1. `installedVersion = targetVersion`
2. `pinnedVersion = targetVersion`
3. `autoUpdate = false`
4. A `rolled_back` entry is appended to the version changelog.

Response (200):

```json theme={null}
{
  "status": 200,
  "state": "success",
  "data": {
    "installationId": "inst_abc123",
    "appId": "lms_app_xxx",
    "storeId": "f73049dc-...",
    "installedVersion": "1.0.0",
    "pinnedVersion": "1.0.0",
    "autoUpdate": false,
    "status": "active",
    "grantedScopes": ["read_products", "write_metafields"],
    "...": "..."
  }
}
```

Error codes:

| HTTP  | Message                                     | When                                           |
| ----- | ------------------------------------------- | ---------------------------------------------- |
| `404` | `Installation not found`                    | `(installationId, storeId)` not matched.       |
| `404` | `Target version not found or not available` | `AppVersion` row missing or in `draft` status. |
| `500` | (generic)                                   | DB write failed.                               |

## Resume Auto-Updates

### `POST /apps/store/installations/:installationId/resume-auto-update`

```bash theme={null}
curl -X POST "https://api.launchmystore.io/apps/store/installations/inst_abc123/resume-auto-update" \
  -H "Authorization: Bearer MERCHANT_JWT"
```

Side effects on success:

1. `autoUpdate = true`
2. `pinnedVersion = null`
3. If a published version exists for this app, `installedVersion`
   jumps to the latest published version. Otherwise `installedVersion`
   is left as-is.

Response (200): the updated installation.

```json theme={null}
{
  "status": 200,
  "state": "success",
  "data": {
    "installationId": "inst_abc123",
    "installedVersion": "1.2.0",
    "pinnedVersion": null,
    "autoUpdate": true,
    "status": "active"
  }
}
```

| HTTP  | Message                  | When                                     |
| ----- | ------------------------ | ---------------------------------------- |
| `404` | `Installation not found` | `(installationId, storeId)` not matched. |

## Interaction with Developer Publish

When a developer publishes a new version
(`POST /apps/developer/:appId/versions/:version/publish`), the platform
bumps `installedVersion` to the new version on every installation of
the app that has `autoUpdate = true` and no pinned version.

Pinned installations are **skipped entirely** — the publish has no
effect on them until the merchant resumes auto-update.

## When to use rollback vs uninstall

| Goal                                                  | Endpoint                            |
| ----------------------------------------------------- | ----------------------------------- |
| Run an older version of the same app for one merchant | `rollback`                          |
| Permanently uninstall and remove extension files      | `POST /apps/store/uninstall/:appId` |
| Stop receiving auto-updates but keep current version  | `rollback` to current version       |
| Switch back to "always latest"                        | `resume-auto-update`                |

## Common Patterns

### Pin to the current version (suspend updates)

Rolling back to the version already installed is a valid no-op publish:

```bash theme={null}
# Currently installed: 1.2.0. Pin it.
curl -X POST .../installations/inst_abc/rollback \
  -d '{ "targetVersion": "1.2.0" }'
```

After this call, the merchant stays on `1.2.0` regardless of future
publishes, until they call `/resume-auto-update`.

### Beta channel

Developers commonly publish `1.x.x-beta.N` versions, then have early-
access merchants `rollback` to the beta version. When the beta is
promoted (the dev publishes `1.x.x` as stable), pinned beta merchants
keep their `-beta.N` install until they resume auto-update.

<Note>
  There is currently no `force` flag — auto-updates always respect
  `pinnedVersion`. If a merchant must be force-updated (e.g. critical
  security fix), contact platform support; there is no public REST
  endpoint for this.
</Note>
