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

# Search

> How to call the Platform API search endpoints: the /v3/search/results request and response, pagination, filter and sort semantics, and /v3/search/suggestions.

<Warning>
  The Platform API currently has two active versions. Build new integrations
  against the `/v3` endpoints — `/v3` is the successor to `/v2`. `/v2` is
  expected to be deprecated within roughly 6 months and `/v3` within roughly 9
  months, with a v4 API expected in Q4. These are expectations, not committed
  dates — confirm timelines with your Depict contact before planning a
  migration deadline.
</Warning>

Search on the Platform API consists of these endpoints:

| Endpoint                 | Method | Purpose                                                                                                       |
| ------------------------ | ------ | ------------------------------------------------------------------------------------------------------------- |
| `/v3/search/results`     | POST   | Search results for a query, with filters, sorting and pagination                                              |
| `/v3/search/suggestions` | GET    | Query and listing suggestions for autocomplete                                                                |
| `/v3/search/related`     | POST   | Related-products recommendations for a search — returns a recommendations-shaped response, see the note below |

<Note>
  `/v3/search/related` returns the same response shape as
  [`/v3/recommend/products`](/api-guide/recommendations/api), not a search
  response. Its displays carry `recommendation_id` (not `search_result_id`) for
  [tracking](/api-guide/tracking/product-cards).
</Note>

## Limits and behavior

