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

# Filtering & Pagination

## Filtering and pagination

Most list queries in the WikiParfum API support a shared set of filtering, pagination, and sorting parameters. Understanding these patterns lets you build precise, performant queries across perfumes, ingredients, brands, and recommendations.

## Pagination

Pagination uses an offset-based pattern via the `page` parameter, formatted as a string: `"offset,limit"`.

<CodeGroup>
  ```graphql Query theme={null}
  query PaginatedPerfumes {
    findPerfumes(search: {
      lang: "EN"
      page: "0,20"
    }) {
      id
      name
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "findPerfumes": [
        {
          "id": "19761",
          "name": "MON GUERLAIN EAU DE PARFUM"
        },
        {
          "id": "1726",
          "name": "DAISY EAU SO FRESH"
        }
      ]
    }
  }
  ```
</CodeGroup>

| Example   | Meaning          |
| --------- | ---------------- |
| `"0,20"`  | First 20 results |
| `"20,20"` | Results 21–40    |
| `"40,10"` | Results 41–50    |

The offset is zero-based. The first value is the starting position, the second is the number of results to return.

## Sorting

Use the `order_by` parameter to control result ordering. The format is `"field direction"`.

<CodeGroup>
  ```graphql Query theme={null}
  query SortedPerfumes {
    findPerfumes(search: {
      lang: "EN"
      page: "0,20"
      order_by: "name asc"
    }) {
      id
      name
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "findPerfumes": [
        {
          "id": "31797",
          "name": "000"
        },
        {
          "id": "4845",
          "name": "1 MILLION"
        }
      ]
    }
  }
  ```
</CodeGroup>

Common sort options:

