> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Customers

> Customer accounts — registration, authentication, profiles, and guest checkout

## Overview

Customers interact with your store through the Store API. They can register, log in, manage their profile, and view order history.

```mermaid theme={"theme":"night-owl"}
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
    }
```

## Registration

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  const { token, user } = await client.customers.create({
    email: 'john@example.com',
    password: 'password123',
    password_confirmation: 'password123',
    first_name: 'John',
    last_name: 'Doe',
  })
  // token => JWT token for subsequent authenticated requests
  // user => { id: "usr_xxx", email: "john@example.com", first_name: "John", ... }
  ```

  ```bash cURL theme={"theme":"night-owl"}
  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": "john@example.com",
      "password": "password123",
      "password_confirmation": "password123",
      "first_name": "John",
      "last_name": "Doe"
    }'
  ```
</CodeGroup>

## Login

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  const { token, user } = await client.auth.login({
    email: 'john@example.com',
    password: 'password123',
  })
  // Use the token for authenticated requests
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X POST 'https://api.mystore.com/api/v3/store/auth/login' \
    -H 'Authorization: Bearer pk_xxx' \
    -H 'Content-Type: application/json' \
    -d '{
      "email": "john@example.com",
      "password": "password123"
    }'
  ```
</CodeGroup>

The response includes a JWT `token` and a `user` object. Pass the token in subsequent requests via the `Authorization: Bearer <token>` header.

## Token Refresh

Refresh an expiring token to keep the session alive:

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  const { token } = await client.auth.refresh({
    token: existingToken,
  })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X POST 'https://api.mystore.com/api/v3/store/auth/refresh' \
    -H 'Authorization: Bearer <jwt_token>'
  ```
</CodeGroup>

## Password Reset

Password reset is a two-step flow. First, request a reset email. Then, use the token from the email to set a new password.

### Step 1: Request Reset

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  await client.customer.passwordResets.create({
    email: 'john@example.com',
    redirect_url: 'https://myshop.com/reset-password',
  })
  // Always returns { message: "..." } — even if the email doesn't exist
  // This prevents email enumeration
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X POST 'https://api.mystore.com/api/v3/store/customer/password_resets' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Content-Type: application/json' \
    -d '{
      "email": "john@example.com",
      "redirect_url": "https://myshop.com/reset-password"
    }'
  ```
</CodeGroup>

The optional `redirect_url` parameter specifies where the password reset link in the email should point to. The token will be appended as a query parameter (e.g., `https://myshop.com/reset-password?token=...`). If the store has [Allowed Origins](/developer/core-concepts/allowed-origins) configured, the `redirect_url` must match one of them.

This fires a `customer.password_reset_requested` event with the reset token in the payload. If you're using the `spree_emails` package, the email is sent automatically. Otherwise, subscribe to this event to send the reset email yourself (see [Events](/developer/core-concepts/events)).

### Step 2: Reset Password

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  const { token, user } = await client.customer.passwordResets.update(
    'reset-token-from-email',
    {
      password: 'newsecurepassword',
      password_confirmation: 'newsecurepassword',
    }
  )
  // Returns JWT token + user (auto-login)
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X PATCH 'https://api.mystore.com/api/v3/store/customer/password_resets/RESET_TOKEN' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Content-Type: application/json' \
    -d '{
      "password": "newsecurepassword",
      "password_confirmation": "newsecurepassword"
    }'
  ```
</CodeGroup>

On success, the user is automatically logged in and a JWT token is returned. The reset token expires after 15 minutes (configurable via `Spree::Config.customer_password_reset_expires_in`) and is single-use (changing the password invalidates it).

## Customer Profile

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  // Get current customer
  const customer = await client.customer.get()
  // {
  //   id: "usr_xxx",
  //   email: "john@example.com",
  //   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,
  })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # 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 }'
  ```
</CodeGroup>

## Customer Resources

Authenticated customers have access to these resources:

| Resource                                                                  | Description                                           |
| ------------------------------------------------------------------------- | ----------------------------------------------------- |
| [**Addresses**](/developer/core-concepts/addresses#customer-address-book) | Billing and shipping addresses with default selection |
| [**Orders**](/developer/core-concepts/orders#order-history)               | 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                                   |

## Guest Checkout

Customers don't need to register to purchase. Guest checkout uses an order token (`X-Spree-Token`) to identify the cart. See [Orders — Cart](/developer/core-concepts/orders#cart) for details.

## Related Documentation

* [Addresses](/developer/core-concepts/addresses) — Customer address management
* [Orders](/developer/core-concepts/orders) — Order history and checkout
* [Authentication](/developer/customization/authentication) — Custom authentication setup
* [Staff & Roles](/developer/core-concepts/staff-roles) — Admin users and permissions
