Aller au contenu principal

Sections de la page d'accueil

La mise en page de l'accueil est la liste ordonnée des sections qu'une boutique affiche sur sa page d'accueil. Chaque section a 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. types dans la réponse du GET donne les réglages de chacun. Chaque écriture de cette page est en ligne sur la boutique dès qu'elle répond.

Ce n'est pas GET /v1/store/home-sections, qui lit les interrupteurs des pages d'accueil Digital, Ariana et Prestige.

Avant de commencer​

  • GET demande store:read et les écritures demandent store:write. Les clés marchand ont les deux.
  • POST, PATCH et DELETE demandent une Idempotency-Key. Sur PUT, elle est facultative. Voir Idempotence.
  • L'id d'une catégorie vient de GET /v1/categories, qui demande products:read.

L'objet section​

ChampTypeNotes
idintStable tant que la section existe. Une section qui revient par une annulation reçoit un nouvel id.
typestringL'une des valeurs type listées dans types par GET /v1/store/home-layout.
settingsobjectTous les réglages du type, valeurs par défaut comprises.
is_activeboolfalse masque la section aux acheteurs et la garde dans la liste.
availableboolfalse quand le thème de la boutique n'a plus ce type. La section est gardée telle quelle et une écriture peut la conserver.

Réglages de category-products​

RéglageTypeDéfautRègles
categoryid de catégorie0Une catégorie de cette boutique. 0 veut dire aucune, et la section n'affiche alors rien aux acheteurs. L'id d'une autre boutique répond 422 invalid_settings.
titletext""Jusqu'à 80 caractères, HTML retiré. Vide, il affiche le nom de la catégorie.
countrange8De 4 à 12. Un nombre hors de cet intervalle est ramené à la borne la plus proche.
layoutselectgridgrid ou slider.
show_view_allcheckboxtrueUn lien vers la page de la catégorie.

Une catégorie sans produits n'affiche rien aux acheteurs non plus. Lisez les règles de chaque type dans son settings_schema au lieu de les coder en dur : la liste des types dépend du thème de la boutique.

Formats des réglages​

Type de réglageValeur acceptée
categoryUn id de GET /v1/categories, ou 0 pour aucune.
link#ancre, un /chemin de la boutique, une adresse http:// ou https://, ou un lien tel: ou mailto:, 500 caractères au plus, ou "". Une adresse envoyée sans son préfixe, comme wa.me/213..., est enregistrée avec https:// devant.
youtubeUn lien de vidéo YouTube ou son identifiant de 11 caractères. L'identifiant est enregistré.
imageLe chemin d'une image envoyée depuis le dashboard pour cette boutique, /uploads/banners/{store_id}/..., ou "". L'API ne peut pas envoyer d'image aujourd'hui : le marchand envoie d'abord l'image dans les réglages de la section, dans le dashboard, puis GET renvoie son chemin.

Quand les acheteurs voient une section​

Une section dont le contenu n'est pas encore rempli est enregistrée et l'écriture répond 2xx, mais les acheteurs ne la voient pas tant qu'il ne l'est pas :

TypeLes acheteurs la voient dès que
category-productscategory est une catégorie de la boutique qui a des produits.
featuredla source choisie a des produits.
categoriesla boutique a une catégorie avec des produits, ou n'importe quelle catégorie quand show_empty vaut true.
bannerimage est rempli.
image-with-textimage est rempli, avec un title ou un text.
rich-texttitle ou text est rempli.
trust-badgestoujours. Les badges 1 et 2 vides affichent les lignes par défaut de livraison et de paiement à la livraison.
testimonialsau moins un tN_text est rempli.
faqau moins un qN est rempli avec son aN.
videovideo contient un identifiant YouTube.

rendered ne change pas pour autant : il dit si le thème affiche les sections enregistrées, pas si une section précise est visible. Sur un thème à sections (atlas), les sections enregistrées remplacent l'accueil du thème seulement tant qu'elles contiennent une section product-grid visible, et rendered vaut false jusque-là ; avant, les acheteurs voient l'accueil du thème, et le GET ne liste que les sections enregistrées, pas celles du thème.

GET /v1/store/home-layout​

Les sections dans l'ordre d'affichage, les types de section qu'on peut ajouter sur le thème de la boutique, et le plafond du plan.

Auth : clé plateforme avec store:read.

Requête​

curl 'https://api.dzbuild.app/v1/store/home-layout' \
-H "Authorization: Bearer $DZ_KEY"

