Skip to main content
Installation is what links your app to a specific store. Until an installation exists, the client credentials flow rejects the store with 403 App is not installed on this store — so this page is step zero for every integration. There are two ways an installation gets created, and they end in the same place: Both paths work for public and private apps. After either one, you mint per-store tokens with client_credentials exactly the same way.

Prerequisites

Before installing on a store, you need all of the following:
  1. An app with credentials. Created in the developer dashboard — see Creating an App. You need the client_id, and the plaintext client_secret shown once at creation or rotation (op_secret_...).
  2. The app approved. Public apps go through marketplace review; private apps only need review when they request admin-gated scopes. An app still in review cannot be installed.
  3. Access to the target store. For your own account’s stores you have this already. For a merchant’s store, your organization needs an approved collaboration — once the merchant approves, everyone in your org holds collaborator access to that store.
  4. A live redirect URI. The first redirect URI registered on your app receives the authorization code on marketplace installs (see code delivery). It must be a public HTTPS endpoint.
  5. The store ID (a cuid like cms6hqe230006gifyusgheils). We share it when provisioning your stores; it also appears in dashboard API responses for any store you can access.

Path A — Marketplace install

The App Marketplace appears in the dashboard’s left sidebar for users whose role carries marketplace access: account owners, developer-org members, and store collaborators. Approved public apps are listed for every merchant; your private apps appear under the Private tab for your own stores.
  1. Select the store, open App Marketplace, and find your app.
  2. Click Install. A consent dialog lists every requested scope — required scopes are locked on, optional scopes can be unchecked.
  3. On confirm, OrderProtection creates the installation and delivers an authorization code to your server (details below).
Because collaborators get marketplace access, your org can install your own app on a collaborated merchant store through this same UI — no merchant action needed beyond the collaboration approval.

How the authorization code reaches you

On a marketplace install, code delivery is server-to-server — the merchant’s browser never touches your domain. OrderProtection’s backend sends:
Three things to build your callback handler around:
  • You must respond 2xx within 10 seconds. Any other response (or a timeout) makes the whole install fail and roll back — the merchant sees an error and no installation exists. Keep the handler fast: acknowledge first, process async.
  • There is no state parameter on this delivery, and the request is not signed. Treat the callback as a hint, not proof: the code is only trustworthy once you exchange it (the exchange requires your client_secret).
  • The code is single-use and expires in 10 minutes.
You can exchange the code via the authorization code grant, or ignore it and mint client credentials tokens — the installation exists either way.

Path B — API install

For automated onboarding, your backend performs the install directly. The endpoint that creates an installation is:
It is a dashboard-user endpoint: it requires the bearer token of a logged-in OrderProtection user who has access to the target store. It rejects every other credential — op_at_ app access tokens, op_pat_ personal access tokens, embedded session tokens, and store API keys all return 401.

Step 1 — Obtain a user token

Log in programmatically with a dashboard user’s credentials (we recommend a dedicated service user in your org):
data.access_token is the bearer token for the install call. Notes for automation:
  • The token expires after expires_in seconds. Refresh with POST /v1/auth/refresh {"refreshToken": "..."} — it returns a fresh access_token; keep reusing the original refresh token.
  • If the account has MFA enabled, the login response returns {"mfaRequired": true, ...} instead of tokens. Use a service user without MFA, or contact us about the TOTP flow.
  • Store access is evaluated fresh on every request, so a collaboration approved after login is visible to an existing token immediately — no re-login needed.

Step 2 — Install

Rules the request must satisfy:
  • redirectUri must exactly string-match a redirect URI registered on the app — no wildcards, no trailing-slash forgiveness.
  • scopes must include every scope the app marks as required (for most apps, all of them) and nothing the app doesn’t request. Short lists fail with Required scopes cannot be denied; extra scopes fail with Requested scopes exceed application permissions.
  • storeId must be a store the authenticated user can access (via role or approved collaboration).
Unlike the marketplace path, the code comes back in the response body — nothing calls your redirect URI. Exchange it, or skip straight to client credentials. The call is idempotent-friendly: re-running it against a store that already has the app installed does not error — it refreshes the installation and re-syncs the scope grants.

Mint tokens

Once the installation exists (either path), mint one token per store:
client_secret is the plaintext value shown once at creation or rotation — see Authentication for token lifetimes and refresh.

Uninstalling

Merchants (and your org, on collaborated or own stores) uninstall from App Marketplace → Installed. The API equivalent, with the same dashboard-user auth as the install call:
On uninstall, all of the installation’s access and refresh tokens are revoked immediately, and registered app webhooks for the store are removed. To be notified of uninstalls, add the app/uninstalled topic to your app’s webhook settings — it is delivered directly to your webhook URL for every installation, with the store and installation ids in the body. See Webhooks. As a fallback, handle 401 responses gracefully or poll GET /v1/developer/apps/{appId}/installations (dashboard-user auth) and diff the list. Reinstalling after an uninstall works through either path with no special handling — the installation is recreated cleanly and new tokens mint as normal. This makes install → uninstall → install cycles safe for testing.

Common errors