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

# Slugs

> How Spree generates SEO-friendly URL slugs for products, categories, and stores, and how to look up resources by slug or ID via the API.

## Overview

Spree generates SEO-friendly URL slugs for resources like products, categories, and stores. Instead of accessing resources by ID, you can use clean, readable URLs based on resource names.

The Store API accepts slugs or prefixed IDs interchangeably for resource lookups. The Admin API resolves resources by prefixed ID only — slugs are not accepted.

<CodeGroup>
  ```typescript Store SDK theme={"theme":"night-owl"}
  // Both work — slug or ID
  const product = await client.products.get('spree-tote')
  const product = await client.products.get('prod_86Rf07xd4z')

  // Categories use permalink slugs
  const category = await client.categories.get('clothing/shirts')
  ```

  ```typescript Admin SDK theme={"theme":"night-owl"}
  // Admin SDK accepts prefixed IDs only — not slugs
  const product = await adminClient.products.get('prod_86Rf07xd4z')
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # By slug
  curl 'https://api.mystore.com/api/v3/store/products/spree-tote' \
    -H 'X-Spree-API-Key: pk_xxx'

  # By ID
  curl 'https://api.mystore.com/api/v3/store/products/prod_86Rf07xd4z' \
    -H 'X-Spree-API-Key: pk_xxx'
  ```
</CodeGroup>

## Slug Generation

Slugs are automatically generated from resource names:

| Input                    | Generated Slug           |
| ------------------------ | ------------------------ |
| `Spree T-Shirt`          | `spree-t-shirt`          |
| `Café & Restaurant`      | `cafe-and-restaurant`    |
| `Summer Collection 2025` | `summer-collection-2025` |

If a slug already exists, Spree appends the SKU or a unique identifier to ensure uniqueness.

## Models with Slugs

| Resource | Slug Column | Translatable | Hierarchical |
| -------- | ----------- | :----------: | :----------: |
| Product  | `slug`      |      Yes     |      No      |
| Category | `permalink` |      Yes     |      Yes     |
| Store    | `code`      |      No      |      No      |

### Category Permalinks

Category slugs include the full parent path, making them hierarchical:

```
clothing                       → "clothing"
clothing/shirts                → "clothing/shirts"
clothing/shirts/t-shirts       → "clothing/shirts/t-shirts"
```

When a parent category is renamed, all child permalinks update automatically.

## Slug History

When a slug changes (e.g., a product is renamed), Spree records the old slug in its history table (`friendly_id_slugs`).

Note: the Store API product and category endpoints look up the *current* slug only (`find_by!` on the slug/permalink column) and do not automatically resolve retired slugs — a request using an old slug returns `404`. To preserve SEO and avoid broken links, issue HTTP 301 redirects from old slugs to the current one in your storefront or application layer.

## Internationalization

Products and categories support localized slugs — a different slug per locale. The locale is resolved from the request's [`X-Spree-Locale` header](/api-reference/store-api/localization):

<CodeGroup>
  ```typescript Store SDK theme={"theme":"night-owl"}
  // English
  const product = await client.products.get('red-shoes')

  // French — locale goes in the third (request options) argument,
  // which sends the X-Spree-Locale header
  const product = await client.products.get('chaussures-rouges', undefined, {
    locale: 'fr',
  })
  ```

  ```typescript Admin SDK theme={"theme":"night-owl"}
  // Admin SDK accepts prefixed IDs only — not slugs
  const product = await adminClient.products.get('prod_86Rf07xd4z')
  ```

  ```bash cURL theme={"theme":"night-owl"}
  # English
  curl 'https://api.mystore.com/api/v3/store/products/red-shoes' \
    -H 'X-Spree-API-Key: pk_xxx'

  # French
  curl 'https://api.mystore.com/api/v3/store/products/chaussures-rouges' \
    -H 'X-Spree-API-Key: pk_xxx' \
    -H 'X-Spree-Locale: fr'
  ```
</CodeGroup>

Slugs are unique within the same locale but can be duplicated across different locales.

## Reserved Words

Spree prevents certain words from being used as slugs to avoid route conflicts: `new`, `edit`, `index`, `login`, `logout`, `admin`, and others.

## Related Documentation

* [Products](/developer/core-concepts/products) — Product catalog
* [Translations](/developer/core-concepts/translations) — Multi-language content
* [Querying](/api-reference/store-api/querying) — API resource lookup
* [Store SDK Products](/developer/sdk/store/products) — `client.products.get()` slug/ID lookup
