# Browsing and search

> The shop page, search, filters, sorting, prices in the visitor's currency, listing pages, photos, categories, brands and favourites.

Everything a visitor sees before they sign in works with your secret key alone (a publishable key works too, from a native app).

## Start from the marketplace

`GET /v1/marketplace` tells you how to build the shop:

| Field | Use it for |
|---|---|
| `currencies` | The currency picker. The first is the default. |
| `locales` | Languages. The first is the default. |
| `term_kinds` | Which catalogue filters exist, e.g. `brand`, `designer`. |
| `listings.attributes_schema` | A JSON Schema of the marketplace's own listing fields (condition, dimensions…). Filter on them with `attr`. |
| `shipping` | Delivery prices by size and zone, for "delivery from…" hints. See [Shipping and delivery](https://dev.mongrl.com/guides/delivery.md). |

Cache it for a few minutes; it changes when the team edits Settings.

## Search and filter

```http
GET /v1/listings?q=lounge+chair&term=<brand id>&attr=condition:excellent&min_price=500000&currency=EUR&sort=newest&limit=24
```

| Parameter | What it does |
|---|---|
| `q` | Words in the title, catalogue terms or description. Accents don't matter and word beginnings match: "henn" finds Henningsen. |
| `category` | This category and everything under it. |
| `term` | Catalogue term ids; repeat it. Terms of one kind match any (brand A **or** B); different kinds must all match (brand A **and** designer C). |
| `attr` | `key:value` on the marketplace's own fields; repeat it. Values of one key match any. |
| `min_price`, `max_price` | Minor units of `currency`, which is then required. Listings in other currencies are compared at the day's rate. |
| `seller` | One seller's listings, for a seller page. |
| `currency` | Adds `display_price` in this currency (one of the marketplace's). |
| `sort` | `relevance` (the default with `q`), `newest` (the default without), `price_asc`, `price_desc`, `popular` (most saved). |
| `limit`, `cursor` | Paging. Pass `next_cursor` back as `cursor`; there's no more when it's absent. |

The answer has `items`, `total` (how many match) and `next_cursor`. Only listings on sale are returned.

## Prices

Every listing has `price`: what the seller set, in the listing's currency. With `currency`, it also has `display_price`, converted at the day's rate.

- Show `display_price` when you asked for one, otherwise `price`.
- Converted prices are approximate. The buyer pays what the [quote](https://dev.mongrl.com/guides/checkout.md#1-quote) says.
- Format with `Intl.NumberFormat(locale, { style: 'currency', currency })` after dividing by 100 for currencies with two decimals.

```ts
const money = ({ amount, currency }: { amount: number; currency: string }, locale = 'sv-SE') =>
  new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount / 100)
```

A listing on sale may have a `price_schedule`: the price falls in steps while it doesn't sell. The current `price` is already the dropped one, so you don't need to work it out.

## The listing page

`GET /v1/listings/{id}?currency=EUR` returns one listing on sale (`404` otherwise). Useful fields:

- `title`, `description`, `terms` (by kind, each with `name` and `slug`), `attributes`, `category_id`.
- `images` in display order; the first is the main photo.
- `delivery`: how it can reach the buyer. See [Shipping and delivery](https://dev.mongrl.com/guides/delivery.md).
- `site`: the showroom or warehouse it's stored at, when it is (`buyer_pickup` says whether buyers may collect it there).
- `favorite_count`, and `favorited` when you send the user's session.
- `seller_id`, for a link to the seller's other listings (`?seller=`).

## Photos

Each image has `status` and `urls`:

| Size | Use |
|---|---|
| `thumb` | 400 px square, for grids |
| `medium` | 800 px wide, for listing pages on phones |
| `large` | 1600 px wide, for zoom |

The URLs are public and can be cached forever; a changed photo gets a new URL. Only `ready` images have sizes.

## Categories and catalogue terms

- `GET /v1/categories?locale=sv` returns the whole tree at once, with `parent_id` and `position`. Build the menu from it.
- `GET /v1/catalog-terms?kind=brand&in_use=true` returns every brand with listings on sale, each with `listing_count`, for a filter list.
- `GET /v1/catalog-terms?kind=designer&q=hen` filters by the start of the name, a page at a time, for a brand or designer index.
- `GET /v1/catalog-terms/{kind}/{slug}` returns one term, for a brand page at `/brands/<slug>`. Then list its listings with `term=<id>`.

## Showrooms

`GET /v1/locations` returns the marketplace's active showrooms and warehouses: address, opening hours and whether buyers may collect there. Use it for a "visit us" page.

## Favourites

With the user's session:

- `PUT /v1/me/favorites/{listing id}` saves, `DELETE` removes. Both are safe to repeat.
- `GET /v1/me/favorites?currency=EUR` lists them, newest first, with cursor paging.

Show the heart from `favorited` on listings you fetched with the session.
