Getting started

Public apps & OAuth

Public apps install on any Sellify store with OAuth 2.0 and can be listed in the App Store. Create one in the Partner dashboard.

An install is just like a custom app on that store: the token is an Admin API token (sfat_…) limited to the scopes the merchant approved, and your app can subscribe to webhooks with it.

Install flow

  1. 1
    The merchant clicks Install in the App Store. Sellify opens your App URL with store, shop, timestamp and hmac.
  2. 2
    Your app checks the hmac and redirects to https://admin-sellifyhq.vercel.app/oauth/authorize with client_id, scope (comma separated), redirect_uri (one of your allowed URLs), a random state and store.
  3. 3
    The merchant sees what your app can access and clicks Install app (or Cancel → error=access_denied).
  4. 4
    Sellify redirects to your redirect_uri with code, store, shop, state, timestamp and hmac. Check state and hmac.
  5. 5
    Your server exchanges the code (valid 10 minutes, once) for an access token.
HTTP
GET https://admin-sellifyhq.vercel.app/oauth/authorize?client_id=YOUR_CLIENT_ID&scope=read_products,read_orders&redirect_uri=https://myapp.com/auth/callback&state=RANDOM&store=mystore

Verifying requests from Sellify

Sort the query parameters except hmac, join them as key=value with &, and compare the hex HMAC-SHA256 (keyed with your client secret) in constant time. Reject timestamps older than a few minutes.

JavaScript
import crypto from "node:crypto";

function verifySellifyQuery(query, clientSecret) {
  const { hmac, ...rest } = query;
  const message = Object.keys(rest).sort().map((k) => `${k}=${rest[k]}`).join("&");
  const digest = crypto.createHmac("sha256", clientSecret).update(message).digest("hex");
  return hmac?.length === digest.length && crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(digest))
    && Math.abs(Date.now() / 1000 - Number(rest.timestamp)) < 300;
}

Token exchange

cURL
curl -X POST https://admin-sellifyhq.vercel.app/api/oauth/access_token \
  -H "Content-Type: application/json" \
  -d '{"client_id":"…","client_secret":"…","code":"…"}'

# → {"access_token":"sfat_…","scope":"read_products,read_orders"}

Store the token per store, encrypted. Errors: 401 invalid_client (wrong credentials) and 400 invalid_grant (code expired, already used or for another app). Installing again — for example to ask for more scopes — issues a new token and revokes the old one.

Uninstalls

When a merchant uninstalls your app its token stops working immediately and its webhook subscriptions are deleted. If you set an app/uninstalled webhook URL, Sellify POSTs { store, shop_domain, uninstalled_at } there, signed in X-Sellify-Hmac-Sha256 with your client secret (base64, like other webhooks).

App Store listing

Tick List in the Sellify App Store once your app has an App URL, a redirection URL, a tagline and a support email. That submits it for review: Sellify checks the listing, the scopes and that the app works, then approves it or asks for changes (you get an email either way). Approved apps appear in the App Store.

Until it's approved, an app can still be installed with your authorize link on up to 10 stores, for testing. Changing the name, tagline, description, category, pricing, support email, URLs or scopes of an approved app sends it back to review; cosmetic changes such as the color don't.

Customer personal data

Without the read_customer_pii scope, orders, customers and order webhooks come with names, emails, phone numbers and street addresses set to null; city, state, PIN code and country stay. Public apps can request read_customer_pii only after Sellify approves it during review — explain why your app needs it in the description. Merchants' own custom apps can choose it freely.

Suspension

Sellify can suspend an app that breaks the developer terms or puts merchants at risk. Suspension stops every install's token (APP_SUSPENDED, HTTP 403), stops webhooks and blocks new installs until the app is reinstated.

Ask only for the scopes you use. Merchants see every scope on the install screen, and apps that over-ask get uninstalled.