Aller au contenu principal

Livraison

Ces endpoints couvrent ce que le dashboard garde dans ses pages de livraison : le tarif de livraison à domicile et au bureau de chaque wilaya, les règles de livraison gratuite et les transporteurs liés à la boutique. Ils servent aussi les listes de wilayas et de communes dont un formulaire de commande a besoin, ainsi que les communes et les stop desks que dessert le transporteur de la boutique.

Les prix sont en DZD. POST /v1/orders calcule la livraison à partir de ces tarifs et ignore tout coût de livraison envoyé dans le corps : une vitrine personnalisée lit donc les tarifs pour afficher une estimation et laisse la commande calculer le montant. Voir Thèmes & vitrines personnalisés.

Avant de commencer​

  • La clé a besoin des portées de livraison. Les clés créées depuis le dashboard (Paramètres → API, /dashboard/api) ont les deux. Les portées sont figées à la création de la clé : une clé plus ancienne qui ne les a pas répond 403 forbidden. Créez une nouvelle clé depuis le dashboard.
  • Une boutique qui vend des produits numériques n'a pas de réglages de livraison : toute écriture de cette page y répond 422 shipping_not_available.
  • Chaque écriture demande un en-tête Idempotency-Key. Voir Idempotence.
  • Tester et lier un transporteur appellent ses serveurs pendant la requête, et une synchronisation des tarifs les appelle en arrière-plan. Ces trois appels et POST /v1/orders/{id}/send-to-delivery partagent un budget transporteur par boutique, en plus des limites de taux.
  • Les écritures de tarifs et de réglages peuvent être annulées. La liaison, la déliaison et le changement de transporteur par défaut ne le peuvent pas. La section sur l'annulation, en fin de page, explique comment faire.
  • Les lectures de livraison ne sont pas mises en cache par la passerelle : un GET envoyé juste après une écriture renvoie les nouvelles valeurs.
PortéeDescription
shipping:readLire les tarifs et réglages de livraison, les transporteurs liés, la couverture des transporteurs et les listes de wilayas et de communes.
shipping:writeModifier les tarifs et réglages de livraison, et lier, tester, délier ou synchroniser les transporteurs.

GET /v1/wilayas​

Les wilayas que la boutique dessert, selon son mode de wilayas : 1 à 58 en mode compatible transporteurs, 1 à 69 en mode 69 wilayas. Les noms sont en arabe, en français et en anglais. Toute la liste arrive en une réponse, sans pagination.

Auth : clé plateforme avec shipping:read.

Requête​

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

Réponse 200​

Deux des 58 wilayas sont montrées. mode_note est une phrase en anglais sur le mode.

{
"data": {
"wilaya_mode": "58",
"mode_note": "Courier-compatible mode: wilayas 1-58 only.",
"count": 58,
"wilayas": [
{ "id": 1, "name_ar": "أدرار", "name_fr": "Adrar", "name_en": "Adrar" },
{ "id": 16, "name_ar": "الجزائر", "name_fr": "Alger", "name_en": "Algiers" }
]
}
}

GET /v1/wilayas/{id}/communes​

Les communes d'une wilaya, triées par nom français. Toute wilaya de 1 à 69 reçoit une réponse, quel que soit le mode de wilayas de la boutique. Toute la liste arrive en une réponse.

Auth : clé plateforme avec shipping:read.

C'est la liste de communes de la plateforme. Elle ne dit pas quelles communes un transporteur dessert : c'est le rôle de GET /v1/shipping/coverage.

Requête​

curl 'https://api.dzbuild.app/v1/wilayas/16/communes' \
-H "Authorization: Bearer $DZ_KEY"

Réponse 200​

Deux des 57 communes de la wilaya 16 sont montrées.

{
"data": {
"wilaya_id": 16,
"count": 57,
"communes": [
{ "id": 564, "wilaya_id": 16, "name_ar": "عين بنيان", "name_fr": "Ain Benian" },
{ "id": 558, "wilaya_id": 16, "name_ar": "عين طاية", "name_fr": "Ain Taya" }
]
}
}

