Aller au contenu principal

Changements et annulation

La plupart des écritures de configuration faites par l'API sont enregistrées comme changements : réglages, design et thème de la boutique, sections de la page d'accueil, catégories, stock, codes promo, pixels, tarifs et réglages de livraison, et sections de landing page. Chaque changement garde les valeurs qu'il a remplacées, et une annulation les réécrit en passant par les mêmes contrôles que l'écriture d'origine. Les écritures faites sur la boutique par Copilot, par un assistant IA connecté (Claude ou ChatGPT) ou par une application installée sont aussi enregistrées. Les changements enregistrés dans le dashboard ne le sont pas.

Les trois endpoints ci-dessous listent les changements, en lisent un en entier et en annulent un. Les écritures sous /v1/store/home-layout et la synchronisation des tarifs d'un transporteur répondent avec un change_id. Pour les autres écritures, retrouvez le changement avec GET /v1/changes.

Ce qui est enregistré​

entityEnregistré parentity_idPortée pour le lire en entierPortée pour l'annuler
store.settingsPATCH /v1/storesettingsstore:readstore:write
store.designPATCH /v1/store/designdesignstore:readstore:write
store.themePOST /v1/store/theme, POST /v1/store/fast-checkout-theme, POST /v1/store/variant-stylethemestore:readstore:write
store.home_sectionsPATCH /v1/store/home-sectionshome_sectionsstore:readstore:write
store.home_layoutToute écriture sous /v1/store/home-layoutlayoutstore:readstore:write
categoryPOST /v1/categories, PATCH et DELETE /v1/categories/{id}Id de la catégorieproducts:readproducts:write
stockPOST /v1/products/{id}/stockId du produitproducts:readproducts:write
promo_codePOST /v1/promo-codes, PATCH et DELETE /v1/promo-codes/{id}Id du code promopromos:readpromos:write
pixelsPOST /v1/pixels, PATCH et DELETE /v1/pixels/{id}L'id du pixel chez DZBuild, pas son pixel_idpixels:readpixels:write
shipping.ratesPOST /v1/shipping/rates, POST /v1/shipping/rates/syncratesshipping:readshipping:write
shipping.settingsPATCH /v1/shipping/settingssettingsshipping:readshipping:write
lp.sectionLes écritures de sections sous /v1/landing-pages/{id}/sectionsId de la section, ou lp: suivi de l'id de la page pour un réordonnancementlanding_pages:readlanding_pages:write
  • Ces écritures ne sont pas enregistrées et ne peuvent pas être annulées : les produits avec leurs images, variantes, offres, add-ons et règles de quantité (le stock est enregistré), les commandes, les landing pages elles-mêmes, l'ordre des catégories, les transporteurs, les webhooks et les clés.
  • lp.page est accepté comme filtre entity, mais aucune écriture ne l'enregistre.
  • L'enregistrement ne bloque pas une écriture. Quand un changement ne peut pas être enregistré, par exemple parce que ses valeurs d'avant ou d'après dépassent 256 KB, l'écriture passe quand même et ne peut pas être annulée. Les écritures de tarifs de livraison font exception : elles vérifient la taille d'abord et répondent 422 snapshot_too_large au lieu de s'exécuter.
  • Chaque portée du tableau fait partie des portées par défaut d'une nouvelle clé : une clé créée depuis le dashboard (Paramètres → API, /dashboard/api) peut donc utiliser les trois endpoints. Les portées sont figées à la création de la clé : une clé plus ancienne sans la portée qu'il faut répond 403 forbidden. Créez une nouvelle clé depuis le dashboard.

GET /v1/changes​

Les changements de la boutique, du plus récent au plus ancien, sans les valeurs qu'ils ont remplacées.

Auth : clé plateforme avec store:read. Le jeton d'une application installée reçoit 403 forbidden (Apps cannot use this endpoint).

Paramètres de requête​

ParamTypeDéfautNotes
entitystringaucunSeulement les changements d'une entity du tableau ci-dessus. Toute autre valeur est ignorée et la liste entière revient.
limitint25De 1 à 100. Une valeur plus petite compte pour 1, une plus grande pour 100.
cursorstringaucunLe next_cursor de la page précédente. Voir Pagination.

Requête​

curl 'https://api.dzbuild.app/v1/changes?limit=2' \
-H "Authorization: Bearer $DZ_KEY"

Réponse 200​

