# Home page sections

The home layout is the ordered list of sections a store shows on its home page. Each section has a type and settings. Ten types can be added on every theme: `category-products`, `featured`, `categories`, `banner`, `image-with-text`, `rich-text`, `trust-badges`, `testimonials`, `faq` and `video`. A section theme such as `atlas` also offers `hero` and `product-grid`. `types` in the `GET` answer gives the settings of each. Every write on this page is live on the store as soon as it answers.

This is not `GET /v1/store/home-sections`, which reads the switches of the Digital, Ariana and Prestige home pages. Those switches are described at the end of this page.

## Before you start

* `GET` needs `store:read` and the writes need `store:write`. Merchant keys carry both.
* `POST`, `PATCH` and `DELETE` need an `Idempotency-Key`. On `PUT` it is optional. See [Idempotency](https://dzbuild.com/api-docs/idempotency.md).
* A category id comes from `GET /v1/categories`, which needs `products:read`.

## The section object

| Field       | Type   | Notes                                                                                                          |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------- |
| `id`        | int    | Stable while the section exists. A section that comes back through an undo gets a new id.                      |
| `type`      | string | One of the `type` values listed in `types` by `GET /v1/store/home-layout`.                                     |
| `settings`  | object | Every setting of the type, with the defaults filled in.                                                        |
| `is_active` | bool   | `false` hides the section from buyers and keeps it in the list.                                                |
| `available` | bool   | `false` when the store's theme no longer has this type. The section is kept as stored and a write may keep it. |

### Settings of `category-products`

| Setting         | Type        | Default | Rules                                                                                                                                          |
| --------------- | ----------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `category`      | category id | `0`     | A category of this store. `0` means none, and the section then shows nothing to buyers. An id of another store answers `422 invalid_settings`. |
| `title`         | text        | `""`    | Up to 80 characters, HTML removed. Empty shows the category name.                                                                              |
| `count`         | range       | `8`     | 4 to 12. A number outside that range is moved to the nearest end.                                                                              |
| `layout`        | select      | `grid`  | `grid` or `slider`.                                                                                                                            |
| `show_view_all` | checkbox    | `true`  | A link to the category page.                                                                                                                   |

A category with no products shows nothing to buyers either. Read the rules of any type from its `settings_schema` rather than hard-coding them: the list of types depends on the store's theme.

### Setting formats

| Setting type | Accepted value                                                                                                                                                                                                                                                     |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `category`   | An id from `GET /v1/categories`, or `0` for none.                                                                                                                                                                                                                  |
| `link`       | `#anchor`, a `/path` on the store, an `http://` or `https://` address, or a `tel:` or `mailto:` link, up to 500 characters, or `""`. An address sent without its scheme, such as `wa.me/213...`, is stored with `https://` in front.                               |
| `youtube`    | A YouTube video link or its 11-character id. The id is stored.                                                                                                                                                                                                     |
| `image`      | The path of an image uploaded in the dashboard for this store, `/uploads/banners/{store_id}/...`, or `""`. The API cannot upload images today: the merchant uploads the picture in the section's settings in the dashboard first, and `GET` then returns its path. |

### When buyers see a section

A section whose content is not filled in yet is stored and the write answers `2xx`, but buyers do not see it until it is:

| Type                | Buyers see it once                                                                   |
| ------------------- | ------------------------------------------------------------------------------------ |
| `category-products` | `category` is a category of the store that has products.                             |
| `featured`          | the chosen `source` has products.                                                    |
| `categories`        | the store has a category with products, or any category when `show_empty` is `true`. |
| `banner`            | `image` is set.                                                                      |
| `image-with-text`   | `image` is set, with a `title` or a `text`.                                          |
| `rich-text`         | `title` or `text` is set.                                                            |
| `trust-badges`      | always. Empty badges 1 and 2 show the default delivery and cash on delivery lines.   |
| `testimonials`      | at least one `tN_text` is set.                                                       |
| `faq`               | at least one `qN` is set with its `aN`.                                              |
| `video`             | `video` holds a YouTube id.                                                          |

`rendered` does not change for this: it says whether the theme shows stored sections, not whether one section is visible. On a section theme (`atlas`), saved sections replace the theme's own home only while they include a visible `product-grid` section, and `rendered` is `false` until then; buyers see the theme's home, and `GET` lists only the saved sections, not the theme's own.

## `GET /v1/store/home-layout`

The sections in render order, the section types that can be added on the store's theme, and the plan cap.

**Auth:** platform key with `store:read`.

### Request

```
curl 'https://api.dzbuild.app/v1/store/home-layout' \

  -H "Authorization: Bearer $DZ_KEY"
```

### Response 200

```
{

  "data": {

    "theme": "starter",

    "rendered": true,

    "max_sections": 25,

    "cap": 25,

    "version": "9c1e04b7a2d35f68",

    "sections": [

      {

        "id": 412,

        "type": "category-products",

        "settings": {

          "category": 57,

          "title": "",

          "count": 8,

          "layout": "grid",

          "show_view_all": true

        },

        "is_active": true,

        "available": true

      },

      {

        "id": 415,

        "type": "category-products",

        "settings": {

          "category": 61,

          "title": "Nos parfums",

          "count": 10,

          "layout": "slider",

          "show_view_all": false

        },

        "is_active": false,

        "available": true

      }

    ],

    "types": [

      {

        "type": "category-products",

        "name": {"ar": "منتجات فئة", "fr": "Produits d'une catégorie"},

        "description": {"ar": "اعرض منتجات فئة واحدة في شبكة أو شريط تمرير.", "fr": "Affichez les produits d'une catégorie en grille ou en carrousel."},

        "icon": "bi-grid-3x3-gap",

        "limit": 12,

        "settings_schema": [

          {"id": "category", "type": "category", "default": 0, "label": {"ar": "الفئة", "fr": "Catégorie"}},

          {"id": "title", "type": "text", "max": 80, "default": "", "label": {"ar": "العنوان (إذا تركته فارغاً يظهر اسم الفئة)", "fr": "Titre (si vide, le nom de la catégorie s'affiche)"}},

          {"id": "count", "type": "range", "min": 4, "max": 12, "default": 8, "label": {"ar": "عدد المنتجات", "fr": "Nombre de produits"}},

          {"id": "layout", "type": "select", "options": ["grid", "slider"], "default": "grid", "label": {"ar": "طريقة العرض", "fr": "Affichage"}, "option_labels": {"ar": ["شبكة", "شريط تمرير"], "fr": ["Grille", "Carrousel"]}},

          {"id": "show_view_all", "type": "checkbox", "default": true, "label": {"ar": "زر عرض الكل", "fr": "Lien « Voir tout »"}}

        ]

      }

    ]

  },

  "meta": {"request_id": "8f2c1a9d4b7e6035", "api_version": "v1"}

}
```

| Field          | Meaning                                                                                                                                                                                                                   |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `theme`        | The store's theme key.                                                                                                                                                                                                    |
| `rendered`     | `false` when the store's current theme does not show home page sections. The sections are kept and show again on a theme that does. On a section theme it is `true` only while a visible `product-grid` section is saved. |
| `max_sections` | 25, the most sections one home page holds.                                                                                                                                                                                |
| `cap`          | The sections the store's plan allows: 3 on Free or an expired plan, 25 from Pro.                                                                                                                                          |
| `version`      | A fingerprint of the stored layout. Send it back as `version` on `PUT` to refuse a layout that changed since this read.                                                                                                   |
| `sections`     | The sections in render order, hidden ones included.                                                                                                                                                                       |
| `types`        | The types that can be added on this theme, with `name`, `description`, `icon`, `limit` (the most sections of that type one page holds) and `settings_schema`. The sample above shows one of them.                         |

### Reading after a write

Through `api.dzbuild.app` every `GET` is served fresh: a `GET` sent right after a write returns the new layout. You rarely need it, because every write returns the whole list in render order with the new `version`.

## `POST /v1/store/home-layout/sections`

Adds one section.

**Auth:** platform key with `store:write`. **Requires `Idempotency-Key`.**

### Body

| Field      | Type   | Required | Notes                                                                                        |
| ---------- | ------ | -------- | -------------------------------------------------------------------------------------------- |
| `type`     | string | yes      | A `type` from `types`.                                                                       |
| `settings` | object | no       | Settings you do not send take the type's defaults.                                           |
| `position` | int    | no       | 0 puts the section at the top, 24 is the last place. Without it the section goes at the end. |

### Request

```
curl -X POST 'https://api.dzbuild.app/v1/store/home-layout/sections' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: hs-add-sacs-1" \

  -d '{"type": "category-products", "settings": {"category": 64, "layout": "slider"}, "position": 0}'
```

### Response 201

```
{

  "data": {

    "section": {

      "id": 418,

      "type": "category-products",

      "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true},

      "is_active": true,

      "available": true

    },

    "sections": [

      {"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true}, "is_active": true, "available": true},

      {"id": 412, "type": "category-products", "settings": {"category": 57, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true},

      {"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 10, "layout": "slider", "show_view_all": false}, "is_active": false, "available": true}

    ],

    "version": "e27a90c4b1f36d05",

    "change_id": 90231,

    "rendered": true

  },

  "meta": {"request_id": "3b7d0e5a9c14f862", "api_version": "v1"}

}
```

## `PATCH /v1/store/home-layout/sections/{id}`

Changes one section. The settings you send are merged over the stored ones. Send `settings`, `is_active` or both.

**Auth:** platform key with `store:write`. **Requires `Idempotency-Key`.**

### Body

| Field       | Type   | Required | Notes                                                                        |
| ----------- | ------ | -------- | ---------------------------------------------------------------------------- |
| `settings`  | object | no       | Merged over the stored settings.                                             |
| `is_active` | bool   | no       | `false` hides the section, `true` shows it.                                  |
| `replace`   | bool   | no       | With `settings`, `true` resets every setting you do not send to its default. |

### Request

```
curl -X PATCH 'https://api.dzbuild.app/v1/store/home-layout/sections/415' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: hs-415-show-1" \

  -d '{"settings": {"count": 6}, "is_active": true}'
```

### Response 200

The answer has the same fields as the `POST` answer: `section` (the section after the change), `sections`, `version`, `change_id` and `rendered`.

```
{

  "data": {

    "section": {

      "id": 415,

      "type": "category-products",

      "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false},

      "is_active": true,

      "available": true

    },

    "sections": [

      {"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true}, "is_active": true, "available": true},

      {"id": 412, "type": "category-products", "settings": {"category": 57, "title": "", "count": 8, "layout": "grid", "show_view_all": true}, "is_active": true, "available": true},

      {"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false}, "is_active": true, "available": true}

    ],

    "version": "51d8c3e06fa2b974",

    "change_id": 90232,

    "rendered": true

  },

  "meta": {"request_id": "c90a6e1f2d7b4538", "api_version": "v1"}

}
```

## `DELETE /v1/store/home-layout/sections/{id}`

Removes one section.

**Auth:** platform key with `store:write`. **Requires `Idempotency-Key`.**

### Request

```
curl -X DELETE 'https://api.dzbuild.app/v1/store/home-layout/sections/412' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Idempotency-Key: hs-del-412-1"
```

### Response 200

```
{

  "data": {

    "deleted": true,

    "id": 412,

    "sections": [

      {"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "slider", "show_view_all": true}, "is_active": true, "available": true},

      {"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false}, "is_active": true, "available": true}

    ],

    "version": "0f6b2d9e84a1c357",

    "change_id": 90233,

    "rendered": true

  },

  "meta": {"request_id": "71e4b08c3a5d9f26", "api_version": "v1"}

}
```

## `POST /v1/store/home-layout/reorder`

Sets the render order. `ids` lists every section of the page exactly once, hidden ones included.

**Auth:** platform key with `store:write`. **Requires `Idempotency-Key`.**

### Request

```
curl -X POST 'https://api.dzbuild.app/v1/store/home-layout/reorder' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: hs-order-2" \

  -d '{"ids": [415, 418]}'
```

### Response 200

The answer carries `sections` in the new order, `version`, `change_id` and `rendered`. An id that is not on the page answers `404 section_not_found`. A missing or repeated id answers `422 invalid_order`.

## `PUT /v1/store/home-layout`

Replaces the whole layout with the list you send, in that order.

**Auth:** platform key with `store:write`. `Idempotency-Key` is optional.

### Body

| Field      | Type   | Required | Notes                                                                                                                                                                  |
| ---------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sections` | array  | yes      | At most 25 items, each `{id?, type, settings?, is_active?}`. An empty list removes every section.                                                                      |
| `version`  | string | no       | The `version` from your last read. When the layout changed since, the call answers `409 write_conflict` with the current `sections` and `version`, and writes nothing. |

How each item is read:

* An item with an `id` keeps that section. Its `type` must be the section's current type.
* An item without an `id` creates a section.
* A section of the page that is not in the list is deleted.
* `settings` is the whole object: a setting you leave out goes back to its default. Send the full settings of every section you keep.
* `is_active` defaults to `true`.

### Request

```
curl -X PUT 'https://api.dzbuild.app/v1/store/home-layout' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: hs-replace-7" \

  -d '{

    "version": "0f6b2d9e84a1c357",

    "sections": [

      {"id": 415, "type": "category-products", "settings": {"category": 61, "title": "Nos parfums", "count": 6, "layout": "slider", "show_view_all": false}},

      {"type": "category-products", "settings": {"category": 57}}

    ]

  }'
