> ## 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.

# Authentication

> How to authenticate requests to the Store API

The Store API uses three authentication mechanisms depending on the use case: **API keys** for all requests, **JWT tokens** for authenticated customers, and **order tokens** for guest checkout.

## API Key (Required)

Every request to the Store API requires a **publishable API key**. This key identifies your storefront and is safe to use in client-side code.

Pass the key via the `X-Spree-Api-Key` header:

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  import { createClient } from '@spree/sdk'

  const client = createClient({
    baseUrl: 'http://localhost:3000',
    publishableKey: 'pk_xxx',
  })

  // The SDK automatically sends the publishable key with every request
  const products = await client.products.list()
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X GET 'http://localhost:3000/api/v3/store/products' \
    -H 'X-Spree-Api-Key: pk_xxx'
  ```
</CodeGroup>

Publishable API keys are prefixed with `pk_`. You can create them in the Spree Admin under **Settings > API Keys** or via the Spree CLI:

```bash theme={"theme":"night-owl"}
spree api-key create       # Create a new API key
spree api-key list         # List existing API keys
```

<Warning>
  If you omit the API key, the API returns a `401 Unauthorized` error:

  ```json theme={"theme":"night-owl"}
  {
    "error": {
      "code": "invalid_token",
      "message": "Valid API key required"
    }
  }
  ```
</Warning>

## JWT Token (Authenticated Customer)

For actions that require a logged-in customer (viewing orders, managing addresses, saved payment methods), use a **JWT bearer token** in addition to the API key.

### Login

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  // Login to get a JWT token
  const { token, user } = await client.auth.login({
    email: 'customer@example.com',
    password: 'password123',
  })

  // Use the token for authenticated requests
  const orders = await client.customer.orders.list({}, { token })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # Login
  curl -X POST 'http://localhost:3000/api/v3/store/auth/login' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Content-Type: application/json' \
    -d '{"email": "customer@example.com", "password": "password123"}'

  # Use the returned token for authenticated requests
  curl -X GET 'http://localhost:3000/api/v3/store/orders' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Authorization: Bearer <jwt_token>'
  ```
</CodeGroup>

### Register

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  const { token, user } = await client.customers.create({
    email: 'new@example.com',
    password: 'password123',
    password_confirmation: 'password123',
    first_name: 'John',
    last_name: 'Doe',
  })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X POST 'http://localhost:3000/api/v3/store/customers' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Content-Type: application/json' \
    -d '{
      "email": "new@example.com",
      "password": "password123",
      "password_confirmation": "password123",
      "first_name": "John",
      "last_name": "Doe"
    }'
  ```
</CodeGroup>

### Token Refresh

JWT tokens expire after 1 hour by default. Use the refresh endpoint to get a new token:

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

  ```bash cURL theme={"theme":"night-owl"}
  curl -X POST 'http://localhost:3000/api/v3/store/auth/refresh' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Authorization: Bearer <current_jwt_token>'
  ```
</CodeGroup>

## Order Token (Guest Checkout)

For guest checkout flows, use the **order token** returned when creating a cart. This allows unauthenticated users to manage their cart and complete checkout.

Pass the token via the `x-spree-token` header:

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  // Create a cart (guest)
  const cart = await client.carts.create()

  // Use spreeToken for all guest cart operations
  const options = { spreeToken: cart.token }

  // Add items
  await client.carts.items.create(cart.id, {
    variant_id: 'variant_abc123',
    quantity: 1,
  }, options)
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # Create a cart
  curl -X POST 'http://localhost:3000/api/v3/store/carts' \
    -H 'X-Spree-Api-Key: pk_xxx'

  # Use the returned token for cart operations
  curl -X POST 'http://localhost:3000/api/v3/store/carts/cart_xxx/items' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'X-Spree-Token: <order_token>' \
    -H 'Content-Type: application/json' \
    -d '{"variant_id": "variant_abc123", "quantity": 1}'
  ```
</CodeGroup>

### Associating a Guest Cart

After a guest user logs in, you can associate their guest cart with their account:

<CodeGroup>
  ```typescript SDK theme={"theme":"night-owl"}
  await client.carts.associate(cart.id, {
    token: jwtToken,
    spreeToken: cart.token,
  })
  ```

  ```bash cURL theme={"theme":"night-owl"}
  curl -X PATCH 'http://localhost:3000/api/v3/store/carts/cart_xxx/associate' \
    -H 'X-Spree-Api-Key: pk_xxx' \
    -H 'Authorization: Bearer <jwt_token>' \
    -H 'X-Spree-Token: <order_token>'
  ```
</CodeGroup>

## Authentication Summary

| Method      | Header                          | Use Case                       |
| ----------- | ------------------------------- | ------------------------------ |
| API Key     | `X-Spree-Api-Key: pk_xxx`       | All requests (required)        |
| JWT Token   | `Authorization: Bearer <token>` | Authenticated customer actions |
| Order Token | `X-Spree-Token: <token>`        | Guest cart and checkout        |