Réponse 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"}
}
ChampSignification
themeLa clé du thème de la boutique.
renderedfalse 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_sections25, le nombre maximum de sections sur une page d'accueil.
capLes sections que le plan de la boutique autorise : 3 sur Free ou un plan expiré, 25 à partir de Pro.
versionUne empreinte de la mise en page enregistrée. Renvoyez-la dans version sur PUT pour refuser une mise en page qui a changé depuis cette lecture.
sectionsLes sections dans l'ordre d'affichage, sections masquées comprises.
typesLes types qu'on peut ajouter sur ce thème, avec name, description, icon, limit (le nombre maximum de sections de ce type sur une page) et settings_schema. L'exemple ci-dessus en montre un seul.

Lire après une écriture​

Par api.dzbuild.app, un GET réussi est mis en cache 30 secondes par clé et par chaîne de requête (l'en-tête X-Cache: HIT|MISS indique lequel). Un GET envoyé juste après une écriture peut donc renvoyer la mise en page d'avant. Utilisez la mise en page de la réponse à l'écriture : chaque écriture renvoie la liste complète dans l'ordre d'affichage, avec la nouvelle version. Si vous devez relire, ajoutez votre propre chaîne de requête, par exemple ?fresh=1727520000.

POST /v1/store/home-layout/sections​

Ajoute une section.

Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.

Corps​

ChampTypeRequisNotes
typestringouiUn type de types.
settingsobjectnonLes réglages non envoyés prennent les valeurs par défaut du type.
positionintnon0 met la section en haut, 24 est la dernière place. Sans lui, la section va à la fin.

Requête​

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}'

Réponse 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}​

Modifie une section. Les réglages envoyés sont fusionnés avec ceux enregistrés. Envoyez settings, is_active ou les deux.

Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.

Corps​

ChampTypeRequisNotes
settingsobjectnonFusionnés avec les réglages enregistrés.
is_activeboolnonfalse masque la section, true l'affiche.
replaceboolnonAvec settings, true remet à sa valeur par défaut chaque réglage non envoyé.

Requête​

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}'

Réponse 200​

La réponse a les mêmes champs que celle de POST : section (la section après le changement), sections, version, change_id et 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}​

Supprime une section.

Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.

Requête​

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"

Réponse 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​

Fixe l'ordre d'affichage. ids liste chaque section de la page une seule fois, sections masquées comprises.

Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.

Requête​

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]}'

Réponse 200​

La réponse porte sections dans le nouvel ordre, version, change_id et rendered. Un id absent de la page répond 404 section_not_found. Un id manquant ou répété répond 422 invalid_order.

PUT /v1/store/home-layout​

Remplace toute la mise en page par la liste envoyée, dans cet ordre.

Auth : clé plateforme avec store:write. Idempotency-Key est facultative.

Corps​

ChampTypeRequisNotes
sectionsarrayoui25 éléments au plus, chacun {id?, type, settings?, is_active?}. Une liste vide supprime toutes les sections.
versionstringnonLa version de votre dernière lecture. Si la mise en page a changé depuis, l'appel répond 409 write_conflict avec les sections et la version actuelles, et n'écrit rien.

Comment chaque élément est lu :

  • Un élément avec un id garde cette section. Son type doit être le type actuel de la section.
  • Un élément sans id crée une section.
  • Une section de la page absente de la liste est supprimée.
  • settings est l'objet complet : un réglage omis revient à sa valeur par défaut. Envoyez les réglages complets de chaque section que vous gardez.
  • is_active vaut true par défaut.

Requête​

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}}
]
}'

Réponse 200​

La réponse porte sections, version, change_id et rendered. La section 418 n'a pas été envoyée, elle est donc supprimée. Renvoyer telle quelle la mise en page lue répond change_id: null.

Avec une Idempotency-Key, un réessai avec la même clé et le même corps renvoie la réponse conservée pendant 24 heures avec Idempotency-Replay: 1, et la même clé avec un autre corps répond 422 idempotency_key_reuse. Sans clé, l'appel s'exécute à chaque fois, ce qui est sans risque : envoyer deux fois la même liste laisse la même mise en page.

Annulation​