Un id qui n'est pas composé de chiffres répond 400 bad_request. Une wilaya qui n'existe pas répond 404 not_found.

GET /v1/shipping/rates​

Le tarif de livraison de chaque wilaya qui a un tarif dans la boutique, indexé par id de wilaya. Une wilaya sans tarif est absente de rates.

Auth : clé plateforme avec shipping:read.

Requête​

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

Réponse 200​

Une seule wilaya est montrée.

{
"data": {
"wilaya_mode": "58",
"currency": "DZD",
"limits": {
"max_price": 100000,
"max_delivery_days": 60
},
"count": 58,
"rates": {
"16": {
"home_price": 400,
"home_enabled": true,
"desk_price": 300,
"desk_enabled": true,
"days": 1,
"is_active": true,
"synced_provider": null,
"synced_at": null
}
}
}
}
ChampSignification
wilaya_mode58 ou 69, la même valeur que dans GET /v1/shipping/settings.
limitsLe prix le plus haut et la valeur days la plus haute qu'accepte POST /v1/shipping/rates.
countNombre de wilayas dans rates.
home_price, desk_pricePrix de la livraison à domicile et de la livraison au bureau, en DZD.
home_enabled, desk_enabledSi la boutique propose ce type de livraison dans cette wilaya.
daysDélai de livraison en jours.
synced_provider, synced_atLe transporteur dont la grille de tarifs a écrit ce tarif en dernier, et quand (YYYY-MM-DD HH:MM:SS). null si aucune synchronisation ne l'a écrit.

POST /v1/shipping/rates​

Crée ou modifie les tarifs des wilayas envoyées. Les autres wilayas ne sont pas touchées.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key.

Corps​

rates est un objet indexé par id de wilaya, écrit en chiffres seuls ("16", pas "016"), avec 1 à 69 wilayas. Chaque valeur porte les champs à modifier, et chaque champ est optionnel.

ChampTypeNotes
home_pricenumberEn DZD, arrondi à deux décimales, de 0 à 100000. Une chaîne numérique est acceptée.
home_enabledbooltrue ou false. 0, 1, "0" et "1" sont aussi acceptés.
desk_pricenumberMêmes règles que home_price.
desk_enabledboolMêmes règles que home_enabled.
daysintUn nombre entier de jours, de 0 à 60.

Un champ omis, ou envoyé à null, garde sa valeur enregistrée. Une wilaya qui n'avait pas de tarif part d'un prix de 0, des deux types de livraison activés et de 3 jours.

Requête​

curl -X POST 'https://api.dzbuild.app/v1/shipping/rates' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: rates-2026-10-06-1" \
-d '{"rates": {"16": {"home_price": 450, "desk_price": 350}, "31": {"desk_enabled": false}}}'

Réponse 200​

rates ne contient que les wilayas écrites, telles qu'enregistrées après l'écriture.

{
"data": {
"updated": 2,
"wilaya_ids": [16, 31],
"rates": {
"16": { "home_price": 450, "home_enabled": true, "desk_price": 350, "desk_enabled": true, "days": 1 },
"31": { "home_price": 500, "home_enabled": true, "desk_price": 350, "desk_enabled": false, "days": 2 }
}
}
}

Les valeurs précédentes sont conservées : l'écriture peut donc être annulée. La réponse ne porte pas de change_id : voir la section sur l'annulation.

GET /v1/shipping/settings​

Les règles de livraison gratuite et le mode de wilayas.

Auth : clé plateforme avec shipping:read.

Requête​

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

Réponse 200​

La réponse porte aussi un objet notes avec deux phrases en anglais qui rappellent la règle du seuil et celle du mode de wilayas. L'exemple ne le montre pas.

{
"data": {
"free_shipping": false,
"free_shipping_threshold": 8000,
"free_shipping_threshold_active": true,
"wilaya_mode": "58"
}
}
ChampSignification
free_shippingtrue quand la livraison est gratuite pour toutes les commandes.
free_shipping_thresholdSous-total de commande en DZD à partir duquel la livraison est gratuite. 0 ou null veut dire pas de seuil.
free_shipping_threshold_activetrue seulement quand le seuil est supérieur à 0.
wilaya_mode"58" : les 58 wilayas avec lesquelles travaillent les transporteurs. "69" : les 69 wilayas, un mode réglé depuis le dashboard.

