---
title: "Make an element a shared section"
method: POST
path: "/api/v1/sites/{slug}/shared-sections"
tags: ["Content"]
---

# Make an element a shared section

`POST /api/v1/sites/{slug}/shared-sections`

## Request

- Base URL: `https://api.dotsy.ai`
- URL: `https://api.dotsy.ai/api/v1/sites/{slug}/shared-sections`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

Saves the element as `fragments/<name>.html` and replaces it with a reference on the source page and on the pages you include — or, with `every_page`, puts one reference in the layout instead. All pages change together or none do. Staged as a draft, recorded as one activity event (undo it from there). A retry of a share that already happened answers `alreadyApplied`. Sharing again under the name of a section that holds this same block adds the pages to it. With `selectors`, a run of elements next to each other becomes one section inside a wrapper (`wrapTag`, `keepLayout`), and every page with the same run gets the reference in its place.

## Path parameters

- `slug` string, required

## Request body

- ShareSectionRequest
  - `sourceKey` string, required: Content key of the page the element is on, e.g. 'about.html'.
  - `selector` string: CSS selector of the element in the page's stored HTML (the editor's selector, or one checked with get_content?selector=). It must match exactly one element.
  - `ifMatch` string: The page's content hash (analyze's sourceEtag). If the page changed since, nothing is written.
  - `name` string: Name of the new section. Default: analyze's proposedName. A name in use answers 409 section_name_taken.
  - `scope` 'where_found' | 'every_page': where_found: each page that has it gets a reference. every_page: one slot in the layout, at the top or bottom of the page content; pages listed in `hide` don't show it.
  - `keys` string[]: Pages with an exact copy to share it on (analyze's matches.keys). Omit for every exact copy. The source page is always included.
  - `similar` string[]: Pages with a similar copy (analyze's similar.keys) that take the shared version, losing their own wording. Default none.
  - `hide` string[]: every_page only: pages on the layout that should not show it. Default none.
  - `selectors` string[]: A run of elements that sit next to each other in one parent (only whitespace or comments between), in page order — instead of `selector`. Each must match exactly one element. The section is the run inside one wrapper (`wrapTag`); the pages that hold the same run (the same elements, in the same order, next to each other) take it.
  - `wrapTag` 'div' | 'section' | 'footer' | 'header' | 'article' | 'aside': With `selectors`: the wrapper element. Default `footer` when the run is the last of the page content, else `section`.
  - `keepLayout` boolean: With `selectors`: give the wrapper style="display:contents" so a flex or grid parent still lays out the run's elements as before. Default true.

## Response `200`

Shared (staged as a draft).

- ShareSectionResult
  - `name` string, required
  - `key` string, required
  - `scope` 'where_found' | 'every_page', required
  - `pages` integer, required: Pages that show it now.
  - `hidden` integer, required: every_page: pages on the layout that hide it.
  - `skipped` object[], required: Pages left alone. `ambiguous_similar`: none or several similar copies on the page; on every page such a page hides the section (it keeps its own copies, and counts in `hidden`). `not_a_match` (`selectors` only): the index listed the page but its stored HTML doesn't hold the same run of elements, so it keeps what it has.
    - `key` string, required
    - `reason` 'ambiguous_similar' | 'not_a_match', required
  - `written` string[], required: Every content key this call staged (or, on a dry run, would stage): the section file, pages, the layout. Staged as a draft; in live publishing mode the dashboard then publishes exactly these keys.
  - `alreadyApplied` boolean, required: True on a retry of a share that already happened: nothing was written.
  - `eventId` string, nullable, required: The activity event of this change — undo with POST …/activity/{eventId}/revert. Null on a dry run, when nothing was written, or when the audit insert failed.

## Other responses

- `400`: The body or selector is not valid, or the change needs more pages than one call can change (`too_many_pages`, with `max`).
- `401`: Missing or invalid credentials.
- `403`: The key or token cannot edit this site (viewer role, or AI access set to read only).
- `404`: No such site, or the page (`content_not_found`).
- `409`: A page changed (`shared_section_conflict`, nothing written), or the name is in use (`section_name_taken`, with `suggestion`). `index_warming`: the index is not ready yet — retry in a minute.
- `422`: The element or page can't take part (`not_eligible`, with `reason`), the selector matched 0 or 2+ elements (`unexpected_match_count`), or `selectors` don't sit next to each other in one parent, in page order (`not_siblings`).

---

[API](https://skmtc.dev/dotsy/apis/dotsy-api.md) · [All operations](https://skmtc.dev/dotsy/apis/dotsy-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dotsy/apis/dotsy-api/revisions/4272ed3b85d7?raw)
