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 |
| int | L'id de la catégorie. |
| string | 1 à 100 caractères. |
| string | Tiré du nom et unique dans la boutique. La page de la catégorie dans la boutique l'utilise dans son adresse. |
| string ou null | Texte libre. |
| string ou null | URL complète de l'image, ou |
| int ou null | La catégorie parente, ou |
| 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é à |
| int | Position dans les listes de catégories de la boutique, la plus petite d'abord. |
| string |
|
| string |
|
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 |
| id, | aucun | Un id de catégorie renvoie ses sous-catégories. |
|
| aucun | Seulement les catégories qui ont ce statut. Toute autre valeur est ignorée. |
| int | 50 | 1 à 200. |
| string | aucun | Le |
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 |
| string | oui | Espaces de début et de fin retirés, 1 à 100 caractères. |
| string ou null | non | Espaces de début et de fin retirés. Une chaîne vide est enregistrée comme |
| int ou null | non | Une catégorie principale de cette boutique : la nouvelle catégorie devient sa sous-catégorie. |
|
| non |
|
| bool | non |
|
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 |
| array | oui | Les catégories dans leur nouvel ordre. Chaque élément est |
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 |
| L'id dans le chemin n'est pas fait que de chiffres, le corps n'est pas un JSON valide, le filtre |
401 |
| Clé absente ou invalide. |
402 |
| Le quota mensuel de requêtes de la boutique est épuisé. Voir Limites de taux. |
403 |
|
|
404 |
| 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 |
| La catégorie contient encore des produits ou des sous-catégories. |
409 |
| Annulation seulement : le changement a déjà été annulé. |
413 |
| Le corps dépasse 1 Mo. |
422 |
|
|
422 |
|
|
422 |
| Annulation seulement : le changement a créé la catégorie. |
422 |
| Annulation seulement : la catégorie n'existe plus, ou son ancien id est pris. |
422 |
| La même |
429 |
| Trop d'appels dans la minute en cours. Attendez les secondes indiquées par |
500 |
| La requête a échoué. Réessayez avec la même |