PATCH /v1/shipping/settings​

Modifie un ou plusieurs des trois réglages. Envoyez-en au moins un ; les autres champs sont ignorés.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key.

Corps​

ChampTypeNotes
free_shippingbooltrue ou false. 0, 1, "0" et "1" sont aussi acceptés.
free_shipping_thresholdnumber ou nullEn DZD, arrondi à deux décimales, de 0 à 99999999.99. 0 ou null désactive le seuil.
wilaya_modestringSeulement "58", qui ramène une boutique en mode 69 wilayas à 58 wilayas. Le passage à 69 wilayas se fait depuis la page Tarifs de livraison du dashboard (/dashboard/shipping) et répond ici 422 wilaya_mode_69_unsupported.

Requête​

curl -X PATCH 'https://api.dzbuild.app/v1/shipping/settings' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: settings-2026-10-06-1" \
-d '{"free_shipping_threshold": 8000}'

Réponse 200​

Les réglages après l'écriture, sans notes. Les valeurs précédentes sont conservées : le changement peut donc être annulé.

GET /v1/shipping/providers​

Tous les transporteurs pris en charge par la plateforme, liés à la boutique ou non, avec ce que chacun demande quand vous le liez. Les valeurs des identifiants ne sont jamais renvoyées : has_id et has_token disent seulement si une valeur est enregistrée. Toute la liste arrive en une réponse.

Auth : clé plateforme avec shipping:read.

Requête​

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

Réponse 200​

Un seul transporteur est montré. La réponse porte aussi une phrase note, omise ici.

{
"data": {
"count": 103,
"providers": [
{
"provider": "yalidine",
"family": "yalidine",
"credentials": {
"api_id": { "label": "API ID", "required": true },
"api_token": { "label": "API Token", "required": true },
"_note": "Send an empty string to keep the currently stored value. Credentials are never returned by this API."
},
"extra_fields": {
"delivery_tier": {
"label": "Service tier",
"required": false,
"values": ["express"],
"note": "Only \"express\" is valid here: this courier rejects the economic parameter outright and every order push would fail."
}
},
"supports_rate_sync": true,
"linked": true,
"source": "store_delivery_providers",
"is_enabled": true,
"is_default": true,
"is_send_default": true,
"has_id": true,
"has_token": true,
"delivery_tier": "express",
"economic_available": null,
"credentials_failed_at": null,
"synced_tier": "express",
"stock_account": null,
"auto_validate": null,
"custom_name": null,
"linked_at": "2026-09-14 10:12:00",
"updated_at": "2026-09-14 10:12:00"
}
]
}
}
ChampSignification
familyyalidine, procolis, ecotrack ou standalone.
credentialsCe que api_id et api_token veulent dire pour ce transporteur, avec ses propres termes. api_token est absent pour un transporteur qui prend une seule valeur.
extra_fieldsLes autres champs que ce transporteur accepte quand vous le liez, indexés par nom. Un tableau vide quand il n'y en a pas.
supports_rate_syncSi POST /v1/shipping/rates/sync fonctionne avec ce transporteur.
linkedSi la boutique a ce transporteur.
sourcestore_delivery_providers pour un transporteur lié depuis la liste des transporteurs (cette API ou le dashboard), store_row pour un transporteur configuré à l'ancienne, directement dans les réglages de la boutique, null s'il n'est pas lié.
is_enabledSi la liaison est activée.
is_defaultSi c'est le transporteur par défaut de la boutique.
is_send_defaultLe transporteur qu'utilise POST /v1/orders/{id}/send-to-delivery quand l'appel n'en nomme aucun.
delivery_tier, synced_tier, economic_availableNiveau de service de la famille Yalidine : celui choisi, celui utilisé par la dernière synchronisation des tarifs, et si le compte proposait le niveau économique lors de cette synchronisation.
stock_account, auto_validate, custom_nameLes champs supplémentaires enregistrés pour ce transporteur, null s'ils ne sont pas définis.
credentials_failed_atHeure ISO 8601, définie quand le transporteur a refusé à plusieurs reprises les identifiants enregistrés. Les envois vers ce transporteur sont refusés tant qu'elle est définie. Lier de nouveau le transporteur l'efface.
linked_at, updated_atYYYY-MM-DD HH:MM:SS. null pour un transporteur configuré dans les réglages de la boutique.