```

### Response 200

The answer carries `sections`, `version`, `change_id` and `rendered`. Section 418 was left out, so it is deleted. Sending back the layout you read, unchanged, answers `change_id: null`.

With an `Idempotency-Key`, a retry with the same key and the same body gets the stored answer back for 24 hours with `Idempotency-Replay: 1`, and the same key with another body answers `422 idempotency_key_reuse`. Without a key the call runs every time, which is safe: sending the same list twice leaves the same layout.

## Undo

Every write answers with a `change_id`, or `null` when it changed nothing. `POST /v1/changes/{change_id}/undo` puts the whole home page back as it was before that change.

* An added section can be undone too: the undo removes it. For other resources, undo refuses a change that created something.
* If the home page changed after that change, through the API or in the dashboard, the undo answers `409 layout_changed` and writes nothing. Read the layout and write what you want directly.
* A section that comes back after a delete gets a new id.
* The undo is recorded as a change of its own, `undo_change_id`, which you can undo in turn. Undoing the undo of a delete answers `409 layout_changed`, because the section came back with a new id.
* Changes the merchant saves in the dashboard are not recorded, so they cannot be undone through the API.
* `GET /v1/changes?entity=store.home_layout` lists the home layout changes, newest first, with `store:read`.
* An installed app's token cannot read or undo changes: `GET /v1/changes` and the undo answer `403 forbidden` (`Apps cannot use this endpoint`). Write answers still carry the `change_id`.
* The undo answer does not carry the layout. Read it again with `GET /v1/store/home-layout`; the read is served fresh.

The undo needs `store:write` and an `Idempotency-Key`.

```
curl -X POST 'https://api.dzbuild.app/v1/changes/90231/undo' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Idempotency-Key: undo-90231"
```

```
{

  "data": {

    "undone": true,

    "change_id": 90231,

    "entity": "store.home_layout",

    "undo_change_id": 90240

  },

  "meta": {"request_id": "5ad2f7c01e9b8634", "api_version": "v1"}

}
```

A change undone a second time answers `409 already_undone`.

## Errors

| HTTP | Code                    | Cause                                                                                                                                                                                                                                                                                                                                                                      |
| ---- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `bad_request`           | The body is not a JSON object, a field has the wrong type (`type` missing, `settings` not an object, `is_active` or `replace` not a boolean, `position` outside 0 to 24, `ids` not an array of section ids, `version` not a string), the section id in the path is not a positive number, or `Idempotency-Key` is missing or malformed on `POST`, `PATCH` or `DELETE`.     |
| 401  | `unauthorized`          | Bad or missing key.                                                                                                                                                                                                                                                                                                                                                        |
| 402  | `quota_exceeded`        | The store's monthly request quota is used up. See [Rate limits](https://dzbuild.com/api-docs/rate-limits.md).                                                                                                                                                                                                                                                              |
| 403  | `forbidden`             | `Missing scope: store:read` or `Missing scope: store:write`, or `API access requires an active Enterprise plan` for a merchant key whose store is not on an active Enterprise plan.                                                                                                                                                                                        |
| 403  | `plan_required`         | The write would leave more sections than the plan allows. The error carries `plan` and `cap`.                                                                                                                                                                                                                                                                              |
| 404  | `section_not_found`     | No section with this id on the page.                                                                                                                                                                                                                                                                                                                                       |
| 409  | `write_conflict`        | Another write landed first, or the `version` sent on `PUT` is not the current one. When the error carries `sections` and `version`, they are the current layout: retry from them. Otherwise read the layout and retry.                                                                                                                                                     |
| 409  | `layout_changed`        | Undo only: the home page changed after this change.                                                                                                                                                                                                                                                                                                                        |
| 409  | `already_undone`        | Undo only: the change was already undone.                                                                                                                                                                                                                                                                                                                                  |
| 413  | `payload_too_large`     | The body is over 1 MB.                                                                                                                                                                                                                                                                                                                                                     |
| 422  | `invalid_settings`      | A value was refused. `fields` lists every refused setting of the section, such as `settings.category`. On `PUT` it lists those of the first refused section only, such as `sections.2.settings.layout`, and it also covers an `id` that is not on the page (`sections.N.id`) and a kept section sent with another type (`sections.N.type`). `message` names the paths too. |
| 422  | `invalid_section_type`  | The type does not exist or cannot be added on this theme. `fields` gives the path.                                                                                                                                                                                                                                                                                         |
| 422  | `limit_reached`         | More than 25 sections, or more of one type than its `limit`. The error carries `limit`, except when a `PUT` sends more than 25 items.                                                                                                                                                                                                                                      |
| 422  | `invalid_order`         | Reorder `ids` miss a section or repeat one.                                                                                                                                                                                                                                                                                                                                |
| 422  | `no_changes`            | A `PATCH` without `settings` or `is_active`.                                                                                                                                                                                                                                                                                                                               |
| 422  | `idempotency_key_reuse` | The same `Idempotency-Key` was used with another body.                                                                                                                                                                                                                                                                                                                     |
| 429  | `rate_limited`          | Too many requests, including more than 30 home layout writes a minute for the store. Wait for `Retry-After`.                                                                                                                                                                                                                                                               |
| 429  | `too_many_concurrent`   | More than 5 home layout writes running at once for the store. Retry in a few seconds.                                                                                                                                                                                                                                                                                      |
| 500  | `server_error`          | The request failed. Retry with the same `Idempotency-Key`.                                                                                                                                                                                                                                                                                                                 |

An `invalid_settings` answer looks like this.

```
{

  "error": {

    "code": "invalid_settings",

    "message": "Invalid value at settings.category: category not found in this store; accepted values are in settings_schema of GET /v1/store/home-layout",

    "fields": [{"path": "settings.category", "code": "invalid"}]

  },

  "meta": {"request_id": "e4c19a0b7d2f5836", "api_version": "v1"}

}
```

## Limits

* **25 sections** per home page (`max_sections`).
* **Plan cap** (`cap`): 3 sections on Free or an expired plan, 25 from Pro. Hidden sections count. A store above its cap after a downgrade keeps its sections and can still edit, hide, reorder and delete them. A write that leaves more sections than the cap and more than before answers `403 plan_required`.
* **Per type**: each type has a `limit` in `types`, 12 for `category-products`.
* **Settings**: 8 KB per section once encoded. Longer text is cut to the setting's `max`.
* **Body**: 1 MB.
* **Writes**: 30 a minute and 5 at once per store, on top of the store's per-minute limit. See [Rate limits](https://dzbuild.com/api-docs/rate-limits.md).

## Home page switches of Digital, Ariana and Prestige

The Digital, Ariana and Prestige themes build their home page from fixed blocks. An older set of switches shows or hides those blocks and sets their titles, categories and banners. `GET` and `PATCH /v1/store/home-sections` read and change these switches. They are stored apart from the home layout above, so a write on one never changes the other.

| Theme           | Keys it reads                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Digital, Ariana | `show_hero_slider`, `hero_slides`, `show_sidebar_widget`, `sidebar_widget_title`, `sidebar_widget_category_id`, `show_category_cards`, `show_top_sellers`, `top_sellers_title`, `show_popular_by_category`, `popular_by_category_title`, `show_promo_banners`, `banner_1_*` and `banner_2_*` (`title`, `subtitle`, `button_text`, `button_link`, `image`), `show_multi_column_lists`, `column_1_title` to `column_4_title`, `column_1_category_id` to `column_4_category_id`, `section_order` |
| Prestige        | `show_testimonials`, `testimonials_title`, `testimonials`                                                                                                                                                                                                                                                                                                                                                                                                                                     |

No other theme reads these switches: on another theme a write is saved and answers `200`, and buyers see no change. A switch that was never saved is missing from the answer, and Digital and Ariana then show its block while Prestige hides its testimonials. `section_order` sets the order of the Digital and Ariana blocks with the values `hero_slider`, `category_cards`, `top_sellers`, `popular_by_category`, `promo_banners` and `multi_column_lists`. A block left out of that list is not shown.

### `GET /v1/store/home-sections`

**Auth:** platform key with `store:read`. Like `GET /v1/store/home-layout`, the answer is served fresh on every call.

```
curl 'https://api.dzbuild.app/v1/store/home-sections' \

  -H "Authorization: Bearer $DZ_KEY"
