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
- 1The merchant clicks Install in the App Store. Sellify opens your App URL with
store,shop,timestampandhmac. - 2Your app checks the
hmacand redirects tohttps://admin-sellifyhq.vercel.app/oauth/authorizewithclient_id,scope(comma separated),redirect_uri(one of your allowed URLs), a randomstateandstore. - 3The merchant sees what your app can access and clicks Install app (or Cancel →
error=access_denied). - 4Sellify redirects to your
redirect_uriwithcode,store,shop,state,timestampandhmac. Checkstateandhmac. - 5Your server exchanges the code (valid 10 minutes, once) for an access token.
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=mystoreVerifying 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.
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 -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.