Ce que contiennent api_id et api_token​

providerapi_idapi_token
yalidine, yalitec, guepex, easyandspeed, economiqua, wecanAPI IDAPI Token
zrexpress, abexexpress, leopardexpress, colilog, flashdeliveryTokenKey
zrexpressnewAPI Key (secret key)Tenant ID
noestAPI TokenUser GUID
colivraisonPublic KeyBearer Token
ecomdeliveryAPI KeyAPI Token
neardeliveryApiKeyApiSecret
maystroAPI Tokenaucun
zimouBearer Tokenaucun
elogistiaAPI Keyaucun
mdmx-api-keyaucun
customecotrack et tous les transporteurs de la famille ecotrackBearer Tokenaucun

Champs supplémentaires, tous optionnels sauf indication contraire :

  • delivery_tier, famille Yalidine : express. guepex accepte aussi economic.
  • stock_account, famille ecotrack : préparer les commandes depuis le stock du transporteur.
  • auto_validate, noest : valider les commandes automatiquement chez le transporteur.
  • api_url et custom_name, customecotrack, tous deux requis pour lier : l'adresse Ecotrack https du transporteur (un hôte qui se termine par .ecotrack.dz, ou platform.dhd-dz.com ou app.conexlog-dz.com) et le nom à afficher pour lui, jusqu'à 100 caractères.

POST /v1/shipping/providers/test​

Envoie des identifiants au transporteur et indique s'il les a acceptés. Rien n'est enregistré. Un api_id ou un api_token vide ou absent reprend la valeur enregistrée pour ce transporteur : vous pouvez donc retester un transporteur lié sans détenir ses identifiants.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key. Compte dans le budget transporteur.

Corps​

ChampTypeRequisNotes
providerstringouiUn slug de GET /v1/shipping/providers.
api_idstringsauf si enregistréPremier identifiant.
api_tokenstringsauf si enregistréSecond identifiant, pour les transporteurs qui en prennent deux.
api_urlstringcustomecotrack seulementL'adresse Ecotrack du transporteur. Quand les identifiants enregistrés sont réutilisés, elle doit correspondre à l'adresse enregistrée.
delivery_tierstringnonexpress ou economic. economic n'est accepté que pour guepex.

Requête​

curl -X POST 'https://api.dzbuild.app/v1/shipping/providers/test' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: test-yalidine-1" \
-d '{"provider": "yalidine", "api_id": "YOUR_API_ID", "api_token": "YOUR_API_TOKEN"}'

Réponse 200​

Un transporteur qui refuse les identifiants répond aussi 200, avec ok: false et le message de la vérification chez le transporteur. resolved_provider n'est défini que pour zrexpressnew : la plateforme ZR Express qui a accepté la paire.

{
"data": {
"provider": "yalidine",
"ok": true,
"message": "تم الاتصال بنجاح",
"resolved_provider": null,
"saved": false
}
}

POST /v1/shipping/providers​

Lie un transporteur, ou réenregistre un transporteur lié. La plateforme teste d'abord les identifiants auprès du transporteur et n'enregistre rien s'il les refuse.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key. Compte dans le budget transporteur.

Corps​

Les champs de l'appel de test, plus :