Chaque écriture répond avec un change_id, ou null quand elle n'a rien changé. POST /v1/changes/{change_id}/undo remet toute la page d'accueil telle qu'elle était avant ce changement.

  • Un ajout de section s'annule aussi : l'annulation retire la section. Pour les autres ressources, l'annulation refuse un changement qui a créé quelque chose.
  • Si la page d'accueil a changé après ce changement, par l'API ou dans le dashboard, l'annulation répond 409 layout_changed et n'écrit rien. Lisez la mise en page et écrivez directement ce que vous voulez.
  • Une section qui revient après une suppression reçoit un nouvel id.
  • L'annulation est enregistrée comme un changement à part, undo_change_id, que vous pouvez annuler à son tour. Annuler l'annulation d'une suppression répond 409 layout_changed, parce que la section est revenue avec un nouvel id.
  • Les changements que le marchand enregistre dans le dashboard ne sont pas enregistrés, on ne peut donc pas les annuler par l'API.
  • GET /v1/changes?entity=store.home_layout liste les changements de la mise en page de l'accueil, du plus récent au plus ancien, avec store:read.
  • La réponse de l'annulation ne contient pas la mise en page. Relisez-la avec votre propre chaîne de requête, par exemple ?fresh=<unix time>, pour que le cache de 30 secondes ne renvoie pas la mise en page d'avant l'annulation.

L'annulation demande store:write et une 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"}
}

Un changement annulé une seconde fois répond 409 already_undone.

Erreurs​

HTTPCodeCause
400bad_requestLe corps n'est pas un objet JSON, un champ a le mauvais type (type absent, settings qui n'est pas un objet, is_active qui n'est pas un booléen, position hors de 0 à 24, ids qui n'est pas un tableau d'ids de section, version qui n'est pas une chaîne), l'id de section dans le chemin n'est pas un nombre positif, ou Idempotency-Key manque ou est mal formée sur POST, PATCH ou DELETE.
401unauthorizedClé absente ou invalide.
402quota_exceededLe quota mensuel de requêtes de la boutique est épuisé. Voir Limites de taux.
403forbidden« Missing scope: store:read » ou « Missing scope: store:write ».
403plan_requiredL'écriture laisserait plus de sections que le plan n'en autorise. L'erreur porte plan et cap.
404section_not_foundAucune section avec cet id sur la page.
409write_conflictUne autre écriture est arrivée avant, ou la version envoyée sur PUT n'est pas l'actuelle. Quand l'erreur porte sections et version, c'est la mise en page actuelle : réessayez à partir d'elles. Sinon, relisez la mise en page et réessayez.
409layout_changedAnnulation seulement : la page d'accueil a changé après ce changement.
409already_undoneAnnulation seulement : le changement a déjà été annulé.
413payload_too_largeLe corps dépasse 1 Mo.
422invalid_settingsUne valeur a été refusée. fields liste chaque réglage refusé de la section, par exemple settings.category. Sur PUT, il liste ceux de la première section refusée seulement, par exemple sections.2.settings.layout, et couvre aussi un id absent de la page (sections.N.id) et une section gardée envoyée avec un autre type (sections.N.type). message nomme aussi les chemins.
422invalid_section_typeLe type n'existe pas ou ne peut pas être ajouté sur ce thème. fields donne le chemin.
422limit_reachedPlus de 25 sections, ou plus de sections d'un type que sa limit. L'erreur porte limit, sauf quand un PUT envoie plus de 25 éléments.
422invalid_orderLes ids du réordonnancement oublient une section ou en répètent une.
422no_changesUn PATCH sans settings ni is_active.
422idempotency_key_reuseLa même Idempotency-Key a servi avec un autre corps.
429rate_limitedTrop de requêtes, y compris plus de 30 écritures de mise en page de l'accueil par minute pour la boutique. Attendez la durée de Retry-After.
429too_many_concurrentPlus de 5 écritures de mise en page de l'accueil en cours en même temps pour la boutique. Réessayez dans quelques secondes.
500server_errorLa requête a échoué. Réessayez avec la même Idempotency-Key.

Une réponse invalid_settings ressemble à ceci.

{
"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"}
}

Limites​

  • 25 sections par page d'accueil (max_sections).
  • Plafond du plan (cap) : 3 sections sur Free ou un plan expiré, 25 à partir de Pro. Les sections masquées comptent. Une boutique au-dessus de son plafond après un changement de plan garde ses sections et peut toujours les modifier, les masquer, les réordonner et les supprimer. Une écriture qui laisse plus de sections que le plafond et plus qu'avant répond 403 plan_required.
  • Par type : chaque type a une limit dans types, 12 pour category-products.
  • Réglages : 8 Ko par section une fois encodés. Un texte plus long est coupé au max du réglage.
  • Corps : 1 Mo.
  • Écritures : 30 par minute et 5 en même temps par boutique, en plus de la limite par minute de la boutique. Voir Limites de taux.