Skip to main content
GET
/
apps
/
developer
/
{appId}
/
versions
App Versions
curl --request GET \
  --url https://api.launchmystore.io/apps/developer/{appId}/versions \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "version": "<string>",
  "releaseNotes": "<string>",
  "extensions": {},
  "functions": {},
  "wasmPaths": {}
}
'

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.

App Versions

LaunchMyStore apps are versioned independently of the underlying App record. Each version captures a snapshot of the app’s extensions, functions, and per-function wasmPaths, plus a free-form releaseNotes body. Versions move through a three-state lifecycle:
draft ─► published ─► deprecated
  • draft — created but not visible to merchants. Cannot be installed.
  • published — the currently active version. Auto-installs to merchants with autoUpdate = true and no pinnedVersion.
  • deprecated — superseded by a newer published version, or explicitly deprecated. Still installable via rollback, but new installs go to the latest published version.
There is at most one published version per app at any time — publishing a new version automatically demotes the previously published one to deprecated. All endpoints in this group require merchant JWT auth and verify that the caller’s storeId matches App.developerId. Calls from non-owners return 404 App not found.

Endpoints

MethodPathPurpose
POST/apps/developer/:appId/versionsCreate a new draft version.
GET/apps/developer/:appId/versionsList all versions for the app.
GET/apps/developer/:appId/versions/statsPer-version install counts.
POST/apps/developer/:appId/versions/:version/publishPromote draft → published.
POST/apps/developer/:appId/versions/:version/deprecatePromote → deprecated.
For per-installation rollback and resume-auto-update, see Rollback.

Create Version

POST /apps/developer/:appId/versions

curl -X POST "https://api.launchmystore.io/apps/developer/lms_app_xxx/versions" \
  -H "Authorization: Bearer DEVELOPER_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "version": "1.2.0",
    "releaseNotes": "Added shipping zone customization. Fixed cart-transform null guard.",
    "extensions": { "blocks": [...], "snippets": [...] },
    "functions": { "cart-transform-bundle": { "type": "cart_transform" } },
    "wasmPaths": { "cart-transform-bundle": "r2://apps/lms_app_xxx/1.2.0/cart-transform.wasm" }
  }'
version
string
required
Semver-valid version string (e.g. 1.0.0, 2.3.1-beta.4). Validated with semver.valid(). Must be strictly greater than the current published version. Invalid versions return 400 Invalid version format. Use semver (e.g. 1.0.0). Versions less than or equal to the latest published return 400 Version must be greater than X.Y.Z.
releaseNotes
string
Free-form changelog body. Displayed to merchants when they review the update and to staff in the review queue.
extensions
object
Snapshot of the app’s extensions config for this version. Defaults to App.extensions (the live config) when omitted.
functions
object
Snapshot of function definitions for this version.
wasmPaths
object
Map of functionHandle → wasmPath for this version’s compiled artifacts. The artifacts themselves must already be uploaded via POST /apps/developer/:appId/functions.
Response (201):
{
  "status": 201,
  "state": "success",
  "data": {
    "versionId": "9f8e7d6c-...",
    "appId": "lms_app_xxx",
    "version": "1.2.0",
    "releaseNotes": "Added shipping zone customization...",
    "extensions": { "...": "..." },
    "functions": { "...": "..." },
    "wasmPaths": { "...": "..." },
    "status": "draft",
    "publishedAt": null,
    "deprecatedAt": null,
    "createdBy": "<developerId>",
    "createdAt": "2026-05-16T12:00:00.000Z",
    "updatedAt": "2026-05-16T12:00:00.000Z"
  }
}
A created entry is also appended to AppVersionChangelogs.

List Versions

GET /apps/developer/:appId/versions

Returns every version (any status), newest-first by createdAt.
{
  "status": 200,
  "state": "success",
  "data": [
    { "version": "1.2.0", "status": "published", "publishedAt": "2026-05-16T12:34:00.000Z" },
    { "version": "1.1.0", "status": "deprecated", "publishedAt": "2026-04-01T...", "deprecatedAt": "2026-05-16T12:34:00.000Z" },
    { "version": "1.0.0", "status": "deprecated", "publishedAt": "2026-03-01T...", "deprecatedAt": "2026-04-01T..." }
  ]
}

Version Stats

GET /apps/developer/:appId/versions/stats

Per-version install counts (joins AppVersions against AppInstallations.installedVersion).
{
  "status": 200,
  "state": "success",
  "data": {
    "totalInstallations": 1284,
    "versions": [
      { "version": "1.2.0", "status": "published",  "publishedAt": "2026-05-16T...", "deprecatedAt": null, "installCount": 1102 },
      { "version": "1.1.0", "status": "deprecated", "publishedAt": "2026-04-01T...", "deprecatedAt": "2026-05-16T...", "installCount": 171 },
      { "version": "1.0.0", "status": "deprecated", "publishedAt": "2026-03-01T...", "deprecatedAt": "2026-04-01T...", "installCount": 11 }
    ]
  }
}
installCount includes installs that are pinned to that version (merchant-initiated rollback) plus stragglers with autoUpdate = false.

Publish Version

POST /apps/developer/:appId/versions/:version/publish

Promotes a draft to published. Has three side effects:
  1. The previously-published version (if any) is set to deprecated with deprecatedAt = now().
  2. App.version is synced to the new version.
  3. All installations with autoUpdate = true AND pinnedVersion IS NULL have installedVersion updated to the new version.
curl -X POST "https://api.launchmystore.io/apps/developer/lms_app_xxx/versions/1.2.0/publish" \
  -H "Authorization: Bearer DEVELOPER_JWT"
Response: the full AppVersion row with status: "published" and publishedAt populated. Error codes:
HTTPMessageWhen
400Version is already publishedCalling publish on a version already in published status.
404App not foundCaller doesn’t own this app, or appId doesn’t exist.
404Version X.Y.Z not foundNo AppVersion row matches (appId, version).

Deprecate Version

POST /apps/developer/:appId/versions/:version/deprecate

Manually deprecate a version — useful for emergency pulls when a bug is discovered in a previously-published version. Does not auto-promote another version; installations already running the deprecated version keep running until they are rolled back or the next published version hits them via autoUpdate.
curl -X POST "https://api.launchmystore.io/apps/developer/lms_app_xxx/versions/1.1.0/deprecate" \
  -H "Authorization: Bearer DEVELOPER_JWT"
Sets status = 'deprecated', deprecatedAt = now(), appends a deprecated changelog entry.

Changelog

Every state transition is recorded in AppVersionChangelogs:
action valueWhen fired
createdPOST .../versions
publishedPOST .../versions/:version/publish
deprecatedPOST .../versions/:version/deprecate, or auto-demotion on publish
rolled_backPOST /apps/store/installations/:id/rollback (per-install)
The changelog endpoint is internal — there is no public list endpoint yet. Use the per-version stats and the version list to drive a UI.
The version + changelog endpoints live on the AppVersionController at src/apps/version/app-version.controller.ts. The publish flow’s auto-update fan-out skips any installation with a non-null pinnedVersion — pinning is the merchant’s signal that they do not want automatic updates for this app.