ChampTypeDéfautNotes
enabledbooltrueActiver ou désactiver la liaison.
set_defaultboolfalseFaire de ce transporteur celui par défaut de la boutique.
custom_namestringaucuncustomecotrack seulement, requis là. Les balises HTML sont retirées et le nom est coupé à 100 caractères.
stock_accountboolvaleur enregistréeFamille ecotrack.
auto_validateboolvaleur enregistréenoest.
  • Un api_id ou un api_token vide garde la valeur enregistrée : un transporteur lié peut être réenregistré sans renvoyer ses identifiants.
  • Le premier transporteur que lie une boutique devient son transporteur par défaut. Dans la réponse, is_default vaut true seulement quand cet appel a fait du transporteur celui par défaut : un transporteur par défaut réenregistré sans set_default le reste alors que la réponse dit false. GET /v1/shipping/providers montre l'état réel.
  • zrexpress et zrexpressnew sont un seul transporteur : lier l'un remplace l'autre. Une paire zrexpressnew acceptée par l'ancienne plateforme ZR Express est enregistrée comme zrexpress, et provider dans la réponse l'indique.

Requête​

curl -X POST 'https://api.dzbuild.app/v1/shipping/providers' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: link-yalidine-1" \
-d '{"provider": "yalidine", "api_id": "YOUR_API_ID", "api_token": "YOUR_API_TOKEN", "set_default": true}'

Réponse 200​

{
"data": {
"provider": "yalidine",
"is_enabled": true,
"is_default": true,
"has_id": true,
"has_token": true,
"undoable": false,
"note": "Courier credentials are never recorded, so linking cannot be undone. To revert, link the previous courier again or unlink this one."
}
}

Un identifiant refusé répond 422 credentials_rejected avec le message du transporteur, et rien n'est enregistré.

POST /v1/shipping/providers/default​

Fait d'un transporteur lié celui par défaut de la boutique. Les nouveaux envois en livraison partent vers lui.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key.

provider dans le corps nomme le transporteur. Seul un transporteur lié depuis la liste des transporteurs peut devenir celui par défaut ; un transporteur configuré dans les réglages de la boutique répond 404 provider_not_linked. Quand le transporteur choisi est désactivé, warning indique que les envois restent coupés jusqu'à ce qu'il soit réactivé.

Requête​

curl -X POST 'https://api.dzbuild.app/v1/shipping/providers/default' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: default-noest-1" \
-d '{"provider": "noest"}'

Réponse 200​

{
"data": {
"provider": "noest",
"is_default": true,
"previous_default": "yalidine",
"undoable": false,
"warning": "New send-to-delivery pushes now go to \"noest\". "
}
}

Confirmation avant une synchronisation des tarifs ou une déliaison​

Une synchronisation écrase les prix du marchand et une déliaison retire des identifiants enregistrés : ces deux appels demandent donc une confirmation avant d'agir.

  1. Appelez sans confirmation. La réponse est 422 confirmation_required, et l'objet error ajoute confirm_token (usage unique), confirm_token_expires_in (600 secondes), action et will_change, le résumé à montrer au marchand.
  2. Une fois que le marchand approuve, refaites l'appel avec confirm_token dans le corps et une nouvelle Idempotency-Key. La première clé est liée au corps sans le jeton : la réutiliser répond 422 idempotency_key_reuse.

Un jeton fonctionne une seule fois, seulement pour la clé qui l'a reçu, et seulement tant que ce qu'il décrit n'a pas changé : la table des tarifs pour une synchronisation, et pour une déliaison le nombre de transporteurs liés et le fait que celui-ci soit ou non celui par défaut. Un jeton déjà utilisé, expiré ou qui ne correspond plus répond 422 confirmation_stale avec un nouveau jeton et un nouveau résumé.

Une clé qui n'est pas utilisée par l'assistant intégré au dashboard peut envoyer "confirm": true au lieu d'un jeton et sauter l'étape 1. Les clés utilisées par l'assistant doivent envoyer le jeton.

Voici la première réponse d'une synchronisation.

{
"error": {
"code": "confirmation_required",
"message": "Syncing overwrites your own prices for every wilaya \"yalidine\" serves. Show the merchant the summary below; when they approve, re-send with the confirm_token.",
"confirm_token": "cft_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"confirm_token_expires_in": 600,
"action": "shipping.rates_sync:yalidine",
"will_change": {
"action": "Overwrite shipping rates from yalidine",
"wilayas_at_risk": 58,
"reversible": true,
"note": "The prior prices are saved to the change log first, so this can be undone."
}
}
}

