docs/developer/core-concepts/users.mdx
Spree has two separate user types:
| User type | Class | Default |
|---|---|---|
| Customers | Spree.user_class | Spree::User |
| Admins | Spree.admin_user_class | Spree::AdminUser |
Customers interact with your store through the Store API. They can register, log in, manage their profile, and view order history.
erDiagram
Customer ||--o{ Order : "places"
Customer ||--o{ Address : "has many"
Customer ||--o{ Wishlist : "has many"
Customer ||--o{ StoreCredit : "has many"
Customer ||--o{ PaymentSource : "has many"
Customer {
string id
string email
string first_name
string last_name
}
Order {
string number
string state
}
Address {
string firstname
string lastname
string address1
string city
}
Wishlist {
string name
boolean is_default
}
const { token, user } = await client.customers.create({
email: '[email protected]',
password: 'password123',
password_confirmation: 'password123',
first_name: 'John',
last_name: 'Doe',
})
// token => JWT token for subsequent authenticated requests
// user => { id: "usr_xxx", email: "[email protected]", first_name: "John", ... }
curl -X POST 'https://api.mystore.com/api/v3/store/customers' \
-H 'X-Spree-Api-Key: pk_xxx' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"password": "password123",
"password_confirmation": "password123",
"first_name": "John",
"last_name": "Doe"
}'
const { token, user } = await client.auth.login({
email: '[email protected]',
password: 'password123',
})
// Use the token for authenticated requests
curl -X POST 'https://api.mystore.com/api/v3/store/auth/login' \
-H 'Authorization: Bearer pk_xxx' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"password": "password123"
}'
The response includes a JWT token and a user object. Pass the token in subsequent requests via the Authorization: Bearer <token> header.
Refresh an expiring token to keep the session alive:
<CodeGroup>const { token } = await client.auth.refresh({
token: existingToken,
})
curl -X POST 'https://api.mystore.com/api/v3/store/auth/refresh' \
-H 'Authorization: Bearer <jwt_token>'
// Get current customer
const customer = await client.customer.get()
// {
// id: "usr_xxx",
// email: "[email protected]",
// first_name: "John",
// last_name: "Doe",
// default_shipping_address: { ... },
// default_billing_address: { ... },
// addresses: [{ ... }, { ... }],
// }
// Update profile
const updated = await client.customer.update({
first_name: 'Jonathan',
accepts_email_marketing: true,
})
# Get current customer
curl 'https://api.mystore.com/api/v3/store/customer' \
-H 'Authorization: Bearer <jwt_token>'
# Update profile
curl -X PATCH 'https://api.mystore.com/api/v3/store/customer' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{ "first_name": "Jonathan", "accepts_email_marketing": true }'
Authenticated customers have access to these resources:
| Resource | Description |
|---|---|
| Addresses | Billing and shipping addresses with default selection |
| Orders | Past order history |
| Credit Cards | Saved credit cards for checkout |
| Payment Sources | Other saved payment methods (PayPal, Klarna, etc.) |
| Store Credits | Balance assigned by the store, usable at checkout |
| Gift Cards | Gift cards owned by or assigned to the customer |
| Wishlists | Saved product lists |
Customers don't need to register to purchase. Guest checkout uses an order token (X-Spree-Token) to identify the cart. See Orders — Cart for details.
Admin users manage the store via the Admin Panel. They have roles that control what they can access.
erDiagram
AdminUser ||--o{ RoleUser : "has many"
RoleUser }o--|| Role : "belongs to"
RoleUser }o--|| Store : "scoped to"
AdminUser ||--o{ Invitation : "invites"
AdminUser {
string id
string email
}
RoleUser {
string role_id
string resource_type
string resource_id
}
Role {
string name
}
Invitation {
string email
string status
string token
datetime expires_at
}
Admin users can have different roles that control their permissions:
| Role | Description |
|---|---|
admin | Full access to all Admin Panel features |
Use the Spree CLI to create admin users:
spree user create
The CLI will prompt you for the email and password. You can also pass them directly:
spree user create --email [email protected] --password secret123
The created user gets the admin role on the default store.
You can invite new admins through the Admin Panel or programmatically.
Via Admin Panel:
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.
flowchart TB
A[Admin creates invitation] --> B[Invitation email sent]
B --> C[Invitee clicks link]
C --> D{Has account?}
D -->|Yes| E[Log in]
D -->|No| F[Create account]
E --> G[Accept invitation]
F --> G
G --> H[Role assigned to store]
| Attribute | Description |
|---|---|
email | Invitee's email address |
token | Secure token for the invitation link |
status | pending or accepted |
expires_at | Expiration date (default: 2 weeks) |
resource | The store being granted access to |
role | The role to assign upon acceptance |
The invitation system publishes events you can subscribe to:
| Event | Description |
|---|---|
invitation.created | Invitation was created (triggers email) |
invitation.accepted | Invitation was accepted and role assigned |
invitation.resent | Invitation was resent to the invitee |
Spree uses CanCanCan for authorization. Permissions apply to both customers (Store API access) and admins (Admin Panel access).
See the Customize Permissions guide for details on creating custom roles and permission sets.