App Installations
Apps
App Installations
List, configure, and uninstall app installations on a merchant store
GET
App Installations
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 Installations
AnAppInstallation row represents one app installed on one merchant
store. It carries the OAuth token pair, granted scopes, billing state,
and per-merchant configuration. This page documents the merchant-facing
endpoints — for OAuth grant flow, see
Authorize; for per-install rollback,
see Rollback.
All endpoints in this group require merchant JWT auth
(UserRole.MERCHANT or UserRole.STAFF_ADMIN) and scope by the
caller’s storeId.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /apps/store/installed | List all installations for the caller’s store. |
POST | /apps/store/install/:appId | Install an app (merchant-initiated, no OAuth flow). |
POST | /apps/store/uninstall/:appId | Uninstall an app (cascade cleanup + webhook). |
PATCH | /apps/store/:installationId/config | Update the install’s config blob. |
GET | /apps/installations/:installationId/settings | Read merchant-configured app settings. |
PUT | /apps/installations/:installationId/settings | Replace merchant-configured app settings. |
Data Model: AppInstallation
UNIQUE (appId, storeId) — a single app can have at most one
installation per merchant.
List Installed Apps
GET /apps/store/installed
Returns every installation for the caller’s store, excluding rows in
pending-uninstall. Each row is joined with the parent App record so
the merchant admin can render name/icon/description without a second
fetch.
Install App
POST /apps/store/install/:appId
Direct install path used by the merchant admin “Install” button. Does
not go through the OAuth code → token exchange — the merchant is
already authenticated as themselves, and the platform issues an
installation token bound to their storeId directly.
Path parameter
appId is the UUID returned by findByPk, not the
app handle. Looking up an app by handle via the marketplace endpoints
returns both appId and handle — pass the appId here. The
marketplace ?search= filter does ILIKE matching on name, not
handle, so searching for foundry-reviews will not find an app named
“Foundry Reviews”. Search by the first word of the name instead.status = 'active'
and the app’s storefront extensions (blocks/snippets/assets) are copied
to disk under public/extensions/{domainSlug}/{appHandle}/ so the
storefront theme can render them.
Error codes:
| HTTP | Message | When |
|---|---|---|
404 | App not found | appId doesn’t exist. |
400 | App is not published | App in draft / pending-review / rejected. |
409 | App already installed | An active installation already exists for (appId, storeId). |
409 | Per-shop function limit exceeded for <type>: max <N> | Function caps prevent a new active install. |
Uninstall App
POST /apps/store/uninstall/:appId
Atomically cleans up everything related to this installation:
- Cancels the Stripe subscription (
stripeSubscriptionId), if any. - Deletes the
AppInstallationrow. - Deletes related
AppWebhook,AppBillingTransaction,GdprRequest.appAcknowledgments, function logs, etc. - Removes extension files from
public/extensions/{domainSlug}/{appHandle}/. - Dispatches the
app/uninstalledwebhook to the app’swebhookCallbackUrl.
| HTTP | Message | When |
|---|---|---|
404 | Installation not found | No active install for (appId, storeId). |
500 | (generic) | DB transaction rolled back; safe to retry. |
Update Installation Config
PATCH /apps/store/:installationId/config
Used by the merchant admin for per-install settings that the app developer
defined as merchant-editable (e.g. block enable/disable toggles, embed
defaults). Distinct from the settings blob — config is more raw and
typically driven by the app’s installation manifest.
Settings
GET /apps/installations/:installationId/settings
Returns the merchant-editable settings blob.
PUT /apps/installations/:installationId/settings
Replaces the settings blob entirely. There is no PATCH-merge variant —
the caller is expected to send the full settings object every time.
| HTTP | Message | When |
|---|---|---|
404 | Installation not found | (installationId, storeId) not matched. |
400 | (validation) | settings not an object. |
Status Reference
status | Visible to merchant admin | Tokens valid | Extensions on storefront |
|---|---|---|---|
active | Yes | Yes (until expiry) | Yes |
disabled | Yes (greyed out) | No (validateToken returns null) | No |
pending-uninstall | Hidden from getInstalledApps | No | Removed |
disabled is set by staff admin when an app has been flagged but not
fully uninstalled (e.g. payment past-due grace period, abuse review).
The OAuth validateToken path short-circuits on any non-active
status, so a disabled install’s API calls 401 immediately even if the
access token hasn’t expired.
Uninstall reasons
The platform records an uninstall reason only when the merchant provides one via the admin UI confirmation dialog. There is currently no REST surface to read uninstall reasons after the fact — the row is deleted, not soft-deleted. Developers should subscribe to theapp/uninstalled webhook to capture the reason in their own systems at
the moment of uninstall.
Per-installation analytics (events, function execution counts, billing
transactions) are queryable through the developer dashboard endpoints
under
/apps/developer/:appId/.... See
Versions for the per-version install
breakdown and
Webhook Delivery Logs for the
per-installation webhook history.