Pour une déliaison, will_change contient action, was_store_default, remaining_providers, consequence, reversible (false) et note.

POST /v1/shipping/rates/sync​

Remplace les prix de la boutique par la grille de tarifs du transporteur, pour chaque wilaya de 1 à 58 que le transporteur tarifie. La synchronisation tourne en arrière-plan. Avant toute mise en file, toute la table des tarifs est conservée, et le change_id de la réponse annule la synchronisation.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key et une confirmation. Compte dans le budget transporteur.

Corps​

ChampTypeRequisNotes
providerstringouiUn transporteur lié depuis la liste des transporteurs et activé. mdm et neardelivery n'ont pas de grille de tarifs.
confirm_tokenstringvoir plus hautTiré de la réponse confirmation_required.
confirmboolvoir plus hauttrue, pour les clés non utilisées par l'assistant.

Ce que change la synchronisation​

  • Elle écrit home_price et desk_price et renseigne synced_provider et synced_at. Les interrupteurs et days d'une wilaya qui avait déjà un tarif restent tels quels. Une wilaya qui n'avait pas de tarif reçoit 3 jours.
  • Les transporteurs de la famille Yalidine ont besoin de la wilaya de la boutique, réglée avec wilaya_id dans PATCH /v1/store (voir Boutique). Sans elle, l'appel répond 422 store_wilaya_required.
  • Suivez le résultat avec GET /v1/shipping/rates : les tarifs écrits par la synchronisation nomment le transporteur dans synced_provider et portent un nouveau synced_at. Quand le transporteur n'envoie aucun prix, les tarifs restent tels quels.
  • Tant qu'une synchronisation du même transporteur tourne, l'appel répond 202 avec status: already_running, le sync_id de cette synchronisation et change_id: null, sans demander de confirmation.
  • Après une synchronisation réussie, le même transporteur peut être resynchronisé 5 minutes plus tard. Un appel plus tôt répond 429 sync_cooldown.

Requête​

curl -X POST 'https://api.dzbuild.app/v1/shipping/rates/sync' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: sync-yalidine-2" \
-d '{"provider": "yalidine", "confirm_token": "cft_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}'

Réponse 202​

{
"data": {
"status": "queued",
"sync_id": "a1b2c3d4e5f6a7b8c9d0e1f2",
"change_id": 500,
"note": "The sync runs in the background and overwrites your prices for every wilaya this courier serves. Poll GET /v1/shipping/rates for the result; undo change_id to restore the prior prices."
}
}

DELETE /v1/shipping/providers/{provider}​

Délie un transporteur et retire ses identifiants de la boutique. C'est irréversible : pour envoyer de nouveau avec ce transporteur, liez-le de nouveau. Les colis déjà chez le transporteur restent suivis.

Auth : clé plateforme avec shipping:write. Nécessite Idempotency-Key et une confirmation.

  • provider dans le chemin est le slug du transporteur. Seul un transporteur lié depuis la liste des transporteurs peut être délié ici ; tout autre répond 404 provider_not_linked.
  • Le corps ne porte que la confirmation : confirm_token, ou confirm: true pour les clés non utilisées par l'assistant.
  • Quand le transporteur délié était celui par défaut, l'autre transporteur activé lié en premier devient celui par défaut.
  • S'il n'y en a aucun, aucun transporteur n'est par défaut et les envois en livraison s'arrêtent pour toute la boutique. La réponse porte alors new_default: null et send_to_delivery_active: false.

Requête​

curl -X DELETE 'https://api.dzbuild.app/v1/shipping/providers/yalidine' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unlink-yalidine-2" \
-d '{"confirm_token": "cft_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}'

Réponse 200​

{
"data": {
"provider": "yalidine",
"unlinked": true,
"undoable": false,
"remaining_providers": 1,
"new_default": "noest",
"send_to_delivery_active": true,
"warning": "The store default is now \"noest\"; new send-to-delivery pushes go there."
}
}

GET /v1/shipping/coverage​

