Skip to main content

OAuth 2.0 Authentication

LaunchMyStore uses OAuth 2.0 for secure app authentication. This allows merchants to grant your app specific permissions without sharing their credentials.

Two install paths

Depending on how the merchant reaches your app, one of two OAuth flows runs.

A. Managed install — the merchant clicks Install in our marketplace

The merchant sees the consent screen inside LaunchMyStore’s admin, approves the scopes, and we redirect them straight to your /auth endpoint with a pre-authorized code. You do not call /oauth/authorize in this flow — the consent already happened. See Install handoff (/auth) for the full contract: HMAC verification, exchange semantics, code samples in Node/Python/Ruby.

B. App-initiated OAuth — your app needs additional scopes later

If your app needs to request scopes outside of install (for example a feature that requires elevated permission), redirect the merchant to /oauth/authorize from inside your embedded UI.

Available Scopes

Request only the scopes your app needs. Merchants see all requested scopes during installation.

Store Data

ScopeDescription
read_shopView store information
write_shopModify store settings
read_productsView products and variants
write_productsCreate, update, delete products
read_collectionsView collections
write_collectionsManage collections

Orders & Customers

ScopeDescription
read_ordersView orders and transactions
write_ordersCreate, update, fulfill orders
read_customersView customer data
write_customersCreate, update customers
read_fulfillmentsView fulfillment data
write_fulfillmentsCreate, update fulfillments

Inventory & Discounts

ScopeDescription
read_inventoryView inventory levels
write_inventoryAdjust inventory
read_discountsView discount codes
write_discountsCreate, manage discounts

Metafields

ScopeDescription
read_metafieldsView metafield data
write_metafieldsCreate, update metafields

Content & Files

ScopeDescription
read_filesList and download merchant-uploaded files (reserved — /api/v1/files endpoints not yet bound)
write_filesUpload, replace, delete files (reserved — /api/v1/files endpoints not yet bound)
read_themesRead theme files and settings
write_themesInstall themes, edit theme files, toggle app embeds
read_contentView blogs, articles, pages
write_contentCreate / update / delete blogs, articles, pages
Scopes marked reserved are declared in the OAuth catalog and can be requested by an app today, but the corresponding REST endpoints are not yet exposed under /api/v1/. Request them now if you want forward-compat; the API surface will land before the v1 freeze.

Shipping & Gift Cards

ScopeDescription
read_shippingView shipping zones, methods, and rates
write_shippingCreate / update / delete shipping zones and rates
read_gift_cardsView issued gift cards and balances
write_gift_cardsIssue, refund, or void gift cards

Billing, Analytics, Settings & Marketing

ScopeDescription
read_billingView merchant subscriptions and invoices
write_billingCreate one-time charges and recurring subscription products
read_analyticsQuery the analytics / reports API
read_settingsView store-wide settings (taxes, payments, locale)
write_settingsModify store-wide settings
read_marketingView campaigns, segments, abandoned-cart data
write_marketingCreate / update marketing campaigns

Email Templates

ScopeDescription
read_email_templatesRead transactional email templates registered by your app
write_email_templatesOverride transactional email templates (order confirmation, password reset, etc.) — see Email Templates extension

Authorization Request

Redirect merchants to the authorization URL:
GET https://api.launchmystore.io/oauth/authorize

Parameters

ParameterRequiredDescription
client_idYesYour app’s Client ID
scopeYesComma-separated list of scopes
redirect_uriYesYour callback URL (must match registered URL)
stateRecommendedRandom string to prevent CSRF attacks

Example

const authUrl = new URL('https://api.launchmystore.io/oauth/authorize');
authUrl.searchParams.set('client_id', CLIENT_ID);
authUrl.searchParams.set('scope', 'read_products,write_products,read_orders');
authUrl.searchParams.set('redirect_uri', 'https://my-app.com/auth/callback');
authUrl.searchParams.set('state', generateRandomString());

res.redirect(authUrl.toString());

Token Exchange

After the merchant approves, they’re redirected to your redirect_uri with a code parameter. Exchange this for tokens:
POST https://api.launchmystore.io/oauth/token
Content-Type: application/json

{
  "client_id": "your_client_id",
  "client_secret": "your_client_secret",
  "code": "authorization_code_from_callback",
  "grant_type": "authorization_code",
  "redirect_uri": "https://my-app.com/auth/callback"
}

Response

{
  "access_token": "lms_token_xxxxxxxxxxxxxxxxxxxxxxxx",
  "refresh_token": "lms_refresh_xxxxxxxxxxxxxxxxxxxxxxxx",
  "token_type": "bearer",
  "expires_in": 86400,
  "scope": "read_products write_products read_orders"
}
scope is a space-delimited string (e.g. "read_products write_orders") — split on a space, not a comma. This is the merchant’s granted scopes; persist it as your authorization source (see below). token_type is returned lowercase (bearer).

Token Refresh

Access tokens expire after 24 hours. Use the refresh token to get a new access token:
POST https://api.launchmystore.io/oauth/token
Content-Type: application/json

{
  "client_id": "your_client_id",
  "client_secret": "your_client_secret",
  "refresh_token": "your_refresh_token",
  "grant_type": "refresh_token"
}
Refresh tokens expire after 30 days. If a refresh token expires, the merchant must re-authorize your app.

Making Authenticated Requests

Include the access token in the Authorization header:
const response = await fetch('https://api.launchmystore.io/api/v1/products', {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  }
});

Security Best Practices

Never store tokens in client-side code or version control. Use encrypted database columns or a secrets manager.
Always validate that the state parameter in the callback matches what you sent. This prevents CSRF attacks.
Implement automatic token refresh before making API calls. Check expires_in and refresh proactively.
Only request the permissions your app actually needs. Merchants are more likely to install apps with fewer permissions.