| Value                  | Description                                            |
| ---------------------- | ------------------------------------------------------ |
| `"name asc"`           | Alphabetical A–Z                                       |
| `"name desc"`          | Alphabetical Z–A                                       |
| `"year desc"`          | Newest first                                           |
| `"year asc"`           | Oldest first                                           |
| `"price-asc"`          | By market segment: mass → prestige → niche             |
| `"price-desc"`         | By market segment: niche → prestige → mass             |
| `"customerPrice-asc"`  | By customer price: lowest first                        |
| `"customerPrice-desc"` | By customer price: highest first                       |
| `"popularity"`         | Most popular first (based on previous month's traffic) |

<Note>
  The `price-asc` and `price-desc` options sort by market classification (`mass`, `prestige`, `niche`) as a proxy for price tier, not by actual product price. Perfumes without a classification are placed last in ascending order and first in descending order.
</Note>

<Note>
  The `customerPrice-asc` and `customerPrice-desc` options sort by your catalog's actual product prices. Perfumes without a price in your catalog are placed last.

  **Requirements:**

  * Your [Product Feed](/catalog-integration/feed-format) must include the `price` column.
  * Use a dot (`.`) as the decimal separator (e.g., `29.99`). Comma-separated values (e.g., `29,99`) will be converted automatically, but using dot format is recommended to avoid potential issues.
  * If a perfume has multiple EANs with different prices, the **lowest price** is used for sorting.
</Note>

<Note>
  The `customerPrice` sorting options and the `customerPriceRange` filter are available on `findPerfumes`, `recommendedPerfumes`, and `findPerfumeByIngredient`.
</Note>

<Note>
  The `popularity` option ranks perfumes by their global view count from the previous calendar month across WikiParfum and the WikiParfum app. Perfumes without traffic data are placed at the end.
</Note>

## The Filters input

The `Filters` input type is shared across perfume, ingredient, brand, and recommendation queries. It provides fine-grained control over which results are returned.

### Gender

Filter by target gender.

<CodeGroup>
  ```graphql Query theme={null}
  query FemalePerfumes {
    findPerfumes(search: {
      lang: "EN"
      page: "0,20"
      filters: {
        gender: "F"
      }
    }) {
      id
      name
      gender
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "findPerfumes": [
        {
          "id": "300",
          "name": "MON PARIS EAU DE PARFUM",
          "gender": "F"
        },
        {
          "id": "301",
          "name": "BURBERRY HER",
          "gender": "F"
        }
      ]
    }
  }
  ```
</CodeGroup>

| Value | Meaning   |
| ----- | --------- |
| `"F"` | Feminine  |
| `"M"` | Masculine |
| `"U"` | Unisex    |

### Brand

Filter by brand slug or brand IDs.

<CodeGroup>
  ```graphql Query theme={null}
  query PerfumesByBrandSlug {
    findPerfumes(search: {
      lang: "EN"
      page: "0,20"
      filters: {
        brand: "chanel"
      }
    }) {
      id
      name
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "findPerfumes": [
        {
          "id": "488",
          "name": "ALLURE EAU DE TOILETTE"
        },
        {
          "id": "489",
          "name": "ALLURE HOMME"
        }
      ]
    }
  }
  ```
</CodeGroup>

Use `brandsIds` for multiple brands: `brandsIds: "42,87,103"`.

Use `excludedBrandsIds` to exclude specific brands: `excludedBrandsIds: "55,60"`.

### Olfactive family

Filter by primary family, secondary family, or both.

<CodeGroup>
  ```graphql Query theme={null}
  query WoodyPerfumes {
    findPerfumes(search: {
      lang: "EN"
      page: "0,20"
      filters: {
        family: "woody"
      }
    }) {
      id
      name
      family {
        name
      }
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "findPerfumes": [
        {
          "id": "6704",
          "name": "VALENTINO DONNA BORN IN ROMA",
          "family": {
            "name": "WOODY"
          }
        },
        {
          "id": "760",
          "name": "FAHRENHEIT",
          "family": {
            "name": "WOODY"
          }
        }
      ]
    }
  }
  ```
</CodeGroup>

| Filter          | Description                             |
| --------------- | --------------------------------------- |
| `family`        | Primary family slug                     |
| `mainfamily`    | Alias for primary family slug           |
| `subfamily`     | Secondary family slug                   |
| `mainFamilyIds` | Primary family IDs (comma-separated)    |
| `subFamilyIds`  | Secondary family IDs (comma-separated)  |
| `familiesIds`   | Combined primary + secondary family IDs |

### Market classification

```graphql theme={null}
filters: {
  classification: "prestige"
}
```

| Value        | Meaning                   |
| ------------ | ------------------------- |
| `"prestige"` | Prestige / luxury segment |
| `"mass"`     | Mass market segment       |

### Intensity range

Filter by olfactive intensity using a min/max range.

```graphql theme={null}
filters: {
  intensity: "3,7"
}
```

### Customer price range

Filter by your catalog's product prices using a min/max range.

```graphql theme={null}
filters: {
  customerPriceRange: "10,100"
}
```

The format is `"min,max"` where both values are numeric. Perfumes without a price in your catalog are excluded from the results when this filter is applied.

<Note>
  This filter requires the `price` column in your [Product Feed](/catalog-integration/feed-format). If a perfume has multiple EANs with different prices, the perfume is included if **any** of its EANs falls within the specified range.
</Note>

### Discontinued products

```graphql theme={null}
filters: {
  discontinued: "no"
}
```

| Value   | Meaning                    |
| ------- | -------------------------- |
| `"yes"` | Only discontinued perfumes |
| `"no"`  | Only active perfumes       |

### Release date

Filter by release year or year-month.

```graphql theme={null}
filters: {
  releaseDate: ["2023", "2024"]
}
```

### Region and country

Restrict results to perfumes available in specific regions or countries.

```graphql theme={null}
filters: {
  regions: ["EU"]
  countries: ["FR", "ES"]
}
```

### Additional filters

| Filter          | Type      | Description                               |
| --------------- | --------- | ----------------------------------------- |
| `withImage`     | `Boolean` | Only return perfumes with images          |
| `popular`       | `Boolean` | Only popular perfumes                     |
| `onlyReleased`  | `Boolean` | Only released perfumes                    |
| `showVariant`   | `Boolean` | Include variant products                  |
| `fragranceType` | `String`  | Filter by fragrance type (e.g., EDP, EDT) |

## Combining filters

Filters can be combined freely. All active filters are applied with AND logic.

<CodeGroup>
  ```graphql Query theme={null}
  query CombinedFilters {
    findPerfumes(search: {
      lang: "EN"
      page: "0,20"
      order_by: "year desc"
      filters: {
        gender: "F"
        classification: "prestige"
        family: "floral"
        discontinued: "no"
        withImage: true
      }
    }) {
      id
      name
      brand {
        name
      }
      family {
        name
      }
      year
      gender
    }
  }
  ```

  ```json Response theme={null}
  {
    "data": {
      "findPerfumes": [
        {
          "id": "4217",
          "name": "LADY MILLION",
          "brand": {
            "name": "Rabanne"
          },
          "family": {
            "name": "FLORAL"
          },
          "year": 2010,
          "gender": "F"
        }
      ]
    }
  }
  ```
</CodeGroup>
