Skip to main content

Overview

Staff manage a store through the dashboard and the Admin API. What each person can do is decided by the roles they hold. Two things about that shape matter: A role belongs to what it governs. Every role names its owner — a Store for back-office staff, a Seller for a marketplace seller’s own team. The owner is both who the role belongs to and who it applies to, so a role on a Store is a staff role by construction. Assigning someone a role therefore grants access to that owner and nothing else, which is what keeps one store’s staff out of another’s data. Because roles are scoped to their owner, two stores can each define a “Manager” without colliding. A role carries its permissions directly. The role holds a plain list of permission keys, so what a role can do is visible on the role itself rather than assembled from something else at runtime.

Roles and permissions

A permission key is a verb and a resource — read_orders, write_products. Roles hold a list of them:
Every grantable key is discoverable, so a permission picker never needs a hardcoded list:
Keys are grouped so they can be presented sensibly — orders, catalog, marketing, customers, settings, access and analytics.
The same vocabulary gates API keys. A secret key’s scopes come from this catalog too, so “what may this integration do” and “what may this person do” are described the same way — there is no second permission system to keep in step.

The admin role

Each store gets one protected admin role meaning everything in this store. It can’t be renamed, edited or deleted, and it isn’t shared between stores — each owner has its own. A role is deletable only when nothing depends on it: staff assignments and pending invitations have to be moved first, so nobody silently loses access.
Roles are pure data. They’re created through the dashboard, the Admin API, or seeds — there’s no code-level role definition to keep in sync. For record-level rules beyond what keys express, see Customize Permissions.

Creating Admin Users

Use the Spree CLI to create admin users:
Spree CLI
The CLI will prompt you for the email and password. You can also pass them directly:
Spree CLI
The created user gets the admin role on the default store.

Authentication & identity providers

Staff authenticate against the Admin API, which issues a short-lived JWT used for subsequent requests. How a staff member proves who they are is pluggable — Spree ships email/password out of the box, and you can plug in any external identity provider (Okta, Microsoft Entra ID, Google Workspace, a custom JWT issuer, SAML, etc.) without changing the rest of the API.

How admin login works

A staff member logs in via the POST /api/v3/admin/auth/login endpoint (see Admin API Authentication). The request’s provider field selects a registered authentication strategy. When provider is omitted it defaults to email, the built-in email/password strategy (which you can also disable and restrict the admin to your preferred SSO provider). Whichever strategy authenticates the request, Spree issues the same credentials in return, so downstream code and the admin SPA never need to know which provider was used:
  • a JWT access token (aud: admin_api), short-lived by design;
  • a rotating refresh token, set as an HttpOnly cookie scoped to /api/v3/admin/auth (the admin flow keeps it out of the response body — see Admin Auth & Cookie Refresh).
The same strategy registry exists on the customer side, so storefront sign-in is pluggable the same way — the only difference is the user class and that the Store API returns the refresh token in the body rather than a cookie.

Registering a custom identity provider

Follow the Custom API Authentication how-to for details how to create a custom authentication strategy and register it with the admin API. Once registered, you can use it from the admin SPA or any API client by passing its name in the provider field of the login request.

Inviting Admin Users

You can invite new admins through the Admin Panel or programmatically. Via Admin Panel:
  1. Navigate to Settings → Users
  2. Click Invite User
  3. Enter the email address and select a role
  4. Click Send Invitation
Programmatically: Using the Admin SDK, call client.invitations.create:
Admin SDK
Creating an invitation publishes invitation.created, which sends the email. Either way, the invitee receives an email with an invitation link. If they already have an account, they log in to accept. Otherwise, they create an account first.

Invitation Details

Invitation Events

The invitation system publishes events you can subscribe to:

Permissions

A role holds flat permission keys from one catalog (read_orders, write_products, …) — the same vocabulary as secret API key scopes. Every Admin API request checks the staff member’s keys on the current store against the endpoint’s read_<resource> / write_<resource> key and returns 403 with details.required_permission when it is missing. Staff endpoints (/admin_users, /invitations, /roles) need read_staff / write_staff. Permissions apply to staff only. Customers never hold roles: the Store API authorizes them by ownership-scoped queries plus Spree::Storefront::AccessPolicy. See the Customize Permissions guide for details on creating custom roles and registering your own permission keys.