Les wilayas, communes et stop desks que dessert un transporteur lié, d'après les données du transporteur lui-même. Un transporteur configuré dans les réglages de la boutique compte ici comme lié.

Auth : clé plateforme avec shipping:read.

Paramètres de requête​

ParamTypeDéfautNotes
providerstringaucunLe slug d'un transporteur lié. Sans lui, le transporteur marqué is_send_default, sinon le premier lié.
wilaya_idint00 donne un décompte par wilaya. 1 à 69 ajoute les communes de cette wilaya, ses stop desks et desk_send_allowed. Une valeur hors de 0 à 69 répond 400 bad_request.

Requête​

curl 'https://api.dzbuild.app/v1/shipping/coverage?wilaya_id=16' \
-H "Authorization: Bearer $DZ_KEY"

Réponse 200​

Une commune et un stop desk sont montrés.

{
"data": {
"provider": "yalidine",
"is_send_default": true,
"knowledge_synced_at": "2026-10-05 03:12:44",
"wilayas": [
{ "wilaya_id": 16, "name": "Alger", "communes": 57, "communes_home": 57, "communes_desk": 12, "desks": 9 }
],
"wilaya_id": 16,
"desk_send_allowed": true,
"communes": [
{ "commune_id": 521, "name": "Alger Centre", "name_ar": "الجزائر الوسطى", "home": true, "desk": true }
],
"desks": [
{ "desk_id": "160101", "name": "Agence Alger Centre", "address": "Alger Centre", "phone": null, "commune_id": 521 }
]
}
}
ChampSignification
knowledge_synced_atLa dernière fois que la plateforme a rafraîchi les communes et les stop desks de ce transporteur. null si elle ne l'a jamais fait.
wilayasPar wilaya : le nombre de communes, combien reçoivent la livraison à domicile (communes_home) et au bureau (communes_desk), et le nombre de desks. Avec wilaya_id, seulement cette wilaya.
desk_send_allowedSi POST /v1/orders/{id}/send-to-delivery accepte une commande au bureau vers cette wilaya avec ce transporteur. C'est la même vérification.
communescommune_id est l'id de GET /v1/wilayas/{id}/communes, ou null quand la commune du transporteur n'a pas de correspondance, et name est alors le nom donné par le transporteur. home et desk disent quels types de livraison le transporteur propose là.
desksLes stop desks du transporteur dans la wilaya. Le guide Thèmes & vitrines personnalisés montre comment les proposer au checkout.

Une boutique sans transporteur répond 422 no_courier_linked. Un provider que la boutique n'a pas lié répond 404 provider_not_linked.

Annuler les changements de tarifs et de réglages​

POST /v1/shipping/rates, PATCH /v1/shipping/settings et une synchronisation des tarifs conservent les valeurs qu'ils remplacent : chacun peut donc être annulé avec POST /v1/changes/{id}/undo.

  • Une synchronisation répond avec son change_id. Les deux autres écritures non : trouvez le changement avec GET /v1/changes?entity=shipping.rates ou GET /v1/changes?entity=shipping.settings, du plus récent au plus ancien. Lister les changements demande store:read.
  • L'annulation demande shipping:write et une Idempotency-Key. L'annulation est elle-même un changement, undo_change_id, que vous pouvez annuler à son tour, sauf l'annulation d'une synchronisation, qui répond 422 nothing_to_restore. Voir Changements et annulation.
  • Annuler une écriture de tarifs supprime les tarifs des wilayas que cette écriture a créés. Annuler une synchronisation remet les wilayas qui avaient un tarif avant elle ; une wilaya ajoutée par la synchronisation garde son nouveau tarif.
  • L'annulation réécrit les valeurs conservées même si les tarifs ou les réglages ont changé depuis, dans le dashboard ou par l'API.
  • Un changement annulé une seconde fois répond 409 already_undone.
  • Le jeton d'une application installée ne peut ni lister ni annuler les changements : les deux répondent 403 forbidden.
curl -X POST 'https://api.dzbuild.app/v1/changes/500/undo' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: undo-500"
{
"data": {
"undone": true,
"change_id": 500,
"entity": "shipping.rates",
"undo_change_id": 510
}
}

