# Pages

> Content pages the marketplace edits in the console (the home page, About…), built from blocks and filled in with live data.

Content pages the marketplace edits in the console (the home page, About…), built from blocks and filled in with live data. Generated from the [OpenAPI spec](https://dev.mongrl.com/openapi.json). Each endpoint says which key it needs; see [Authentication](https://dev.mongrl.com/guides/authentication.md).

| Method | Path | What it does |
|---|---|---|
| GET | [`/v1/media/{id}/{file}`](#get-a-page-image) | Get a page image |
| GET | [`/v1/pages`](#list-the-published-pages) | List the published pages |
| GET | [`/v1/pages/{slug}`](#get-a-published-page) | Get a published page |
| GET | [`/v1/pages/{slug}/preview`](#preview-a-pages-draft) | Preview a page's draft |

## Get a page image

`GET /v1/media/{id}/{file}` · operation `getMedia`

Public, for <img> tags: no key needed. `file` is thumb.jpg, medium.jpg, large.jpg or xlarge.jpg. Never changes, so it's cached for a year.

**Auth:** None.

**Parameters**

| Name | In | Type | Notes |
|---|---|---|---|
| `id` * | path | string |  |
| `file` * | path | string | one of `thumb.jpg`, `medium.jpg`, `large.jpg`, `xlarge.jpg` |

**Responses:** `200` OK · `default` [a problem](https://dev.mongrl.com/reference/conventions.md#errors)

## List the published pages

`GET /v1/pages` · operation `listPages`

Their addresses and languages, e.g. for a sitemap.

**Auth:** a secret or publishable key (`Authorization: Bearer sk_…` or `pk_…`)

**Responses:** `200` [ListPagesResponse](#listpagesresponse) · `default` [a problem](https://dev.mongrl.com/reference/conventions.md#errors)

## Get a published page

`GET /v1/pages/{slug}` · operation `getPage`

The page at `slug` (`home` is the front page) in `locale`, falling back to the marketplace's default language, with its blocks filled in: listings (on sale, prices in `currency`), images in sizes, categories, the showroom. Blocks with nothing to show are left out. 404 until the page is published.

**Auth:** a secret or publishable key (`Authorization: Bearer sk_…` or `pk_…`)

**Parameters**

| Name | In | Type | Notes |
|---|---|---|---|
| `slug` * | path | string | max 80 chars |
| `locale` | query | string | max 35 chars |
| `currency` | query | string | Show listing prices in this currency too (display_price); one of the marketplace's |

**Responses:** `200` [PageBody](#pagebody) · `default` [a problem](https://dev.mongrl.com/reference/conventions.md#errors)

## Preview a page's draft

`GET /v1/pages/{slug}/preview` · operation `previewPage`

The draft, filled in like a published page, for the console's Preview link: the shop opens `/<slug>?preview=<token>` and passes the token here. Don't cache it, and don't let search engines index it.

**Auth:** a secret or publishable key (`Authorization: Bearer sk_…` or `pk_…`)

**Parameters**

| Name | In | Type | Notes |
|---|---|---|---|
| `slug` * | path | string | max 80 chars |
| `token` * | query | string | max 100 chars |
| `currency` | query | string |  |

**Responses:** `200` [PageBody](#pagebody) · `default` [a problem](https://dev.mongrl.com/reference/conventions.md#errors)

## Schemas

Fields marked * are always present in responses and required in requests.

### ListPagesResponse

| Field | Type | Notes |
|---|---|---|
| `items` * | [PublishedPageBody](#publishedpagebody)[] |  |

### PageBody

| Field | Type | Notes |
|---|---|---|
| `blocks` * | [Block](#block)[] | In order, filled in with live data; render each by its type and skip types you don't know |
| `description` * | string | For search results and link previews |
| `locale` * | string |  |
| `published_at` | string (date-time) |  |
| `share_image` | [ImageRef](#imageref) | For link previews (og:image) |
| `slug` * | string | home is the front page |
| `title` * | string | For the browser tab and search results |

### PublishedPageBody

| Field | Type | Notes |
|---|---|---|
| `locale` * | string |  |
| `published_at` * | string (date-time) |  |
| `slug` * | string |  |

### Block

| Field | Type | Notes |
|---|---|---|
| `body` | string | Markdown (text) |
| `button_label` | string | newsletter |
| `buttons` | [Link](#link)[] | Up to 2 (hero, cta) |
| `eyebrow` | string | A short line above the heading (hero, image_text) |
| `heading` | string | hero, listing_grid, banner, category_tiles, image_text, featured_listing, cta, newsletter, showroom, faq |
| `id` * | string | Stable id within the page (1-40 letters, digits, - or _) |
| `image` | [ImageRef](#imageref) | The image, in sizes |
| `image_id` | string | An uploaded image (hero with visual image, banner, image_text, showroom; cta: optional, behind the text) |
| `image_side` | string | image_text. one of `left`, `right` |
| `items` | [Item](#item)[] | promises: 1 to 6 |
| `limit` | integer | listing_grid: how many to show (1-24, default 8) |
| `link` | [Link](#link) | Where the block leads (listing_grid "view all", banner, image_text) |
| `links` | [Link](#link)[] | 1 to 8 (links) |
| `listing` | [ListingBody](#listingbody) | hero (visual listing or newest), featured_listing |
| `listing_id` | string | hero (visual listing), featured_listing |
| `listing_ids` | string[] | listing_grid with source picked, in order |
| `listings` | [ListingBody](#listingbody)[] | listing_grid: the listings on sale to show, in order |
| `location` | [LocationRef](#locationref) | showroom |
| `location_id` | string | showroom: one of the marketplace's locations |
| `phone_image` | [ImageRef](#imageref) |  |
| `phone_image_id` | string | banner: the image for phones (the main one otherwise) |
| `questions` | [Question](#question)[] | faq: 1 to 40 |
| `rule` | [Rule](#rule) | listing_grid with source rule |
| `search` | boolean | hero: show a search box |
| `source` | string | listing_grid: hand-picked listings or a rule. one of `picked`, `rule` |
| `text` | string | Plain text (hero, banner, image_text, featured_listing note, cta, newsletter, showroom) |
| `tiles` | [Tile](#tile)[] | category_tiles: 1 to 12 |
| `tone` | string | cta: the band's colour. one of `brand`, `light`, `dark` |
| `type` * | string | one of `hero`, `links`, `listing_grid`, `banner`, `category_tiles`, `image_text`, `featured_listing`, `cta`, `newsletter`, `promises`, `showroom`, `text`, `faq` |
| `visual` | string | hero: what's beside the text; newest is the newest listing on sale. one of `image`, `listing`, `newest`, `none` |
| `when_sold` | string | featured_listing: hide the block once it sells, or keep showing it (as sold). one of `hide`, `show` |

### ImageRef

| Field | Type | Notes |
|---|---|---|
| `alt` * | string |  |
| `height` * | integer |  |
| `id` * | string |  |
| `urls` * | map of string | thumb (400 px square), medium (800 px), large (1600 px), xlarge (2400 px); cacheable forever |
| `width` * | integer |  |

### Link

| Field | Type | Notes |
|---|---|---|
| `href` * | string | A path in the shop (/shop?sort=newest) or an https:// address. max 500 chars |
| `label` * | string | max 60 chars |
| `style` | string | Buttons: the first is usually primary. one of `primary`, `secondary` |

### Item

| Field | Type | Notes |
|---|---|---|
| `text` | string |  |
| `title` * | string |  |

### ListingBody

| Field | Type | Notes |
|---|---|---|
| `attributes` * | map of any | The marketplace's own fields |
| `category_id` | string |  |
| `closed_at` | string (date-time) |  |
| `commission_percent` | number (double) | Console only: overrides the marketplace's commission; absent means the default |
| `created_at` * | string (date-time) |  |
| `custody` * | string | Where it is: at the seller's, being collected, or stored. one of `seller`, `collecting`, `stored` |
| `delivery` * | [Delivery](#delivery) | How the item can reach the buyer |
| `description` * | string |  |
| `display_price` | [MoneyBody](#moneybody) | The price in the requested currency, converted at the day's rate (approximate; the final amount is set at checkout) |
| `favorite_count` * | integer | How many users have saved it |
| `favorited` | boolean | Whether the signed-in user has saved it (only with X-User-Session) |
| `fulfilment` * | string | Who moves it to the buyer. one of `seller`, `marketplace` |
| `id` * | string |  |
| `images` * | [ImageBody](#imagebody)[] | In display order; the first is the main photo |
| `locale` * | string | The language the seller wrote in |
| `location` * | [LocationBody](#locationbody) |  |
| `offer` | [MoneyBody](#moneybody) | The price the marketplace offers (valuation_offered) |
| `offer_note` | string | A note with the offer |
| `offer_schedule` | [PriceStepBody](#pricestepbody)[] | The price drops offered with the price (valuation_offered) |
| `price` | [MoneyBody](#moneybody) | Base price, in the seller's currency |
| `price_schedule` | [PriceStepBody](#pricestepbody)[] | The price falls in these steps while on sale |
| `published_at` | string (date-time) |  |
| `review_note` | string | Why the marketplace denied it (denied) |
| `seller_blocked` | boolean | The seller is blocked, so the listing is out of the shop |
| `seller_id` * | string |  |
| `shipping_size` | string | Prices delivery from the marketplace's shipping table |
| `site` | [SiteRefBody](#siterefbody) | The marketplace location it's stored at or being collected to |
| `status` * | string | one of `draft`, `pending_valuation`, `valuation_offered`, `pending_approval`, `published`, `closed`, `denied` |
| `stock` * | integer |  |
| `stored_at` | string (date-time) | Stored since |
| `terms` * | map of [TermRefBody](#termrefbody) | By kind, e.g. brand |
| `title` * | string |  |
| `updated_at` * | string (date-time) |  |
| `wants_storage` | boolean | The seller asked to have it collected and stored |

### LocationRef

| Field | Type | Notes |
|---|---|---|
| `buyer_pickup` * | boolean |  |
| `city` * | string |  |
| `country` * | string |  |
| `kind` * | string |  |
| `line1` * | string |  |
| `name` * | string |  |
| `opening_hours` * | string |  |
| `postal_code` * | string |  |

### Question

| Field | Type | Notes |
|---|---|---|
| `answer` * | string |  |
| `question` * | string |  |

### Rule

| Field | Type | Notes |
|---|---|---|
| `category_id` | string |  |
| `sort` | string | one of `newest`, `price_asc`, `price_desc`, `popular` |
| `term_ids` | string[] |  |

### Tile

| Field | Type | Notes |
|---|---|---|
| `category` | [CategoryRef](#categoryref) |  |
| `category_id` * | string |  |
| `image` | [ImageRef](#imageref) |  |
| `image_id` | string |  |
| `label` | string | Shown instead of the category's name |

### Delivery

| Field | Type | Notes |
|---|---|---|
| `buyer_arranged` | boolean |  |
| `pickup` | boolean |  |
| `shipping` | [Shipping](#shipping) |  |

### MoneyBody

| Field | Type | Notes |
|---|---|---|
| `amount` * | integer | In minor units: 125000 SEK is 1 250,00 kr. ≥ 0 |
| `currency` * | string | ISO 4217, one of the marketplace's |

### ImageBody

| Field | Type | Notes |
|---|---|---|
| `height` | integer |  |
| `id` * | string |  |
| `status` * | string | Sizes exist once ready. one of `processing`, `ready`, `failed` |
| `urls` | map of string | thumb (400 px square), medium (800 px), large (1600 px); cacheable forever |
| `width` | integer |  |

### LocationBody

| Field | Type | Notes |
|---|---|---|
| `city` | string |  |
| `country` | string | ISO 3166-1 alpha-2, e.g. SE |
| `postal_code` | string |  |

### PriceStepBody

| Field | Type | Notes |
|---|---|---|
| `amount` * | integer | The new price, in minor units. ≥ 1 |
| `done` | boolean | It has applied |
| `months` * | integer | Months after the schedule starts (the listing goes on sale, or the schedule changes while on sale). ≥ 1; ≤ 60 |
| `on` | string (date-time) | When it applies (once on sale) |

### SiteRefBody

| Field | Type | Notes |
|---|---|---|
| `buyer_pickup` | boolean | Buyers may collect purchases here |
| `city` | string |  |
| `id` * | string |  |
| `kind` * | string | one of `showroom`, `warehouse` |
| `name` * | string |  |

### TermRefBody

| Field | Type | Notes |
|---|---|---|
| `descriptions` | map of string | About the brand, designer…, by locale (e.g. en, sv); on single listings only |
| `id` * | string |  |
| `name` * | string |  |
| `slug` * | string |  |

### CategoryRef

| Field | Type | Notes |
|---|---|---|
| `id` * | string |  |
| `name` * | string |  |
| `slug` * | string |  |

### Shipping

| Field | Type | Notes |
|---|---|---|
| `additional_item_price` | integer | ≥ 0 |
| `price` | integer | For the first item; omit for "ask for a quote". ≥ 0 |