```

```
{

  "data": {

    "theme": "digital",

    "settings": {"show_top_sellers": 1, "top_sellers_title": "Meilleures ventes", "column_1_category_id": 57}

  },

  "meta": {"request_id": "...", "api_version": "v1"}

}
```

`settings` holds only the keys that were saved. A store that never saved any answers `"settings": []`.

### `PATCH /v1/store/home-sections`

**Auth:** platform key with `store:write`. **Requires `Idempotency-Key`.**

Send only the keys to change: the others keep their value, and unknown keys are ignored. `show_*` keys are stored as `1` or `0`. A `*_category_id` takes a category of this store, and `0` clears it. Text is trimmed and cut to 500 characters, `testimonials_title` to 200. `banner_1_button_link` and `banner_2_button_link` take an `https://`, `http://`, `mailto:` or `tel:` link, a `/path` or an `#anchor`. `testimonials` keeps up to 24 entries, each with `name`, `comment` and `stars` from 1 to 5.

```
curl -X PATCH 'https://api.dzbuild.app/v1/store/home-sections' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: hs-top-sellers-off-1" \

  -d '{"show_top_sellers": false, "column_1_category_id": 61}'
```

```
{

  "data": {

    "updated": ["show_top_sellers", "column_1_category_id"],

    "settings": {"show_top_sellers": 0, "top_sellers_title": "Meilleures ventes", "column_1_category_id": 61}

  },

  "meta": {"request_id": "...", "api_version": "v1"}

}
```

