# Sections de la page d'accueil

Votre application peut lire et modifier les sections de la page d'accueil d'une boutique. Une section est un bloc de la page d'accueil avec un type et des réglages. Dix types peuvent être ajoutés sur chaque thème : `category-products`, `featured`, `categories`, `banner`, `image-with-text`, `rich-text`, `trust-badges`, `testimonials`, `faq` et `video` ; un thème à sections comme `atlas` propose aussi `hero` et `product-grid`. Chaque écriture est en ligne sur la boutique dès qu'elle répond.

La référence complète des requêtes et des réponses se trouve dans la description OpenAPI, liée depuis la page [Référence de l'API](https://dzbuild.dev/fr/fr/api-reference.md) : `getStoreHomeLayout`, `addStoreHomeSection`, `updateStoreHomeSection`, `deleteStoreHomeSection`, `reorderStoreHomeSections` et `replaceStoreHomeLayout`. Cette page explique comment les pièces s'assemblent.

## Scopes[​](#scopes "Lien direct vers Scopes")

| Scope         | Autorise                                                                                                                                                                                            |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `store:read`  | `GET /v1/store/home-layout`                                                                                                                                                                         |
| `store:write` | `POST /v1/store/home-layout/sections`, `PATCH /v1/store/home-layout/sections/{id}`, `DELETE /v1/store/home-layout/sections/{id}`, `POST /v1/store/home-layout/reorder`, `PUT /v1/store/home-layout` |

Un appel sans le scope répond `403` avec le code `forbidden` et le message `Missing scope: store:write` (ou `store:read`). Voir [Scopes](https://dzbuild.dev/fr/fr/scopes.md).

## Lire la mise en page[​](#lire-la-mise-en-page "Lien direct vers Lire la mise en page")

`GET /v1/store/home-layout` renvoie :

| Champ          | Signification                                                                                                                                                                                                                                                                 |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `theme`        | La clé du thème de la boutique.                                                                                                                                                                                                                                               |
| `rendered`     | `false` quand le thème actuel de la boutique n'affiche pas les sections de l'accueil. Les sections sont gardées et réapparaissent sur un thème qui les affiche. Sur un thème à sections, il vaut `true` seulement tant qu'une section `product-grid` visible est enregistrée. |
| `max_sections` | 25, le nombre maximum de sections sur une page d'accueil.                                                                                                                                                                                                                     |
| `cap`          | Les sections que le plan de la boutique autorise : 3 sur Free ou un plan expiré, 25 à partir de Pro. Votre application s'installe sur des boutiques de tous les plans, lisez donc `cap` au lieu de supposer 25.                                                               |
| `version`      | Une empreinte de la mise en page enregistrée, pour `PUT`.                                                                                                                                                                                                                     |
| `sections`     | `{id, type, settings, is_active, available}` dans l'ordre d'affichage, sections masquées comprises. `available` vaut `false` quand le thème n'a plus ce type ; la section est gardée telle quelle.                                                                            |
| `types`        | Les types qu'on peut ajouter sur ce thème, chacun avec `name`, `description`, `icon`, `limit` et `settings_schema`.                                                                                                                                                           |

Construisez vos formulaires à partir de `settings_schema` au lieu de coder un type en dur : la liste dépend du thème de la boutique. Chaque réglage a un `id`, un `type` (`checkbox`, `range`, `select`, `text`, `textarea`, `color`, `link`, `image`, `category` ou `youtube`), un `default`, `min` et `max` ou `options` selon le cas, et `label` et `option_labels` en arabe et en français.

Les réglages de `category-products` sont `category` (un id de catégorie de `GET /v1/categories`, qui demande `products:read`), `title` (80 caractères au plus, vide il affiche le nom de la catégorie), `count` (de 4 à 12), `layout` (`grid` ou `slider`) et `show_view_all` (un lien vers la page de la catégorie).

Une section dont le contenu n'est pas encore rempli (aucune catégorie ou une catégorie sans produits, un `banner` sans `image`, un `image-with-text` sans `image` ou sans `title` ni `text`, un `rich-text`, `testimonials`, `faq` ou `video` vide) est enregistrée et l'écriture répond `2xx`, mais les acheteurs ne la voient pas tant qu'elle n'est pas remplie. `rendered` dit seulement si le thème affiche les sections enregistrées.

Un réglage `image` n'accepte que le chemin d'une image que le marchand a envoyée depuis le dashboard pour cette boutique (`/uploads/banners/{store_id}/...`) ou `""`. L'API ne peut pas envoyer d'image aujourd'hui : un `banner` ou un `image-with-text` demande donc d'abord cet envoi.

## Modifier la mise en page[​](#modifier-la-mise-en-page "Lien direct vers Modifier la mise en page")

Chaque écriture sauf `PUT` demande un en-tête `Idempotency-Key` (voir [Limites de requêtes](https://dzbuild.dev/fr/fr/rate-limits.md)).

```
POST /v1/store/home-layout/sections HTTP/1.1

Host: api.dzbuild.app

Authorization: Bearer dzpk_live_xxxxxxxx

Idempotency-Key: hs-add-64

Content-Type: application/json



{"type": "category-products", "settings": {"category": 64}, "position": 0}
```

L'appel répond `201` avec la nouvelle section et toute la mise en page :

```
{

  "data": {

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

    "sections": [

      {"id": 418, "type": "category-products", "settings": {"category": 64, "title": "", "count": 8, "layout": "grid", "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}

    ],

    "version": "e27a90c4b1f36d05",

    "change_id": 90231,

    "rendered": true

  },

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

}
```

| Opération                   | Corps                               | Notes                                                                                                                                                                                                                                       |
| --------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST .../sections`         | `{type, settings?, position?}`      | Les réglages non envoyés prennent les valeurs par défaut. `position` 0 est le haut ; sans lui, la section va à la fin.                                                                                                                      |
| `PATCH .../sections/{id}`   | `{settings?, is_active?, replace?}` | Les réglages sont fusionnés avec ceux enregistrés. `replace: true` remet les autres à leur valeur par défaut. `is_active: false` masque la section.                                                                                         |
| `DELETE .../sections/{id}`  | aucun                               | Répond `deleted: true` et l'`id` de la section.                                                                                                                                                                                             |
| `POST .../reorder`          | `{ids}`                             | Chaque id de section de la page une seule fois, sections masquées comprises.                                                                                                                                                                |
| `PUT /v1/store/home-layout` | `{sections, version?}`              | Toute la liste, 25 éléments au plus. Un élément avec un `id` garde cette section, un élément sans `id` en crée une, une section absente est supprimée. Ici `settings` est l'objet complet : un réglage omis revient à sa valeur par défaut. |

Chaque écriture renvoie toute la mise en page dans l'ordre d'affichage avec la nouvelle `version`, un `change_id` (`null` quand rien n'a changé) et `rendered`. Gardez cette réponse. Par `api.dzbuild.app`, un `GET` réussi est mis en cache 30 secondes par jeton et par chaîne de requête : un `GET` envoyé juste après une écriture peut donc renvoyer la mise en page d'avant. Ajoutez votre propre chaîne de requête quand vous devez relire.

Pour vérifier que personne n'a changé la page entre votre lecture et votre écriture, envoyez avec `PUT` la `version` que vous avez lue. Si la mise en page a bougé, l'appel répond `409 write_conflict` et n'écrit rien ; `error` porte alors les `sections` et la `version` actuelles pour réessayer à partir d'elles.

## Annulation[​](#annulation "Lien direct vers Annulation")

Les jetons d'installation ne peuvent pas appeler `/v1/changes` ni `POST /v1/changes/{id}/undo` : ils répondent `403` avec `Apps cannot use this endpoint`. Chaque écriture est quand même enregistrée, et le marchand peut l'annuler depuis la page de votre application dans son tableau de bord. Pour revenir en arrière dans votre application, gardez les `sections` lues avant le changement et renvoyez-les avec `PUT`. Une section que vous avez supprimée revient avec un nouvel id.

## Limites[​](#limites "Lien direct vers Limites")

* 25 sections par page d'accueil, et au plus `cap` selon le plan de la boutique. Les sections masquées comptent. Une boutique au-dessus de son plafond après un changement de plan garde ses sections ; une écriture qui laisse plus de sections que le plafond et plus qu'avant répond `403 plan_required`.
* Chaque type a une `limit` dans `types`, 12 pour `category-products`.
* 8 Ko de réglages par section une fois encodés, et 1 Mo par corps de requête.
* 30 écritures par minute et 5 en même temps par boutique, en plus du budget de votre installation et de celui de la boutique. Voir [Limites de requêtes](https://dzbuild.dev/fr/fr/rate-limits.md).

## Réponses et codes d'erreur[​](#réponses-et-codes-derreur "Lien direct vers Réponses et codes d'erreur")

| Statut | Code                                    | Signification                                                                                                                                                                                                                          |
| ------ | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  |                                         | Lu, modifié, supprimé, réordonné ou remplacé.                                                                                                                                                                                          |
| `201`  |                                         | Section ajoutée.                                                                                                                                                                                                                       |
| `400`  | `bad_request`                           | Le corps n'est pas un objet JSON, un champ a le mauvais type, l'id du chemin n'est pas un nombre positif, ou `Idempotency-Key` manque sur `POST`, `PATCH` ou `DELETE`.                                                                 |
| `403`  | `forbidden`                             | Le jeton n'a pas `store:read` ou `store:write`.                                                                                                                                                                                        |
| `403`  | `plan_required`                         | L'écriture laisserait plus de sections que le plan de la boutique n'en autorise. `error` porte `plan` et `cap`.                                                                                                                        |
| `404`  | `section_not_found`                     | Aucune section avec cet id sur la page d'accueil de la boutique.                                                                                                                                                                       |
| `409`  | `write_conflict`                        | Une autre écriture a changé la mise en page avant, ou la `version` envoyée sur `PUT` n'est pas l'actuelle. Quand `error` porte `sections` et `version`, repartez d'elles ; sinon, relisez. Réessayez avec une nouvelle clé.            |
| `413`  | `payload_too_large`                     | Le corps dépasse 1 Mo.                                                                                                                                                                                                                 |
| `422`  | `invalid_settings`                      | Une valeur a été refusée. `error.fields` liste les réglages refusés, par exemple `settings.category` ; sur `PUT`, ceux de la première section refusée seulement, par exemple `sections.2.settings.layout`. Le message les nomme aussi. |
| `422`  | `invalid_section_type`                  | Le type n'existe pas ou ne peut pas être ajouté sur ce thème.                                                                                                                                                                          |
| `422`  | `limit_reached`                         | Plus de 25 sections, ou plus de sections d'un type que sa `limit`.                                                                                                                                                                     |
| `422`  | `invalid_order`                         | Les `ids` du réordonnancement oublient une section ou en répètent une.                                                                                                                                                                 |
| `422`  | `no_changes`                            | Un `PATCH` sans `settings` ni `is_active`.                                                                                                                                                                                             |
| `429`  | `rate_limited` ou `too_many_concurrent` | Un budget par minute est épuisé, ou 5 écritures de mise en page de l'accueil sont déjà en cours pour la boutique. Attendez `retry_after` secondes.                                                                                     |

Voir [Erreurs](https://dzbuild.dev/fr/fr/errors.md) pour les codes que tout appel peut recevoir, comme `app_uninstalled`.