{
"data": {
"items": [
{
"id": 120,
"entity": "shipping.rates",
"entity_id": "rates",
"action": "update",
"summary": "Shipping rates updated for 2 wilaya(s)",
"undone_at": null,
"created_at": "2026-10-06 11:02:17",
"undone": false
},
{
"id": 119,
"entity": "promo_code",
"entity_id": "7",
"action": "update",
"summary": "Updated promo code SUMMER10",
"undone_at": null,
"created_at": "2026-10-06 10:52:30",
"undone": false
}
],
"next_cursor": "MTE5",
"has_more": true
}
}
ChampSignification
idL'id du changement, pour GET /v1/changes/{id} et l'annulation.
entityCe qui a changé. Voir le tableau ci-dessus.
entity_idL'élément qui a changé, en chaîne. Voir le tableau ci-dessus.
actioncreate, update ou delete. Une annulation est enregistrée comme un update.
summaryUne courte description en anglais. Une annulation affiche Undo of change # suivi de l'id du changement annulé.
undonetrue une fois le changement annulé.
undone_atQuand le changement a été annulé, sinon null.
created_atYYYY-MM-DD HH:MM:SS, heure du serveur. undone_at suit le même format.

GET /v1/changes/{id}​

Un changement avec before, les valeurs qu'il a remplacées, et after, les valeurs qu'il a écrites. Leur forme dépend de l'entité : certaines gardent seulement les champs touchés par l'écriture, d'autres l'élément entier.

Auth : clé plateforme avec store:read, plus la portée de lecture de l'entité du changement, d'après le tableau ci-dessus. Le jeton d'une application installée reçoit 403 forbidden.

Requête​

curl 'https://api.dzbuild.app/v1/changes/118' \
-H "Authorization: Bearer $DZ_KEY"

Réponse 200​

{
"data": {
"id": 118,
"key_id": "dzpk_live_xxxxxxxxxxxxxx",
"entity": "category",
"entity_id": "12",
"action": "update",
"summary": "Updated category #12 (name, slug)",
"undone_at": null,
"undone_by_id": null,
"created_at": "2026-10-06 10:41:05",
"before": {"name": "Shoes", "slug": "shoes"},
"after": {"name": "Sneakers", "slug": "sneakers"},
"undone": false
}
}

La réponse porte les champs de la liste, plus ceux-ci.

ChampSignification
key_idLa clé qui a fait le changement, ou null pour une annulation faite depuis le dashboard.
undone_by_idL'id du changement qui a annulé celui-ci, sinon null.
beforeLes valeurs que le changement a remplacées. null pour un create.
afterLes valeurs que le changement a écrites. null pour un delete et pour une synchronisation des tarifs d'un transporteur.

Le jeton d'accès (access token) d'un pixel n'est jamais gardé dans un changement. Quand le pixel en a un, before et after affichent •••••••• à sa place.

Erreurs​

HTTPCodeCause
400bad_requestL'id du chemin n'est pas composé uniquement de chiffres.
403forbiddenLa clé n'a pas store:read ou la portée de lecture de l'entité du changement (Missing scope: ...), ou l'appel vient du jeton d'une application installée.
404not_foundAucun changement avec cet id dans la boutique.

POST /v1/changes/{id}/undo​

Réécrit les valeurs before du changement en passant par les mêmes contrôles que l'écriture d'origine, puis enregistre l'annulation comme un nouveau changement. Pas de corps de requête.

Auth : clé plateforme avec la portée d'annulation de l'entité du changement, d'après le tableau ci-dessus ; store:read n'est pas nécessaire. Nécessite Idempotency-Key. Le jeton d'une application installée reçoit 403 forbidden (Apps cannot use this endpoint). Le propriétaire de la boutique voit les 20 derniers changements de chaque application installée sur la page de cette application dans le dashboard (/dashboard/apps/{id}, bloc Ses dernières modifications) et peut les annuler depuis là avec le bouton Annuler.

