Une landing page est une page de conversion focalisée sur un seul produit. Elles sont indépendantes du catalogue boutique — vous pouvez avoir une landing page sans produit en ligne (pour des lancements à venir), ou une liée à un produit pour des pubs payantes.
Les sections (carrousels, faux visiteurs, comptes à rebours, etc.) sont gérées dans le tableau de bord en v1 ; l'API ne fait que CRUD sur l'enregistrement parent. Une mise à jour v1.1 exposera aussi le CRUD des sections.
Limites par plan
Plan | Landing pages (tous statuts — les brouillons comptent) |
Free | 0 (achat unique : 1000 DZD / à vie chacune) |
Pro | 3 |
Unlimited / Enterprise | illimité |
Le plafond n'est appliqué que par les flux création / duplication du tableau de bord, en comptant chaque landing page, brouillons inclus. L'API n'applique rien : POST /v1/landing-pages suivi de /publish contourne totalement le plafond, et sur un plan payant les pages en trop s'affichent bien en ligne sur la vitrine. Sur le plan Free, les pages restent invisibles sauf si la page a été achetée (is_purchased).
GET /v1/landing-pages
Liste les landing pages. Pagination par curseur. Mis en cache pendant 30 s — vérifiez l'en-tête de réponse X-Cache: HIT|MISS. GET /v1/landing-pages/{id} n'est pas mis en cache.
Auth : n'importe quelle clé plateforme active de la boutique (landing_pages:read n'est pas appliqué en v1 ; seul landing_pages:write est contrôlé, sur les endpoints d'écriture).
Paramètres de requête
Param | Type | Notes |
| int 1–200 | Défaut 50 |
| string | Opaque |
|
| Filtre |
Un status non reconnu est ignoré : toutes les pages sont renvoyées plutôt qu'un 400.
Réponse 200
{
"data": {
"items": [
{
"id": 42,
"title": "Black T-Shirt — 30% off",
"slug": "black-tshirt-30-off",
"status": "active",
"language": "ar",
"product_id": 26,
"views": 1543,
"is_purchased": false,
"created_at": "2026-03-01 10:00:00",
"updated_at": "2026-03-15 14:22:11"
}
],
"next_cursor": null,
"has_more": false
}
}
GET /v1/landing-pages/{id}
Détail avec section_count.
{
"data": {
"id": 42,
"title": "Black T-Shirt — 30% off",
"slug": "black-tshirt-30-off",
"status": "active",
"language": "ar",
"product_id": 26,
"views": 1543,
"is_purchased": false,
"meta_title": "Black T-Shirt — Cotton 200gsm — 30% off | DZBuild",
"meta_description": "Limited-time offer on our cotton black t-shirt.",
"section_count": 7,
"created_at": "2026-03-01 10:00:00",
"updated_at": "2026-03-15 14:22:11"
}
}
Référence des champs
Champ | Notes |
| Strictement |
|
|
| Le produit lié, ou |
| Lecture seule. Compté à chaque consultation de la page publique ; l'API ne peut pas l'écrire et il n'existe aucun moyen de le remettre à zéro. |
|
|
| Endpoint détail uniquement — un comptage en direct des sections de la page, calculé à chaque requête. |
| Balises SEO. Voir la note sous création. |
POST /v1/landing-pages — créer
Auth : clé plateforme avec landing_pages:write. Nécessite Idempotency-Key.
Corps
Champ | Type | Requis | Notes |
| string 1–255 | ✅ | |
| string | Auto-déduit de | |
|
| Défaut | |
|
| Défaut | |
| int | Doit appartenir à votre boutique ; la page lie ce produit | |
| string ≤ 255 | Titre SEO. Omis via l'API, il est stocké et renvoyé comme | |
| string | Description SEO |
Les slugs sont rendus uniques dans votre boutique par ajout de -2, -3, … Une base de slug vide retombe sur landing- suivi de 6 caractères hex.
Erreurs
Code | Cause |
| Content-Type incorrect ou JSON malformé |
| Titre manquant ou trop long |
| ID cross-boutique |
Requête
curl -X POST 'https://api.dzbuild.app/v1/landing-pages' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"title": "Black T-Shirt — 30% off",
"language": "ar",
"product_id": 26,
"status": "draft"
}'
Renvoie 200 (et non 201) avec la même forme que GET /v1/landing-pages/{id}. La nouvelle landing page n'a aucune section — peuplez-les depuis le dashboard.
PATCH /v1/landing-pages/{id}
Mise à jour partielle.
PATCH valide plus strictement que la création : un status invalide renvoie 400 bad_request (« status must be active or draft ») et un language invalide renvoie 400 (« language must be ar, fr, or en ») au lieu d'être coercé. title doit toujours faire 1 à 255 caractères. Un slug envoyé sur PATCH est normalisé, contrairement à la création.
curl -X PATCH 'https://api.dzbuild.app/v1/landing-pages/42' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "title": "Black T-Shirt — Spring promo" }'
Renommer régénère slug automatiquement uniquement si vous n'avez pas envoyé slug explicitement.
POST /v1/landing-pages/{id}/publish
Raccourci : passer le status à active. Équivaut à PATCH ... { status: "active" }.
curl -X POST 'https://api.dzbuild.app/v1/landing-pages/42/publish' \ -H "Authorization: Bearer $DZ_KEY" \ -H "Idempotency-Key: publish-42-$(date +%s)"
DELETE /v1/landing-pages/{id}
Suppression dure. Les sections de la page sont supprimées avec elle.
curl -X DELETE 'https://api.dzbuild.app/v1/landing-pages/42' \ -H "Authorization: Bearer $DZ_KEY" \ -H "Idempotency-Key: del-42"
Réponse : { "data": { "deleted": true, "id": 42 } }.