diff --git a/source/rest-v2.html.md b/source/rest-v2.html.md
index 1d1757ebb59..5faa078aacd 100644
--- a/source/rest-v2.html.md
+++ b/source/rest-v2.html.md
@@ -2039,6 +2039,317 @@ Both 'links' and 'products' allow the fields below:
| ----- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| icons | Boolean | No | Show or hide hotspot icons for extracted hotspot. This setting is not applicable to hotspots extracted from PDF annotations (those are defined in the annotation itself) |
+# Hotspot Endpoints
+
+Hotspots are interactive areas placed on spread pages. Each hotspot has a type that determines its behavior and the additional fields returned in the response. All coordinates and dimensions are expressed as a fraction of the spread size (values between 0 and 1).
+
+## List all hotspots of a spread
+
+```shell
+curl "https://api.publitas.com/v2/spreads/42/hotspots" \
+ -H "Authorization: ApiKey "
+```
+
+> The above command returns JSON structured like this:
+
+```json
+{
+ "hotspots": [
+ {
+ "id": 1,
+ "type": "external_link",
+ "top": 0.1,
+ "left": 0.2,
+ "width": 0.15,
+ "height": 0.08,
+ "icon_left": 0.5,
+ "icon_top": 0.5,
+ "show_indication": true,
+ "tab_index": null,
+ "z_index": 0,
+ "embedded_content": false,
+ "dynamic": false,
+ "product_theme_id": null,
+ "rotation": 0.0,
+ "url": "https://example.com",
+ "popup_max_width": null,
+ "popup_max_height": null
+ }
+ ]
+}
+```
+
+### HTTP Request
+
+`GET https://api.publitas.com/v2/spreads//hotspots`
+
+### URL Parameters
+
+| Parameter | Description |
+| --------- | ------------------------------- |
+| Spread ID | The ID of a specific spread |
+
+This endpoint supports [pagination](#understanding-pagination). Results are ordered by page number.
+
+### Response fields
+
+The response returns an array of hotspot objects. All hotspot types share the following base fields:
+
+| Field | Type | Description |
+| ----------------- | ------------ | -------------------------------------------------------- |
+| `id` | Integer | Hotspot ID |
+| `type` | String | Hotspot type (see below) |
+| `top` | Float | Top offset as a fraction of spread height (0–1) |
+| `left` | Float | Left offset as a fraction of spread width (0–1) |
+| `width` | Float | Width as a fraction of spread width (0–1) |
+| `height` | Float | Height as a fraction of spread height (0–1) |
+| `icon_left` | Float | Horizontal center of the hotspot icon (0–1) |
+| `icon_top` | Float | Vertical center of the hotspot icon (0–1) |
+| `show_indication` | Boolean | Whether the hotspot indication icon is visible |
+| `tab_index` | Integer/null | Accessibility tab order |
+| `z_index` | Integer | Stacking order relative to other hotspots on the spread |
+| `embedded_content`| Boolean | Whether the hotspot renders its content inline |
+| `dynamic` | Boolean | `true` shows a full product card overlay; `false` acts as a transparent link |
+| `product_theme_id`| Integer/null | Product theme ID for product-type hotspots |
+| `rotation` | Float | Rotation in degrees |
+
+Additional fields are included depending on `type`:
+
+**`external_link`**
+
+| Field | Type | Description |
+| ----------------- | ------------ | --------------------------------------------- |
+| `url` | String | Target URL |
+| `popup_max_width` | Integer/null | Maximum popup width in pixels |
+| `popup_max_height`| Integer/null | Maximum popup height in pixels |
+
+**`page_reference`**
+
+| Field | Type | Description |
+| ------------- | ------- | ------------------------------------ |
+| `page_number` | Integer | Publication page number to link to |
+
+**`video`**
+
+| Field | Type | Description |
+| -------------------------------- | ------------ | ------------------------------------------------ |
+| `video_id` | String/null | Video ID (for hosted providers) |
+| `video_provider` | String/null | Video provider (e.g. `youtube`, `vimeo`) |
+| `video_url` | String/null | Direct video URL or file path |
+| `video_type` | String/null | Video type |
+| `video_autoplay` | Boolean | Whether the video autoplays on open |
+| `video_show_preview` | Boolean/null | Whether a preview thumbnail is shown |
+| `video_loop` | Boolean | Whether the video loops |
+| `video_start_time` | Integer/null | Start time in seconds |
+| `video_overlay_content` | Boolean | Whether the video overlays other content |
+| `video_show_accessibility_controls` | Boolean | Whether accessibility controls are shown |
+| `accessibility_text` | String/null | Accessible label for the video |
+
+**`image`**
+
+| Field | Type | Description |
+| -------------------- | ------------ | ----------------------------------------------------- |
+| `url` | String | Image URL |
+| `image_alt_text` | String/null | Alt text for the image |
+| `content_fit_mode` | String/null | How the image is fitted (`cover`, `contain`, etc.) |
+| `image_show_lightbox`| Boolean | Whether clicking opens the image in a lightbox |
+| `show_tooltip` | Boolean | Whether to show a tooltip |
+| `corner_radius` | Integer/null | Corner radius in pixels |
+| `opacity` | Float/null | Opacity (0–1) |
+| `image_crop_state` | Object/null | Crop state metadata |
+| `style_json` | Object/null | Custom style overrides |
+| `background_color` | String/null | Background color (hex); `null` when disabled |
+
+**`slideshow`**
+
+| Field | Type | Description |
+| -------- | ----- | ------------------------ |
+| `slides` | Array | Array of slide objects (see below) |
+
+Each slide object contains:
+
+| Field | Type | Description |
+| ------------------- | ------------ | ---------------------------------- |
+| `id` | Integer | Slide ID |
+| `hotspot_id` | Integer | Parent hotspot ID |
+| `position` | Integer | Display order |
+| `url` | String/null | External image URL |
+| `file_path` | String/null | Hosted file path |
+| `file_hosted` | Boolean | Whether the file is hosted |
+| `file_url` | String/null | Absolute URL to the hosted file |
+| `original_filename` | String/null | Original upload filename |
+| `alt_text` | String/null | Accessible alt text for the slide |
+
+**`product`**
+
+| Field | Type | Description |
+| ---------- | ----- | -------------------------------------------------------------- |
+| `products` | Array | Array of product objects serialized via the V2 Product schema |
+
+## Get a specific hotspot
+
+```shell
+curl "https://api.publitas.com/v2/spreads/42/hotspots/1" \
+ -H "Authorization: ApiKey "
+```
+
+> The above command returns JSON structured like this:
+
+```json
+{
+ "hotspot": {
+ "id": 1,
+ "type": "external_link",
+ "top": 0.1,
+ "left": 0.2,
+ "width": 0.15,
+ "height": 0.08,
+ "icon_left": 0.5,
+ "icon_top": 0.5,
+ "show_indication": true,
+ "tab_index": null,
+ "z_index": 0,
+ "embedded_content": false,
+ "dynamic": false,
+ "product_theme_id": null,
+ "rotation": 0.0,
+ "url": "https://example.com",
+ "popup_max_width": null,
+ "popup_max_height": null
+ }
+}
+```
+
+### HTTP Request
+
+`GET https://api.publitas.com/v2/spreads//hotspots/`
+
+### URL Parameters
+
+| Parameter | Description |
+| ---------- | ----------------------------------- |
+| Spread ID | The ID of a specific spread |
+| Hotspot ID | The ID of a specific hotspot |
+
+Returns 404 if the hotspot does not exist on the requested spread or belongs to a different spread.
+
+## Create a hotspot
+
+```shell
+curl "https://api.publitas.com/v2/spreads/42/hotspots" \
+ -H "Authorization: ApiKey " \
+ -H "Content-Type: application/json" \
+ --data '{
+ "type": "external_link",
+ "top": 0.1,
+ "left": 0.2,
+ "width": 0.15,
+ "height": 0.08,
+ "url": "https://example.com"
+ }'
+```
+
+> The above command returns JSON structured like this:
+
+```json
+{
+ "hotspot": {
+ "id": 99,
+ "type": "external_link",
+ "top": 0.1,
+ "left": 0.2,
+ "width": 0.15,
+ "height": 0.08,
+ "icon_left": 0.5,
+ "icon_top": 0.5,
+ "show_indication": true,
+ "tab_index": null,
+ "z_index": 0,
+ "embedded_content": false,
+ "dynamic": false,
+ "product_theme_id": null,
+ "rotation": 0.0,
+ "url": "https://example.com",
+ "popup_max_width": null,
+ "popup_max_height": null
+ }
+}
+```
+
+### HTTP Request
+
+`POST https://api.publitas.com/v2/spreads//hotspots`
+
+### URL Parameters
+
+| Parameter | Description |
+| --------- | ------------------------------- |
+| Spread ID | The ID of a specific spread |
+
+### Request body parameters
+
+**Core fields (all types)**
+
+| Field | Type | Required | Description |
+| ----------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------- |
+| `type` | String | Yes | Hotspot type: `external_link`, `page_reference`, `video`, `image`, `slideshow`, or `product` |
+| `top` | Float | Yes | Top offset as a fraction of spread height (0–1) |
+| `left` | Float | Yes | Left offset as a fraction of spread width (0–1) |
+| `width` | Float | Yes | Width as a fraction of spread width (0–1) |
+| `height` | Float | Yes | Height as a fraction of spread height (0–1) |
+| `show_indication` | Boolean | No | Whether the hotspot indication icon is visible |
+| `tab_index` | Integer | No | Accessibility tab order |
+| `embedded_content`| Boolean | No | Whether the hotspot renders its content inline |
+
+**`external_link` fields**
+
+| Field | Type | Required | Description |
+| ----------------- | ------- | -------- | ---------------------------------- |
+| `url` | String | Yes | Target URL |
+| `popup_max_width` | Integer | No | Maximum popup width in pixels |
+| `popup_max_height`| Integer | No | Maximum popup height in pixels |
+
+**`page_reference` fields**
+
+| Field | Type | Required | Description |
+| ------------- | ------- | -------- | ---------------------------------- |
+| `page_number` | Integer | Yes | Publication page number to link to |
+
+**`video` fields**
+
+| Field | Type | Required | Description |
+| -------------------------------- | ------- | -------- | ------------------------------------------------------ |
+| `video_url` | String | Yes | Video URL or file path |
+| `video_type` | String | No | Video type |
+| `video_provider` | String | No | Video provider (e.g. `youtube`, `vimeo`) |
+| `video_autoplay` | Boolean | No | Whether the video autoplays on open |
+| `video_loop` | Boolean | No | Whether the video loops |
+| `video_show_preview` | Boolean | No | Whether a preview thumbnail is shown |
+| `video_start_time` | Integer | No | Start time in seconds |
+| `video_overlay_content` | Boolean | No | Whether the video overlays other content |
+| `video_show_accessibility_controls` | Boolean | No | Whether accessibility controls are shown |
+| `accessibility_text` | String | No | Accessible label for the video |
+
+**`image` fields**
+
+| Field | Type | Required | Description |
+| -------------------- | ------- | -------- | ------------------------------------------------------- |
+| `url` | String | Yes | Image URL |
+| `image_alt_text` | String | No | Alt text for the image |
+| `image_add_alt_text` | Boolean | No | Whether to include alt text in the response |
+| `content_fit_mode` | String | No | How the image is fitted (`cover`, `contain`, etc.) |
+| `image_show_lightbox`| Boolean | No | Whether clicking opens the image in a lightbox |
+| `show_tooltip` | Boolean | No | Whether to show a tooltip |
+| `corner_radius` | Integer | No | Corner radius in pixels |
+| `opacity` | Float | No | Opacity (0–1) |
+
+### Response codes
+
+| Code | Description |
+| ---- | ---------------------------------- |
+| 201 | Hotspot created successfully |
+| 422 | Validation errors in request body |
+
# Errors
> When there is an error the command returns JSON structured like this: