Catégories
Les catégories regroupent les produits d'une boutique. Elles ont deux niveaux : une catégorie principale peut contenir des sous-catégories, et une sous-catégorie n'en contient aucune. Ces six endpoints listent, lisent, créent, modifient, suppriment et réordonnent les catégories.
Un produit rejoint une catégorie par son champ category_id, voir Produits. Une section category-products de la page d'accueil prend aussi un id de catégorie, voir Sections de la page d'accueil.
Avant de commencer
- Les lectures demandent
products:readet les écrituresproducts:write, les mêmes scopes que pour les produits. Les clés marchand ont les deux. POST,PATCHetDELETEdemandent uneIdempotency-Key. Voir Idempotence.- L'image de la catégorie s'ajoute dans le dashboard. L'API renvoie son URL mais ne peut ni la téléverser ni la changer.
L'objet catégorie
| Champ | Type | Notes |
|---|---|---|
id | int | L'id de la catégorie. |
name | string | 1 à 100 caractères. |
slug | string | Tiré du nom et unique dans la boutique. La page de la catégorie dans la boutique l'utilise dans son adresse. |
description | string ou null | Texte libre. |
image | string ou null | URL complète de l'image, ou null. |
parent_id | int ou null | La catégorie parente, ou null pour une catégorie principale. |
show_subcategories | bool | Affiche les sous-catégories en vignettes sur la page de la catégorie dans la boutique (Afficher la section des sous-catégories dans le formulaire de la catégorie). Enregistré à true pour une sous-catégorie. Tant que Sous-catégories uniquement dans la catégorie parente est activé (/dashboard/categories), la boutique affiche les vignettes sur la page de chaque catégorie, quelle que soit la valeur de ce champ. |
sort_order | int | Position dans les listes de catégories de la boutique, la plus petite d'abord. |
status | string | active ou inactive. |
created_at | string | YYYY-MM-DD HH:MM:SS, heure du serveur. |
La liste et la lecture unitaire ajoutent product_count, le nombre de produits dans la catégorie. La lecture unitaire ajoute aussi children, ses sous-catégories.
GET /v1/categories
Les catégories de la boutique, de la plus récente à la plus ancienne, en liste à curseur. Triez-les par sort_order pour obtenir l'ordre de la boutique.
Auth : clé plateforme avec products:read.
Paramètres de requête
| Param | Type | Défaut | Notes |
|---|---|---|---|
parent_id | id, 0 ou null | aucun | Un id de catégorie renvoie ses sous-catégories. 0, null ou une valeur vide renvoie les catégories principales. Toute autre valeur renvoie 400 bad_request. |
status | active ou inactive | aucun | Seulement les catégories qui ont ce statut. Toute autre valeur est ignorée. |
limit | int | 50 | 1 à 200. |
cursor | string | aucun | Le next_cursor de la page précédente. Voir Pagination. |
Requête
curl 'https://api.dzbuild.app/v1/categories?parent_id=0' \
-H "Authorization: Bearer $DZ_KEY"
Réponse 200
{
"data": {
"items": [
{
"id": 14,
"name": "Montres",
"slug": "montres",
"description": null,
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 4,
"status": "active",
"created_at": "2026-09-30 11:20:05",
"product_count": 0
},
{
"id": 10,
"name": "Parfums",
"slug": "parfums",
"description": "Eaux de parfum et coffrets",
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 1,
"status": "active",
"created_at": "2026-09-12 09:41:37",
"product_count": 18
}
],
"next_cursor": null,
"has_more": false
}
}
GET /v1/categories/{id}
Une catégorie avec product_count et children, ses sous-catégories triées par sort_order.
Auth : clé plateforme avec products:read.
Un id qui n'est pas fait que de chiffres répond 400 bad_request. Une catégorie d'une autre boutique répond 404 not_found, comme une catégorie qui n'existe pas.
Requête
curl 'https://api.dzbuild.app/v1/categories/10' \
-H "Authorization: Bearer $DZ_KEY"
Réponse 200
{
"data": {
"id": 10,
"name": "Parfums",
"slug": "parfums",
"description": "Eaux de parfum et coffrets",
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 1,
"status": "active",
"created_at": "2026-09-12 09:41:37",
"children": [
{"id": 11, "name": "Parfums femme", "slug": "parfums-femme", "sort_order": 2, "status": "active"},
{"id": 12, "name": "Parfums homme", "slug": "parfums-homme", "sort_order": 3, "status": "active"}
],
"product_count": 18
}
}
POST /v1/categories
Crée une catégorie et la place en dernier : son sort_order vaut un de plus que le plus grand de la boutique.
Auth : clé plateforme avec products:write. Nécessite Idempotency-Key.
Corps
| Champ | Type | Requis | Notes |
|---|---|---|---|
name | string | oui | Espaces de début et de fin retirés, 1 à 100 caractères. |
description | string ou null | non | Espaces de début et de fin retirés. Une chaîne vide est enregistrée comme null. |
parent_id | int ou null | non | Une catégorie principale de cette boutique : la nouvelle catégorie devient sa sous-catégorie. null ou 0 crée une catégorie principale. |
status | active ou inactive | non | active par défaut. |
show_subcategories | bool | non | true par défaut. Ignoré, et enregistré à true, pour une sous-catégorie ou tant que Sous-catégories uniquement dans la catégorie parente est activé. |
Le slug est tiré du nom : en minuscules, lettres et chiffres gardés, et chaque suite d'autres caractères remplacée par un seul -. Un nom en arabe garde ses lettres arabes. Quand une autre catégorie de la boutique a déjà ce slug, -2, -3 et ainsi de suite est ajouté.
Requête
curl -X POST 'https://api.dzbuild.app/v1/categories' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cat-create-coffrets-1" \
-d '{"name": "Coffrets cadeaux", "parent_id": 10}'
Réponse 201
La réponse est l'objet catégorie, sans product_count ni children.
{
"data": {
"id": 15,
"name": "Coffrets cadeaux",
"slug": "coffrets-cadeaux",
"description": null,
"image": null,
"parent_id": 10,
"show_subcategories": true,
"sort_order": 5,
"status": "active",
"created_at": "2026-10-06 14:02:11"
}
}
PATCH /v1/categories/{id}
Ne change que les champs envoyés. Le corps accepte les champs de POST, tous facultatifs.
Auth : clé plateforme avec products:write. Nécessite Idempotency-Key.
- Un nouveau
namedonne un nouveauslug: l'adresse de la page de la catégorie dans la boutique change et les liens vers l'ancienne adresse ne marchent plus. Renvoyer le même nom garde leslug. parent_iddéplace la catégorie. Un id de catégorie principale en fait une sous-catégorie, etnullou0en fait une catégorie principale. Une catégorie qui a des sous-catégories ne peut pas devenir une sous-catégorie, et une catégorie ne peut pas être sa propre parente.- Un corps vide ne change rien et renvoie la catégorie telle quelle.
Requête
curl -X PATCH 'https://api.dzbuild.app/v1/categories/15' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cat-15-move-1" \
-d '{"parent_id": null, "status": "inactive"}'
Réponse 200
{
"data": {
"id": 15,
"name": "Coffrets cadeaux",
"slug": "coffrets-cadeaux",
"description": null,
"image": null,
"parent_id": null,
"show_subcategories": true,
"sort_order": 5,
"status": "inactive",
"created_at": "2026-10-06 14:02:11"
}
}
DELETE /v1/categories/{id}
Supprime une catégorie vide et son image.
Auth : clé plateforme avec products:write. Nécessite Idempotency-Key.
Une catégorie qui contient encore des produits ou des sous-catégories répond 409 category_not_empty, et rien n'est supprimé. Le message d'erreur donne les nombres. Pour vider la catégorie :
- Sous-catégories : passez chacune en catégorie principale avec
PATCHet"parent_id": null, ou supprimez-la d'abord. - Produits : l'API ne peut pas retirer un produit d'une catégorie. Donner un
category_idà un produit ajoute une catégorie et garde celles qu'il a déjà, voir Produits. Changez les catégories de ces produits dans le dashboard.
Requête
curl -X DELETE 'https://api.dzbuild.app/v1/categories/14' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: cat-14-delete-1"
Réponse 200
{
"data": {
"deleted": true,
"id": 14
}
}
POST /v1/categories/reorder
Fixe le sort_order des catégories listées, en une seule fois : soit elles changent toutes, soit aucune ne change.
Auth : clé plateforme avec products:write. Nécessite Idempotency-Key.
Corps
| Champ | Type | Requis | Notes |
|---|---|---|---|
categories | array | oui | Les catégories dans leur nouvel ordre. Chaque élément est {"id": 10}, {"id": 10, "sort_order": 7} ou un id seul comme 10. |
- Un élément sans
sort_orderprend sa position dans le tableau : 1, 2, 3 et ainsi de suite. Un élément avecsort_orderprend ce nombre. - Chaque id doit appartenir à la boutique et n'apparaître qu'une fois.
- Les catégories que vous ne listez pas gardent leur
sort_order. - Un réordonnancement n'est pas enregistré dans l'historique des changements, il ne peut donc pas être annulé. Lisez d'abord la liste si vous risquez de vouloir revenir à l'ancien ordre.
Requête
curl -X POST 'https://api.dzbuild.app/v1/categories/reorder' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cat-reorder-1" \
-d '{"categories": [{"id": 14}, {"id": 10}]}'
Réponse 200
{
"data": {
"reordered": 2,
"categories": [
{"id": 14, "sort_order": 1},
{"id": 10, "sort_order": 2}
]
}
}
Annulation
POST, PATCH et DELETE sont enregistrés dans l'historique des changements de la boutique. Leur réponse ne contient pas l'id du changement : GET /v1/changes?entity=category liste les changements des catégories, du plus récent au plus ancien, avec store:read. entity_id est l'id de la catégorie.
Requête
curl 'https://api.dzbuild.app/v1/changes?entity=category&limit=1' \
-H "Authorization: Bearer $DZ_KEY"
Réponse 200
{
"data": {
"items": [
{
"id": 120,
"entity": "category",
"entity_id": "15",
"action": "update",
"summary": "Updated category #15 (parent_id, status, show_subcategories)",
"undone_at": null,
"created_at": "2026-10-06 14:05:48",
"undone": false
}
],
"next_cursor": "MTIw",
"has_more": true
}
}
POST /v1/changes/{id}/undo annule un changement. Il demande products:write et une Idempotency-Key.
- Annuler un
PATCHremet les valeurs d'avant des champs que cet appel a changés, avec les mêmes contrôles quePATCH. - Annuler un
DELETErecrée la catégorie sous son ancien id, sans son image. Si son ancienne catégorie parente n'existe plus ou est devenue une sous-catégorie, l'annulation répond422 invalid_parent. - Une création ne s'annule pas : l'annulation répond
422 nothing_to_restore. Supprimez plutôt la catégorie. - Quand la catégorie n'existe plus, ou que son ancien id est pris, l'annulation répond
422 restore_target_missing. - Un changement annulé une deuxième fois répond
409 already_undone. - Les changements faits dans le dashboard ne sont pas enregistrés, on ne peut donc pas les annuler par l'API.
- Le jeton d'une application installée ne peut ni lire ni annuler les changements : les deux répondent
403 forbidden(Apps cannot use this endpoint).
curl -X POST 'https://api.dzbuild.app/v1/changes/120/undo' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: undo-120"
{
"data": {
"undone": true,
"change_id": 120,
"entity": "category",
"undo_change_id": 121
}
}
Erreurs
| HTTP | Code | Cause |
|---|---|---|
| 400 | bad_request | L'id dans le chemin n'est pas fait que de chiffres, le corps n'est pas un JSON valide, le filtre parent_id n'est ni un id, ni 0, ni null, ni vide, categories manque ou n'est pas un tableau, 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: products:read, Missing scope: products:write ou Missing scope: store:read, ou API access requires an active Enterprise plan pour une clé du marchand dont la boutique n'a pas de plan Enterprise actif, ou Apps cannot use this endpoint quand le jeton d'une application installée lit ou annule des changements. |
| 404 | not_found | Aucune catégorie avec cet id dans la boutique, un réordonnancement liste un id qui n'est pas dans la boutique, ou une annulation vise un changement absent de l'historique de la boutique. |
| 409 | category_not_empty | La catégorie contient encore des produits ou des sous-catégories. |
| 409 | already_undone | Annulation seulement : le changement a déjà été annulé. |
| 413 | payload_too_large | Le corps dépasse 1 Mo. |
| 422 | validation_error | name manque, est vide ou dépasse 100 caractères, status n'est ni active ni inactive, parent_id n'est pas un id, ou un réordonnancement est vide, répète un id, contient un id qui n'est pas un entier positif ou un sort_order qui n'est pas un entier. |
| 422 | invalid_parent | parent_id n'est pas une catégorie de cette boutique, est lui-même une sous-catégorie, est la catégorie elle-même, ou la catégorie a des sous-catégories et ne peut pas passer sous une autre. |
| 422 | nothing_to_restore | Annulation seulement : le changement a créé la catégorie. |
| 422 | restore_target_missing | Annulation seulement : la catégorie n'existe plus, ou son ancien id est pris. |
| 422 | idempotency_key_reuse | La même Idempotency-Key a servi avec un autre corps. |
| 429 | rate_limited | Trop d'appels dans la minute en cours. Attendez les secondes indiquées par Retry-After. Voir Limites de taux. |
| 500 | server_error | La requête a échoué. Réessayez avec la même Idempotency-Key. |