`updated` lists the keys written, and `settings` holds every saved key after the write. The answer has no `change_id`: `GET /v1/changes?entity=store.home_sections` lists these changes, and `POST /v1/changes/{change_id}/undo` undoes one. Undoing the first write of a key does not bring back its default: a `show_*` switch comes back as `0` and `section_order` as `[]`, which on Digital and Ariana hides that block, or every block. To go back to the defaults, send `1` or the full `section_order` list with `PATCH`.

| HTTP | Code                    | Cause                                                                                                                                                                               |
| ---- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `bad_request`           | The body is not JSON, or `Idempotency-Key` is missing or malformed.                                                                                                                 |
| 403  | `forbidden`             | `Missing scope: store:read` or `Missing scope: store:write`, or `API access requires an active Enterprise plan` for a merchant key whose store is not on an active Enterprise plan. |
| 422  | `no_writable_fields`    | The body holds none of the keys this endpoint accepts.                                                                                                                              |
| 422  | `invalid_category`      | A `*_category_id` is not a category of this store.                                                                                                                                  |
| 422  | `invalid_url`           | A button link uses another scheme, such as `javascript:`.                                                                                                                           |
| 422  | `idempotency_key_reuse` | The same `Idempotency-Key` was used with another body.                                                                                                                              |

`401`, `402`, `413` and `500` mean the same as for the home layout writes. `429 rate_limited` comes only from the general per-minute limits in [Rate limits](https://dzbuild.com/api-docs/rate-limits.md): the home layout write limits do not apply here.
