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

# Categories API — Browse and Filter Product Categories

> List all product categories, fetch category details with product count, or list products within a specific category. No authentication required.

The Categories API exposes the product taxonomy that organizes your storefront. Use it to build navigation menus, category landing pages, and scoped product grids. All three endpoints are public — no session cookie is required. Only active, non-deleted categories are visible to customers.

<Tip>
  The recommended pattern for building a category page is to first call `GET /categories` to fetch all visible categories (with their `public_id` values), then call `GET /categories/{category_public_id}/products` to list products scoped to the selected category. This avoids hard-coding category IDs in your client.
</Tip>

***

## List Categories

Retrieve a paginated list of customer-visible categories. Optionally search by name or description and sort alphabetically or by date.

```
GET /categories
```

**Query parameters**

<ParamField query="page" type="integer" default="1">
  Page number (1-based).
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Number of results per page. Minimum `1`, maximum `100`.
</ParamField>

<ParamField query="search" type="string">
  Free-text search across category name and description (trimmed, max 100 characters).
</ParamField>

<ParamField query="sort" type="string" default="name">
  Sort field. Prefix with `-` for descending. Allowed values: `name`, `-name`, `created_at`, `-created_at`, `updated_at`, `-updated_at`. Default is alphabetical by name.
</ParamField>

**Response fields**

<ResponseField name="success" type="boolean">
  Always `true` on success.
</ResponseField>

<ResponseField name="data" type="array">
  Array of category objects.

  <Expandable title="Category object fields">
    <ResponseField name="public_id" type="string">
      Stable public identifier. Pattern: `cat_*`. Pass this to `/categories/{category_public_id}` or `/categories/{category_public_id}/products`.
    </ResponseField>

    <ResponseField name="name" type="string">
      Display name of the category (e.g., `"Sneakers"`).
    </ResponseField>

    <ResponseField name="slug" type="string">
      URL-safe slug (e.g., `"sneakers"`).
    </ResponseField>

    <ResponseField name="description" type="string | null">
      Category description, or `null` if not set.
    </ResponseField>

    <ResponseField name="is_active" type="boolean">
      Always `true` in the public listing — inactive categories are excluded.
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 UTC creation timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object">
  Pagination metadata (`page`, `limit`, `total`, `totalPages`, `hasNext`, `hasPrev`).
</ResponseField>

**Example — Build a navigation menu**

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.example.com/api/v1/categories?sort=name&limit=50"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.example.com/api/v1/categories?sort=name&limit=50'
  );
  const { data } = await response.json();

  // Build a nav menu
  const navItems = data.map(cat => ({
    label: cat.name,
    href: `/categories/${cat.slug}`,
    id: cat.public_id,
  }));
  ```
</CodeGroup>

**Example response**

```json theme={null}
{
  "success": true,
  "data": [
    {
      "public_id": "cat_01H",
      "name": "Running",
      "slug": "running",
      "description": "Performance footwear for road and trail runners.",
      "is_active": true,
      "created_at": "2024-01-10T08:00:00.000Z"
    },
    {
      "public_id": "cat_02H",
      "name": "Sneakers",
      "slug": "sneakers",
      "description": "Everyday casual and lifestyle sneakers.",
      "is_active": true,
      "created_at": "2024-01-10T08:05:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 2,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}
```

***

## Get a Category

Retrieve a single category by its public ID, including the number of products assigned to it.

```
GET /categories/{category_public_id}
```

**Path parameters**

<ParamField path="category_public_id" type="string" required>
  The category's public ID. Pattern: `cat_*`.
</ParamField>

**Response fields**

<ResponseField name="data" type="object">
  A single category object with the same fields as the list response, plus:

  <Expandable title="Additional fields">
    <ResponseField name="product_count" type="integer">
      Number of active, customer-visible products assigned to this category. Use this to show a count badge next to the category name (e.g., "Sneakers (42)").
    </ResponseField>
  </Expandable>
</ResponseField>

**Example — Load a category header**

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.example.com/api/v1/categories/cat_01H
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.example.com/api/v1/categories/cat_01H'
  );
  const { data } = await response.json();
  console.log(`${data.name} — ${data.product_count} products`);
  ```
</CodeGroup>

**Example response**

```json theme={null}
{
  "success": true,
  "data": {
    "public_id": "cat_01H",
    "name": "Running",
    "slug": "running",
    "description": "Performance footwear for road and trail runners.",
    "is_active": true,
    "product_count": 18,
    "created_at": "2024-01-10T08:00:00.000Z"
  }
}
```

**Error responses**

| Status | Description                                    |
| ------ | ---------------------------------------------- |
| `404`  | Category not found, inactive, or soft-deleted. |

***

## List Products in a Category

Retrieve all customer-visible products belonging to a specific category. Supports the same filtering and sorting options as the global product list.

```
GET /categories/{category_public_id}/products
```

**Path parameters**

<ParamField path="category_public_id" type="string" required>
  The category's public ID. Pattern: `cat_*`. Returns `404` if the category is inactive, deleted, or does not exist.
</ParamField>

**Query parameters**

<ParamField query="page" type="integer" default="1">
  Page number (1-based).
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Number of results per page. Minimum `1`, maximum `100`.
</ParamField>

<ParamField query="search" type="string">
  Free-text search within this category's products (name, brand, description).
</ParamField>

<ParamField query="sort" type="string" default="-created_at">
  Sort field. Prefix with `-` for descending. Allowed values: `name`, `-name`, `created_at`, `-created_at`, `updated_at`, `-updated_at`.
</ParamField>

**Response fields**

The response shape is identical to `GET /products` — an array of product summary objects under `data`, each containing `public_id`, `name`, `slug`, `brand`, `primary_image`, and `created_at`, plus a `meta` pagination object.

**Example — Render a category product grid**

<CodeGroup>
  ```bash cURL theme={null}
  curl -G https://api.example.com/api/v1/categories/cat_01H/products \
    --data-urlencode "sort=-created_at" \
    --data-urlencode "limit=24" \
    --data-urlencode "page=1"
  ```

  ```javascript JavaScript theme={null}
  const categoryId = 'cat_01H';
  const response = await fetch(
    `https://api.example.com/api/v1/categories/${categoryId}/products?sort=-created_at&limit=24`
  );
  const { data, meta } = await response.json();
  console.log(`Showing ${data.length} of ${meta.total} products in this category`);
  ```
</CodeGroup>

**Example response**

```json theme={null}
{
  "success": true,
  "data": [
    {
      "public_id": "prd_01H",
      "name": "Runner Sneaker",
      "slug": "runner-sneaker",
      "brand": "Nike",
      "primary_image": {
        "image_url": "https://ik.imagekit.io/demo/products/runner-sneaker.jpg",
        "alt_text": "Runner Sneaker front view"
      },
      "created_at": "2024-03-15T10:00:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 24,
    "total": 18,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}
```

**Error responses**

| Status | Description                                    |
| ------ | ---------------------------------------------- |
| `400`  | Invalid query parameter format.                |
| `404`  | Category not found, inactive, or soft-deleted. |
