Orbit Commerce
Plugin guides

OAuth scopes

Scopes are the permissions a plugin requests and a merchant grants. They define exactly what your plugin can read and write on a store.

What a scope is

A scope is a single permission string of the form <resource>:<action>. Each scope authorises one kind of operation on one kind of resource — for example, product:read lets your plugin read products, and order:create lets it create orders. Your plugin holds a set of scopes, and every API endpoint requires specific scopes to call it.

Scopes flow through four stages, from declaration to enforcement.

  1. Request — You declare the scopes your plugin needs in its manifest under oauth.scopes. This is part of the plugin definition you create in the partner dashboard.
  2. Consent — When a merchant installs your plugin, they see the requested scopes and consent to them. Installation is how the grant happens.
  3. Grant — The consented set becomes the scopes claim inside every token issued for that install (both session and access tokens carry it).
  4. Enforce — Each API endpoint checks the token's scopes claim. If the required scope is present, the call proceeds; if not, it is rejected.
{
  "oauth": {
    "scopes": ["product:list", "product:read", "order:read", "webhook:create"]
  }
}

The token your plugin uses carries exactly this granted set:

{
  "sub": "<StorePlugin id>",
  "storeId": "<store uuid>",
  "pluginId": "your-plugin-id",
  "scopes": ["product:list", "product:read", "order:read", "webhook:create"],
  "type": "plugin_access"
}

Naming convention

Every scope follows one rule:

<resource>:<action>
  • resource is singular and kebab-caseproduct, order, customer, taxonomy, tracking-script, webhook. Never plural.
  • action is almost always one of five CRUD verbs:
ActionMeaning
listEnumerate many records
readRead a single record
createCreate a record
updateModify a record
deleteRemove a record

So product:list, customer:read, and order:create are all valid.

A small number of scopes use a purpose verb instead, where a CRUD action would be misleading about the side effects: order:fulfill (fulfilling can notify the customer) and email:send. These are listed in the Scope Catalog like every other scope — don't coin new verbs by analogy; if it isn't in the catalog, it won't be granted.

Common mistakes

The two most frequent errors are pluralising the resource and inventing an action verb.

WrongRightWhy
products:readproduct:readResource is singular, not plural
orders:listorder:listResource is singular, not plural
order:writeorder:create / order:updatewrite is not an action — use create or update
product:readonlyproduct:readreadonly is not an action verb

If a scope string does not parse to a known <resource>:<action> pair, it will not grant any access.

Common scopes by resource

The following are frequently used scopes. The complete, authoritative list is the Scope Catalog.

ResourceScopes
productproduct:list, product:read, product:create, product:update
orderorder:list, order:read, order:create, order:fulfill
customercustomer:list, customer:read
taxonomytaxonomy:list, taxonomy:read
webhookwebhook:create, webhook:list, webhook:read, webhook:delete

Webhook subscriptions require both a webhook scope and the topic's own scope. To subscribe to product.* topics you need webhook:create plus product:read. See the webhooks guide for the full topic-to-scope mapping.

Request the minimum

Request only the scopes your plugin actually uses. A smaller scope set is easier for merchants to approve and reduces what is at risk if a token leaks.

  • If you only read products, request product:read (and product:list if you enumerate them) — not product:update.
  • Don't request write scopes (create / update / delete) when your plugin only reads.
  • Add scopes as your plugin grows rather than requesting broad access up front. Note that expanding the requested set means merchants must re-consent on install.

Check granted scopes at runtime

A merchant may not grant every scope you requested, so check what you actually hold before calling a guarded endpoint. The granted set lives in your token's scopes claim.

On your backend, read it from the verified token:

import { OrbitClient } from '@orbitcommerce/sdk'

const { scopes } = await OrbitClient.verifyToken(token)

if (scopes.includes('order:read')) {
  // safe to read orders
}

In the iframe, the claim travels inside the session JWT returned by orbit.getToken(). Decode its payload to inspect scopes — it is a standard JWT, so any base64url/JWT decoder works:

const orbit = new OrbitClient()
await orbit.ready()

const [, payload] = orbit.getToken().split('.')
const { scopes } = JSON.parse(atob(payload)) as { scopes: string[] }

if (scopes.includes('order:read')) {
  const orders = await orbit.query(/* ... */)
} else {
  orbit.toast({ message: 'Order access not granted', type: 'warning' })
}

Use these checks to hide or disable features the merchant has not authorised, rather than letting a call fail at the API.

Enforcement errors

When a guarded endpoint rejects a call, the status code — and, for scope failures, the error body — tells you what went wrong.

StatusMeaningWhat to do
401The token is missing, malformed, or expired — or valid but lacking the required scopeIf the token is missing/expired, re-authenticate (in the iframe, ensure await orbit.ready() has resolved; on the backend, refresh the access token — see authentication). If the body reads Missing required scopes: …, add the scope to your manifest's oauth.scopes and have the merchant re-install/re-consent.
403Subscribing to a webhook topic without the topic's own scope — or the id you referenced belongs to a different storeFor topics: add the topic's scope (e.g. order:read for order.*) to your manifest and re-consent. For cross-store ids: your token is bound to one store; only reference ids that belong to it.

Both a missing/expired token and a missing endpoint scope surface as 401 — read the error body to tell them apart (a scope failure names the missing scope). A 403 is never an endpoint-scope problem: it means a webhook topic-scope failure or a cross-store id.

Reference

  • Scope Catalog — the complete list of available scopes.
  • API Reference — the exact scope required by each endpoint.
  • Authentication — how tokens are issued, refreshed, and verified.
  • Webhooks — topic subscriptions and their required scopes.