Skip to main content
GET
App Installations

App Installations

An installation 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 (or staff-admin) JWT auth and scope by the caller’s storeId.

Endpoints

Installation object

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.
Response:

Install App

POST /apps/store/install/:appId

Direct install path used by the merchant admin “Install” button. The installation itself is created immediately (no consent screen — the merchant is already authenticated as themselves), but apps with an external appUrl do still receive the OAuth code → token handoff: the response includes an appLaunchUrl of the form
The admin navigates the merchant’s browser there after the install succeeds. Your /auth endpoint should verify the hmac (HMAC-SHA256 of the query string minus the hmac field, keyed with your client secret), then exchange the code at POST /apps/oauth/token with grant_type=authorization_code to obtain your access + refresh tokens. The code is single-use and expires after 10 minutes. Re-installing an app re-issues a fresh appLaunchUrl, so an app that lost its tokens can recover by uninstall → reinstall. Apps with a platform-local appUrl (first-party embeds) get appLaunchUrl: null and skip this step.
Path parameter appId is the app’s UUID, 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 matches on name (case-insensitive), not handle, so searching for foundry-reviews will not find an app named “Foundry Reviews”. Search by the first word of the name instead.
On success, the installation is created with status = 'active' and the app’s storefront extensions (blocks/snippets/assets) are deployed under extensions/{domainSlug}/{appHandle}/ so the storefront theme can render them. Error codes:
Paid apps without a free trial don’t create the installation row immediately: the install call returns { requiresPayment: true, checkoutUrl, sessionId } and the row is created when Stripe confirms payment. The /auth handoff for these installs fires after checkout completes — the admin redeems it via GET /apps/store/launch-url/:appId when the merchant lands back on ?billing=success.

Uninstall App

POST /apps/store/uninstall/:appId

Atomically cleans up everything related to this installation:
  1. Cancels the Stripe subscription (stripeSubscriptionId), if any.
  2. Deletes the app’s webhook subscriptions, admin-extension registry rows, fulfillment services, sales channels, app-owned metafield definitions, and automation flows for this store.
  3. Deletes the installation row (this also clears the OAuth token pair).
  4. After commit: removes the merchant-scoped extension files staged for this app on the storefront, and wipes compiled function artefacts once the app’s last installation is gone.
  5. Dispatches the app/uninstalled webhook.
All server-side cleanup runs in a single atomic transaction — a partial failure rolls back to the pre-uninstall state. Stripe cancellation runs first (remote idempotent call) so a successful Stripe cancel followed by a DB rollback can be safely re-driven on retry.
Response:
There is no data field on the uninstall response.

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.

Status Reference

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 — and the app/uninstalled webhook payload carries only { appId } (no reason field). If you want exit feedback, collect it in your own off-boarding flow when the webhook arrives.
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.