Erreurs​

HTTPCodeCause
400bad_requestLe corps n'est pas un objet JSON, rates manque ou n'est pas un objet, un id dans le chemin est mal formé, wilaya_id est hors de 0 à 69, ou Idempotency-Key manque ou est mal formé.
400invalid_ratesrates est vide ou a plus de 69 wilayas, un tarif n'est pas un objet, ou un interrupteur n'est pas un booléen.
400, 422invalid_wilaya400 : une clé de rates n'est pas en chiffres seuls. 422 : aucune wilaya n'a cet id.
400, 422invalid_price400 : pas un nombre. 422 : négatif ou supérieur à 100000.
400, 422invalid_days400 : pas un nombre entier. 422 : hors de 0 à 60.
400nothing_to_updatePATCH /v1/shipping/settings sans aucun de ses trois champs.
400invalid_free_shippingfree_shipping n'est pas un booléen.
400, 422invalid_threshold400 : ni un nombre ni null. 422 : négatif ou supérieur à 99999999.99.
400invalid_wilaya_modewilaya_mode n'est ni "58" ni "69".
422wilaya_mode_69_unsupportedwilaya_mode vaut "69", qui se règle depuis le dashboard.
400provider_requiredprovider manque.
400credentials_requiredAucun api_id envoyé ni enregistré, ou aucun api_token pour un transporteur qui prend deux valeurs.
400invalid_credentials_formatDes valeurs zrexpressnew qui contiennent des accolades JSON, des espaces ou des retours à la ligne, qui commencent par http, ou qui dépassent 128 caractères.
400api_url_required, custom_name_requiredcustomecotrack sans son adresse, ou une liaison sans son nom.
400, 422invalid_delivery_tier400 : ni express ni economic. 422 : economic pour un autre transporteur que guepex.
422unsupported_providerLe slug n'est pas dans GET /v1/shipping/providers.
422invalid_api_url, api_url_mismatchL'adresse customecotrack n'est pas une adresse Ecotrack https, ou diffère de celle enregistrée alors que les identifiants enregistrés sont réutilisés.
422credentials_rejectedLe transporteur a refusé les identifiants. Rien n'a été enregistré.
422rate_sync_unsupportedmdm et neardelivery n'ont pas de grille de tarifs.
422provider_not_linkedSynchronisation : le transporteur n'est pas lié depuis la liste des transporteurs, ou est désactivé.
404provider_not_linkedDéfaut, déliaison ou couverture : la boutique n'a pas lié ce transporteur.
422store_wilaya_requiredSynchronisation d'un transporteur de la famille Yalidine avant que la wilaya de la boutique soit réglée.
422confirmation_required, confirmation_staleVoir la section sur la confirmation plus haut.
422snapshot_too_large, snapshot_failedLes tarifs précédents n'ont pas pu être conservés : l'écriture a été refusée plutôt que de devenir impossible à annuler.
422no_courier_linkedCouverture pour une boutique sans transporteur.
422shipping_not_availableUne écriture sur une boutique qui vend des produits numériques.
422idempotency_key_reuseLa même Idempotency-Key avec un corps différent.
403forbiddenLa clé n'a pas la portée, par exemple « Missing scope: shipping:write », ou clé du marchand dont la boutique n'a pas de plan Enterprise actif.
404not_foundCommunes d'une wilaya qui n'existe pas.
404store_not_foundLa boutique de la clé n'existe plus.
429sync_cooldownLe même transporteur a été synchronisé il y a moins de 5 minutes. Le message indique combien de minutes il reste.
429rate_limited, too_many_concurrentLe budget transporteur ou la limite de requêtes de la boutique est épuisé. Voir Limites de taux.
503sync_queue_failedLa synchronisation n'a pas pu démarrer et les tarifs n'ont pas changé. Réessayez plus tard.
500server_errorRéessayez avec la même Idempotency-Key.
Cette page pour les outils IAVoir en MarkdownOuvrir dans ChatGPTOuvrir dans Claude