Scopes reference
Every OAuth scope, the implication hierarchy, and how grants are computed.
Scopes are plain strings stored on access tokens as abilities. The same vocabulary is used for store member RBAC and OAuth grants, so a token's power reads exactly like a team member's permissions.
Platform scopes
| Scope | Grants |
|---|---|
auth | Identity only — "Sign in with Feeef". Read the user's profile, nothing else. Default when an app registered no scopes. |
apps | Developer access to per-user app data (/apps/:id/user-data/users/:userId) |
* | Everything. The consent screen shows an elevated warning; request only for trusted first-party tooling. |
Store scopes
| Scope | Grants |
|---|---|
store | Full store access — implies every store-level scope below |
store.read | Read store profile and settings |
store.settings | Update store settings, delete store |
store.integrations | Manage integrations & webhooks; also implies finance* and inventory* |
store.members | Manage team members and their scopes |
Commerce scopes
Each parent implies its .read child.
| Scope | Resource |
|---|---|
orders / orders.read | Orders — create, update, status changes / read-only |
products / products.read | Products and variants |
categories / categories.read | Categories |
shipping_prices / shipping_prices.read | Shipping price matrices |
finance / finance.read | Financial accounts, entries, analytics (Pro) |
inventory / inventory.read | Warehouses, stock, reservations (Pro) |
Content scopes
| Scope | Resource |
|---|---|
pages / pages.read | Store pages |
product_landing_pages / product_landing_pages.read | Landing pages |
template_components / template_components.read | Custom template components |
store_templates / store_templates.read | Store templates |
Hierarchy rules
- A parent implies its
.readchild:orders⇒orders.read. storeimplies allstore.*scopes.store.integrationsadditionally impliesfinance,finance.read,inventory,inventory.read(integration-gated modules).*implies everything.
Checks are hierarchy-aware: a token with orders passes an orders.read requirement.
How grants are computed
The single source of truth is computeGrantedScopes — used for both the consent display and
the token's abilities:
scopeparam present → grant the requested scopes that the app's registration allows (hierarchy-aware). If the intersection is empty →invalid_scopeerror. Never a silent fallback.- No
scopeparam → grant the app's registered scopes. An app registered with*grants['*']. An app with no registered scopes grants['auth']— never full access.
Enforcement
Enforcement is rolling out incrementally. Currently enforced routes include:
| Route | Required scope |
|---|---|
stores/:id/integrations*, webhooks | store.integrations |
PUT/PATCH /stores/:id (settings) | store.settings (store.integrations for integrations-only patches) |
DELETE /stores/:id | store.settings |
| Member add/remove | store.members |
GET|PUT /apps/:id/user-data/users/:userId | apps + token bound to the app |
Failing a check returns 403:
{ "error": "insufficient_scope", "requiredScope": "store.integrations" }with a WWW-Authenticate: Bearer ... scope="store.integrations" header (RFC 6750).
Request the minimum scopes your integration needs. Users see the list at consent, and narrower requests convert better. You can always re-authorize with broader scopes later.