docs/api-reference/store-api/authentication.mdx
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.
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:
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()
curl -X GET 'http://localhost:3000/api/v3/store/products' \
-H 'X-Spree-Api-Key: pk_xxx'
Publishable API keys are prefixed with pk_. You can create them in the Spree Admin under Settings > API Keys or via the Spree CLI:
spree api-key create # Create a new API key
spree api-key list # List existing API keys
{
"error": {
"code": "invalid_token",
"message": "Valid API key required"
}
}
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 to get a JWT token
const { token, user } = await client.auth.login({
email: '[email protected]',
password: 'password123',
})
// Use the token for authenticated requests
const orders = await client.customer.orders.list({}, { token })
# 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": "[email protected]", "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>'
const { token, user } = await client.customers.create({
email: '[email protected]',
password: 'password123',
password_confirmation: 'password123',
first_name: 'John',
last_name: 'Doe',
})
curl -X POST 'http://localhost:3000/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"
}'
JWT tokens expire after 1 hour by default. Use the refresh endpoint to get a new token:
<CodeGroup>const { token } = await client.auth.refresh({ token: currentToken })
curl -X POST 'http://localhost:3000/api/v3/store/auth/refresh' \
-H 'X-Spree-Api-Key: pk_xxx' \
-H 'Authorization: Bearer <current_jwt_token>'
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:
// 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)
# 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}'
After a guest user logs in, you can associate their guest cart with their account:
<CodeGroup>await client.carts.associate(cart.id, {
token: jwtToken,
spreeToken: cart.token,
})
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>'
| 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 |