* Every response is a single JSON body. No search endpoint streams; there is no SSE or chunked delivery.
* Two pagination styles exist — cursor-based and page-based. They are mutually exclusive: mixing fields from both in one request returns 400.
* Cursor-based `limit`: 1–250. Page-based `hits_per_page`: 1–200 and required whenever `page` is sent.
* `merchant`, `market` and `locale` are required on every request. Enumerate valid values via [`/v3/markets` and `/v3/locales`](/api-guide/introduction#markets-locales-and-currency).
* Unknown request fields are silently ignored — a misspelled field name is dropped, not rejected.
* Available filters and sorts are per-merchant configuration. Do not hardcode them: read them off the `filters` and `sorts` arrays in each response.
* `GET /v2/search/content` (dedicated content search) has no v3 equivalent. Content results are available only as `content_search_links` inside `/v3/search/results` responses.
* Suggestions responses carry a one-hour cache header; `limit` for suggestions is 1–10, default 3.
* Response fields with null values are omitted from the JSON (`exclude_none` serialization).

## Search results

`POST /v3/search/results` with a JSON body:

| Field           | Type    | Required | Description                                                                              |
| --------------- | ------- | -------- | ---------------------------------------------------------------------------------------- |
| `merchant`      | string  | Yes      | Your merchant identifier, provided by Depict                                             |
| `market`        | string  | Yes      | Market identifier                                                                        |
| `locale`        | string  | Yes      | Locale identifier                                                                        |
| `query`         | string  | No       | The search query                                                                         |
| `filters`       | array   | No       | Filters to apply — see [Filters](#filters)                                               |
| `sort`          | object  | No       | Sorting method — see [Sorting](#sorting)                                                 |
| `session_id`    | string  | No       | Session identifier; required for the request to be tracked and attributable              |
| `metadata`      | object  | No       | String-to-string map that can modify search behavior; only use values agreed with Depict |
| `cursor`        | string  | No       | Cursor-based pagination — see [Pagination](#pagination)                                  |
| `limit`         | integer | No       | Cursor-based pagination: max results per response, 1–250                                 |
| `page`          | integer | No       | Page-based pagination: 1-based page index                                                |
| `hits_per_page` | integer | No       | Page-based pagination: results per page, 1–200; required when `page` is sent             |

Example request:

```json theme={null}
{
  "merchant": "MERCHANT_ID",
  "market": "MARKET",
  "locale": "en",
  "query": "jeans",
  "limit": 40,
  "session_id": "SESSION_ID"
}
```

### Response

| Field                  | Type             | Description                                                                                                                                                                                      |
| ---------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `displays`             | array of objects | The results, one object per product card. The contents are merchant-specific product data; each display also carries a `search_result_id` used for [tracking](/api-guide/tracking/product-cards) |
| `n_hits`               | integer          | Total number of results for the query. Not necessarily exact                                                                                                                                     |
| `sorts`                | array            | Available sorting methods. Any element can be sent as `sort` in a subsequent request                                                                                                             |
| `filters`              | array            | Available filters that can be sent back in a subsequent request                                                                                                                                  |
| `search_request_id`    | string           | Identifier for this response, used in tracking                                                                                                                                                   |
| `cursor`               | string           | Cursor for the next page. Absent when there are no more results                                                                                                                                  |
| `page`                 | integer          | Echoed page index when page-based pagination was used; absent otherwise                                                                                                                          |
| `content_search_links` | array            | Content pages matching the query — see [Content results](#content-results)                                                                                                                       |

## Pagination

| Style        | Request fields                       | How to page                                                                                                              |
| ------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| Cursor-based | `cursor`, `limit` (1–250)            | Omit `cursor` for the first request. Send the response's `cursor` in the next request until the response has no `cursor` |
| Page-based   | `page` (≥1), `hits_per_page` (1–200) | Request each page by index. `hits_per_page` is required whenever `page` is sent                                          |

Rules for how the two styles interact:

* The styles are mutually exclusive. A request that mixes fields from both returns 400 with `{"error": "Cannot mix cursor-based and page-based pagination."}`.
* `page` without `hits_per_page` returns 400.
* An undecodable `cursor` returns 400 with `{"error": "Invalid pagination cursor."}`.
* The response mirrors the style used: page-based requests always echo `page` (defaulting to 1) and omit `cursor`; cursor-based requests omit `page`.

## Filters

The filter contract is round-trip based: each response's `filters` array describes every filter available for your catalog, and applying a filter means sending it back in the next request's `filters` array. `field`, `op` and `data` are required on each filter you send; `data` holds the selected state.

A filter object:

| Field   | Type   | Description                                                                                                                       |
| ------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `field` | string | The product attribute the filter applies to                                                                                       |
| `op`    | string | One of `eq`, `neq`, `in`, `nin`, `leq`, `geq`, `inrange`                                                                          |
| `data`  | varies | The selected state — format depends on the filter type, see below                                                                 |
| `meta`  | object | UI metadata (type, title, selectable values, counts, display names). Returned by the API; not required when sending a filter back |
| `id`    | string | Groups filters that belong together. Optional                                                                                     |

The filter type is in `meta.type`:

| `meta.type`             | Selection behavior                                                    | `data` format                |
| ----------------------- | --------------------------------------------------------------------- | ---------------------------- |
| `range`                 | Numeric range, e.g. price                                             | `[min, max]`                 |
| `radio`                 | Exactly one value selectable                                          | List with the selected value |
| `checkbox`              | Multiple values selectable                                            | List of selected values      |
| `checkbox-grid`         | Same as `checkbox`; render compactly as a grid (typically sizes)      | List of selected values      |
| `checkbox-color`        | Same as `checkbox`; `meta.swatches` provides color swatches per value | List of selected values      |
| `checkbox-hierarchical` | Tree of values, typically categories                                  | List of paths — see below    |

### Range filters

`data` is `[min, max]`. `meta` carries the selectable bounds `min` and `max`, plus optional `unit` and `currency` for rendering.

### Value filters

`data` is the list of selected values. `meta.values` lists the selectable values, `meta.counts` the result count per value, and `meta.names` optional display names.

### Hierarchical filters

`data` is a list of paths, where each path is the list of node titles from the root to a selected node. If a parent is selected, all of its children must also be included as selected.

Example: a category tree where the user selected **Shirts** and **Jeans**:

1. Clothes
   1. **Shirts**
      1. **Cotton Shirts**
      2. **Linen Shirts**
   2. Pants
      1. **Jeans**
      2. Shorts

Selecting Shirts (a parent) implies both of its children, so the corresponding `data` is:

```json theme={null}
[
  ["Clothes", "Shirts"],
  ["Clothes", "Shirts", "Cotton Shirts"],
  ["Clothes", "Shirts", "Linen Shirts"],
  ["Clothes", "Pants", "Jeans"]
]
```

Invalid filter, market or locale combinations return 422 with `{"error": "Invalid request parameters. Please check your filters, market, and locale."}`.

## Sorting

Each response's `sorts` array lists the available sorting methods for your catalog; the default is relevance. To sort, send one of them back as `sort`: `{"field": "...", "order": "asc" | "desc"}`. The `meta` object on each sort (title, selectable orders, display names) is for rendering and does not need to be sent back.

## Query suggestions

`GET /v3/search/suggestions` with query-string parameters:

| Parameter    | Type    | Required | Description                                    |
| ------------ | ------- | -------- | ---------------------------------------------- |
| `merchant`   | string  | Yes      | Your merchant identifier                       |
| `market`     | string  | Yes      | Market identifier                              |
| `locale`     | string  | Yes      | Locale identifier                              |
| `query`      | string  | No       | The partial query the user has typed           |
| `session_id` | string  | No       | Session identifier                             |
| `limit`      | integer | No       | Maximum number of suggestions, 1–10. Default 3 |

The response is `{"suggestions_request_id": "...", "suggestions": [...]}` where each suggestion is one of two shapes:

| `type`    | Fields                                                                                                                                                        | Meaning                                                                                            |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `query`   | `query`, `suggestions_result_id`                                                                                                                              | A suggested search query                                                                           |
| `listing` | `listing_id`, `external_id`, `listing_type`, `title`, `slug`, `image_urls`, `show_in_breadcrumbs`, `show_in_quicklinks`, `ancestors`, `suggestions_result_id` | A suggested [listing](/api-guide/listings). `ancestors` is the ordered breadcrumb path, root first |

<Note>
  On v2 the suggested-query field was named `title` and listing suggestions
  were category suggestions. On v3 the field is `query` and suggestions
  reference listings.
</Note>

Suggestions responses carry a one-hour cache header. If the suggestions index for the requested locale has not been built yet, the endpoint returns 404 with an `{"error": ...}` body.

## Content results

There is no dedicated content-search endpoint on v3 — `GET /v2/search/content` has no successor. Content results arrive as the `content_search_links` array on `/v3/search/results` responses. Each element:

| Field         | Type   | Description                               |
| ------------- | ------ | ----------------------------------------- |
| `type`        | string | Always `content_link`                     |
| `title`       | string | Title of the content page                 |
| `description` | string | Short description. May be absent          |
| `image_url`   | string | Image for the content page. May be absent |
| `page_url`    | string | URL of the content page                   |
| `highlights`  | array  | Snippets showing why the query matched    |

## Errors

| Status | Body                | Cause                                                                                                          |
| ------ | ------------------- | -------------------------------------------------------------------------------------------------------------- |
| 400    | `{"error": "..."}`  | Invalid cursor, `page` without `hits_per_page`, mixed pagination styles, unknown merchant/market configuration |
| 422    | `{"error": "..."}`  | Invalid filters, market or locale                                                                              |
| 422    | `{"detail": [...]}` | Request body fails schema validation (missing required field, wrong type)                                      |
| 404    | `{"error": "..."}`  | Suggestions index not yet built for the requested locale                                                       |

Unexpected errors return `{"error": "..."}` including an `Error ID` — quote that ID to Depict support when reporting a problem.