Ce que fait l'annulation​

  1. Un changement qui a créé quelque chose n'a rien à restaurer et répond 422 nothing_to_restore : supprimez l'élément à la place. L'ajout d'une section de la page d'accueil par /v1/store/home-layout fait exception, parce que chaque écriture de la mise en page de l'accueil est enregistrée comme un update de toute la mise en page.
  2. Un update s'annule en réécrivant les valeurs before par-dessus ce qui est là maintenant. Seule la page d'accueil vérifie les changements ultérieurs et répond 409 layout_changed (voir Sections de la page d'accueil). Pour revenir sur plusieurs changements d'un même élément, annulez-les du plus récent au plus ancien.
  3. Une catégorie supprimée revient avec son id, sans son image. Un code promo supprimé revient avec son id si aucun autre code ne l'a pris, et avec son nombre d'utilisations.
  4. Un pixel supprimé revient avec son id s'il est encore libre, mais sans son jeton d'accès et sans ses affectations aux produits, catégories et landing pages. Annuler une modification de pixel laisse son jeton d'accès actuel en place.
  5. Une section de landing page supprimée revient avec un nouvel id.
  6. Une annulation de stock remet chaque valeur au nombre enregistré avant le changement, quoi que les commandes aient fait au stock depuis.
  7. Annuler POST /v1/shipping/rates remet les tarifs précédents, et retire le tarif d'une wilaya qui n'en avait pas avant le changement. Annuler une synchronisation des tarifs d'un transporteur remet chaque tarif que la synchronisation a écrasé, et garde les tarifs qu'elle a ajoutés pour des wilayas qui n'en avaient pas.
  8. L'annulation est enregistrée comme un changement à part, undo_change_id, que vous pouvez annuler pour réappliquer le changement d'origine. Quand le changement d'origine n'a pas d'after (une suppression ou une synchronisation des tarifs d'un transporteur), annuler l'annulation répond 422 nothing_to_restore.
  9. Un changement s'annule une seule fois. Une annulation suivante répond 409 already_undone, et de deux annulations envoyées au même moment une seule s'exécute.
  10. Quand la restauration elle-même échoue (restore_target_missing, une valeur refusée ou un 500), le changement n'est pas marqué comme annulé : vous pouvez réessayer une fois la cause corrigée. Les règles de réessai sont plus bas.

La réponse de l'annulation ne contient pas les valeurs restaurées. Relisez l'élément. Par api.dzbuild.app, le cache de lecture court (GET /v1/store et chaque GET en dessous, les listes GET /v1/products et GET /v1/landing-pages) peut encore renvoyer les anciennes valeurs jusqu'à 30 secondes après l'annulation.

Requête​

curl -X POST 'https://api.dzbuild.app/v1/changes/118/undo' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: undo-118"

Réponse 200​

{
"data": {
"undone": true,
"change_id": 118,
"entity": "category",
"undo_change_id": 121
}
}
ChampSignification
undoneToujours true avec un 200.
change_idLe changement annulé.
entitySon entité.
undo_change_idLe changement qui enregistre cette annulation, ou null s'il n'a pas pu être enregistré.

Erreurs​

HTTPCodeCause
400bad_requestL'id du chemin n'est pas composé uniquement de chiffres, ou Idempotency-Key est absente ou mal formée.
403forbiddenLa clé n'a pas la portée d'annulation de l'entité du changement (Missing scope: ...), ou l'appel vient du jeton d'une application installée.
404not_foundAucun changement avec cet id dans la boutique.
409already_undoneLe changement a déjà été annulé.
409layout_changedPage d'accueil seulement : la mise en page a changé après ce changement.
422not_undoableCe type de changement ne peut pas être annulé.
422nothing_to_restoreLe changement a créé quelque chose, ou ne contient aucune valeur à restaurer. Supprimez l'élément à la place.
422restore_target_missingCe que le changement a touché n'existe plus, par exemple une catégorie ou une section de landing page supprimée depuis.
422idempotency_key_reuseLa même Idempotency-Key a déjà servi pour une autre requête, par exemple l'annulation d'un autre changement.
4xxLe code de l'écriture d'origineLes contrôles de l'écriture d'origine refusent les valeurs, par exemple invalid_wilaya sur les tarifs de livraison, ou un thème qui n'est plus proposé.
500server_errorL'annulation n'a pas pu s'exécuter. Le changement reste annulable.

Réessais et Idempotency-Key​

La première réponse à une clé est conservée 24 heures, un 4xx compris. Un réessai avec la même clé pour le même changement renvoie cette réponse avec Idempotency-Replay: 1, et aucune seconde annulation ne s'exécute. Après avoir corrigé la cause d'une erreur, réessayez donc avec une nouvelle clé. Une réponse 5xx ou 429 n'est jamais conservée : réessayez-la avec la même clé. Voir Idempotence.

Cette page pour les outils IAVoir en MarkdownOuvrir dans ChatGPTOuvrir dans Claude