Pages de la boutique
Les pages de la boutique sont les pages de texte du marchand, comme À propos, Livraison ou Retours. Chaque page est écrite en Markdown. Une page publiée vit à l'adresse /pages/{slug} de la boutique et figure dans son sitemap.xml et son llms.txt. Un brouillon répond 404 sur la boutique. Ces cinq endpoints listent, lisent, créent, modifient et suppriment les pages.
Le marchand modifie les mêmes pages dans le tableau de bord, dans Personnaliser, ligne Pages. Voir Pages de la boutique dans la documentation marchand.
Avant de commencer
- Les lectures demandent
store:readet les écrituresstore:write. Les clés du marchand portent les deux. POST,PATCHetDELETEdemandent uneIdempotency-Key. Voir Idempotence.- L'API ne peut pas envoyer d'images. Une image dans
body_mdest un lien vers une image déjà en ligne, écrit.
L'objet page
| Champ | Type | Notes |
|---|---|---|
id | int | L'id de la page. |
slug | string | La fin de l'adresse de la page, après /pages/. 2 à 80 lettres latines minuscules, chiffres ou tirets, qui commencent et finissent par une lettre ou un chiffre. Unique dans la boutique. |
title | string | 1 à 120 caractères. |
body_md | string | Le texte en Markdown, jusqu'à 65 536 octets. Voir Comment le texte est affiché. |
seo_title | string ou null | Le titre que montrent les moteurs de recherche, 70 caractères au plus. null reprend title. |
seo_description | string ou null | La description que montrent les moteurs de recherche, 160 caractères au plus. null reprend les premières lignes du texte. |
status | string | draft ou published. |
translations | object ou null | Les textes de la deuxième langue de la boutique, indexés par code de langue, comme {"fr": {"title": "...", "body_md": "...", "seo_title": null, "seo_description": null}}, ou null. Voir Deuxième langue. |
url | string | L'adresse complète de la page sur la boutique. |
created_at | string | YYYY-MM-DD HH:MM:SS, heure du serveur. |
updated_at | string | YYYY-MM-DD HH:MM:SS, heure du serveur. |
Les balises HTML de title, seo_title et seo_description sont retirées, et un texte trop long est coupé à la limite.
Comment le texte est affiché
- Le Markdown est affiché en mode sûr : le HTML brut est échappé et s'affiche comme du texte.
- Un simple retour à la ligne dans le texte reste un retour à la ligne.
- Un lien vers la boutique elle-même, comme
/products,/category/12ou/pages/delivery, s'ouvre dans le même onglet. Un lien vers un autre site s'ouvre dans un nouvel onglet, comme un lien qui commence par//. - Un lien YouTube seul sur sa ligne affiche la vidéo.
Deuxième langue
translations n'est écrit que si l'extension Boutique multilingue est active sur la boutique. Sans elle, le champ est ignoré et la valeur enregistrée est gardée. La clé est la deuxième langue de la boutique : fr pour une boutique en arabe, ar pour une boutique en français. Un client qui parcourt la boutique dans cette langue voit ces textes, et un champ vide reprend le champ principal.
GET /v1/store/pages
Toutes les pages de la boutique, brouillons compris, triées par titre. Les éléments sont des résumés sans le texte : lisez une page pour obtenir son body_md. La liste n'est pas paginée : une boutique a au plus 25 pages.
Auth : clé plateforme avec store:read.
Requête
curl 'https://api.dzbuild.app/v1/store/pages' \
-H "Authorization: Bearer $DZ_KEY"
Réponse 200
Chaque élément porte id, slug, title, status, url et updated_at. cap est le nombre de pages que le plan de la boutique autorise. max_pages est la limite fixe pour tous les plans.
{
"data": {
"items": [
{
"id": 7,
"slug": "retours",
"title": "Retours",
"status": "published",
"url": "https://my-store.dzbuild.app/pages/retours",
"updated_at": "2026-11-06 10:12:40"
}
],
"cap": 25,
"max_pages": 25
},
"meta": {"request_id": "3f1c9a7b20d4e865", "api_version": "v1"}
}
GET /v1/store/pages/{id}
Une page.
Auth : clé plateforme avec store:read.
Requête
curl 'https://api.dzbuild.app/v1/store/pages/7' \
-H "Authorization: Bearer $DZ_KEY"
Réponse 200
La réponse est l'objet page. Une page qui n'est pas dans la boutique répond 404 page_not_found.
POST /v1/store/pages
Crée une page.
Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.
Corps
| Champ | Type | Obligatoire | Notes |
|---|---|---|---|
title | string | oui | 1 à 120 caractères. |
slug | string | non | Fait à partir du titre si vous ne l'envoyez pas. Quand cela ne donne pas de slug utilisable (un titre sans lettre latine ni chiffre comme un titre en arabe, un mot réservé, ou un slug qu'une autre page utilise), la page reçoit page-N. Un slug envoyé est mis en minuscules, puis doit être valide et libre. |
body_md | string | non | Markdown, jusqu'à 65 536 octets. |
seo_title | string ou null | non | 70 caractères au plus. |
seo_description | string ou null | non | 160 caractères au plus. |
status | draft ou published | non | draft par défaut. Publiez seulement si le marchand l'a demandé. |
translations | object ou null | non | Voir Deuxième langue. |
Un slug ne peut pas être un mot que la boutique utilise déjà pour ses propres adresses, comme products, product, cart, checkout, category, track-order, landing, pages, sitemap, ar ou fr. Un tel slug répond 422 invalid_page.
Requête
curl -X POST 'https://api.dzbuild.app/v1/store/pages' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: page-create-retours-1" \
-d '{"title": "Retours", "slug": "retours", "body_md": "## Comment retourner un article\n\nÉcrivez-nous sur WhatsApp avec votre numéro de commande.", "status": "published"}'
Réponse 201
{
"data": {
"page": {
"id": 7,
"slug": "retours",
"title": "Retours",
"body_md": "## Comment retourner un article\n\nÉcrivez-nous sur WhatsApp avec votre numéro de commande.",
"seo_title": null,
"seo_description": null,
"status": "published",
"translations": null,
"url": "https://my-store.dzbuild.app/pages/retours",
"created_at": "2026-11-06 10:12:40",
"updated_at": "2026-11-06 10:12:40"
},
"change_id": 90310
},
"meta": {"request_id": "8b2e04d1c9a7f356", "api_version": "v1"}
}
PATCH /v1/store/pages/{id}
Modifie seulement les champs envoyés. Le corps prend les champs de POST, tous facultatifs. Un corps sans aucun d'eux répond 422 no_changes, et un appel qui ne change rien répond change_id: null.
Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.
- Un nouveau
slugchange l'adresse de la page. L'ancienne adresse continue de répondre par une redirection301vers la nouvelle, donc les liens partagés marchent toujours. Remettre l'ancienslugest permis. Sansslug, l'adresse reste la même, même quand le titre change. "status": "draft"retire la page de la boutique sans la supprimer.
Requête
curl -X PATCH 'https://api.dzbuild.app/v1/store/pages/7' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: page-7-seo-1" \
-d '{"seo_title": "Retours et échanges", "seo_description": "Comment retourner un article commandé sur notre boutique."}'
Réponse 200
La réponse a les mêmes champs que la réponse de POST : page, la page après le changement, et change_id.
DELETE /v1/store/pages/{id}
Supprime une page. Son adresse sur la boutique ne marche plus tout de suite.
Auth : clé plateforme avec store:write. Nécessite Idempotency-Key.
Requête
curl -X DELETE 'https://api.dzbuild.app/v1/store/pages/7' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: page-7-delete-1"
Réponse 200
{
"data": {
"deleted": true,
"id": 7,
"change_id": 90312
},
"meta": {"request_id": "c40a91e7b25d3f68", "api_version": "v1"}
}
Annuler
Chaque écriture répond avec un change_id. POST /v1/changes/{change_id}/undo annule ce changement. L'annulation demande store:write et une Idempotency-Key.
- Annuler un
PATCHremet la page comme elle était avant cet appel. Si la page a été supprimée depuis, l'annulation répond422 restore_target_missing. - Annuler un
DELETErecrée la page sous son ancien id et son ancien slug. - Une création ne peut pas être annulée : l'annulation répond
422 nothing_to_restore. Supprimez plutôt la page. - Si une autre page a pris depuis l'id ou le slug de la page supprimée, ou si la boutique a déjà 25 pages, l'annulation de la suppression répond
409 page_restore_conflict. Renommez ou supprimez cette page, puis annulez à nouveau. - Un changement annulé une seconde fois répond
409 already_undone. - Les changements que le marchand enregistre dans Personnaliser ne sont pas enregistrés dans l'historique, donc ils ne peuvent pas être annulés par l'API.
GET /v1/changes?entity=store.pageliste les changements des pages, les plus récents d'abord, avecstore:read.entity_idest l'id de la page.- Le jeton d'une application installée ne peut ni lire ni annuler les changements :
GET /v1/changeset l'annulation répondent403 forbidden(« Apps cannot use this endpoint »). Les réponses d'écriture portent quand même lechange_id.
curl -X POST 'https://api.dzbuild.app/v1/changes/90312/undo' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: undo-90312"
{
"data": {
"undone": true,
"change_id": 90312,
"entity": "store.page",
"undo_change_id": 90315
},
"meta": {"request_id": "71d5e0a2c8b94f36", "api_version": "v1"}
}
Erreurs
| HTTP | Code | Cause |
|---|---|---|
| 400 | bad_request | Le corps n'est pas un objet JSON, l'id de la page dans le chemin n'est pas un nombre positif, ou Idempotency-Key manque ou est mal formée. |
| 401 | unauthorized | Clé absente ou invalide. |
| 402 | quota_exceeded | Le quota mensuel de requêtes de la boutique est épuisé. Voir Limites de taux. |
| 403 | forbidden | « Missing scope: store:read » ou « Missing scope: store:write », ou « API access requires an active Enterprise plan » pour une clé du marchand dont la boutique n'a pas de plan Enterprise actif. |
| 403 | plan_required | Une création dépasserait le nombre de pages que le plan autorise. L'erreur porte plan et cap. |
| 404 | page_not_found | Aucune page avec cet id dans la boutique. |
| 409 | slug_taken | Une autre page de la boutique utilise ce slug. fields vaut [{"path": "slug", "code": "taken"}]. |
| 409 | write_conflict | Une autre écriture est arrivée au même moment. Lisez la page, puis réessayez avec une nouvelle Idempotency-Key. |
| 409 | already_undone | Annulation seulement : le changement a déjà été annulé. |
| 409 | page_restore_conflict | Annulation d'une suppression seulement : une autre page utilise maintenant l'id ou le slug de la page, ou la boutique a déjà 25 pages. |
| 413 | payload_too_large | Le corps dépasse 1 Mo. |
| 422 | invalid_page | Une valeur a été refusée : un titre absent ou vide, un champ qui n'est pas du texte, un slug mal formé ou réservé, un status autre que draft et published, des translations qui ne sont pas un objet, ou un body_md de plus de 65 536 octets. fields donne {path, code} pour le champ refusé, comme slug. |
| 422 | limit_reached | La boutique a déjà 25 pages. L'erreur porte limit. |
| 422 | no_changes | Un PATCH sans aucun des champs de la page. |
| 422 | nothing_to_restore | Annulation seulement : le changement a créé la page. |
| 422 | restore_target_missing | Annulation d'un PATCH seulement : la page a été supprimée depuis. |
| 422 | idempotency_key_reuse | La même Idempotency-Key a servi avec un autre corps. |
| 429 | rate_limited | Trop de requêtes, dont plus de 30 écritures de pages par minute pour la boutique. Attendez Retry-After. |
| 429 | too_many_concurrent | Plus de 5 écritures de pages en cours en même temps pour la boutique. Réessayez dans quelques secondes. |
| 500 | server_error | La requête a échoué. Réessayez avec la même Idempotency-Key. |
Une réponse invalid_page ressemble à ceci.
{
"error": {
"code": "invalid_page",
"message": "slug: 2 to 80 lowercase latin letters, digits or dashes, not a store route",
"fields": [{"path": "slug", "code": "invalid"}]
},
"meta": {"request_id": "e9a3c17f04b26d58", "api_version": "v1"}
}
Limites
- 25 pages par boutique (
max_pages), brouillons compris. - Plafond du plan (
cap) : 3 pages sur Free ou un plan expiré, 25 à partir de Pro. Une boutique au-dessus de son plafond après un changement de plan garde ses pages et peut toujours les lire, les modifier et les supprimer. Une création répond403 plan_requiredtant que la boutique n'est pas sous son plafond. - Texte :
body_mdjusqu'à 65 536 octets, et la requête jusqu'à 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.
Outils MCP
Le serveur MCP, en version 1.8.0, donne à un assistant IA cinq outils de pages avec les mêmes règles : pages_list, page_get, page_create, page_update et page_delete. L'outil page_delete demande à l'assistant de confirmer d'abord avec le marchand.