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épond403 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-deliverypartagent 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
GETenvoyé juste après une écriture renvoie les nouvelles valeurs.
| Portée | Description |
|---|---|
shipping:read | Lire les tarifs et réglages de livraison, les transporteurs liés, la couverture des transporteurs et les listes de wilayas et de communes. |
shipping:write | Modifier 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
}
}
}
}
| Champ | Signification |
|---|---|
wilaya_mode | 58 ou 69, la même valeur que dans GET /v1/shipping/settings. |
limits | Le prix le plus haut et la valeur days la plus haute qu'accepte POST /v1/shipping/rates. |
count | Nombre de wilayas dans rates. |
home_price, desk_price | Prix de la livraison à domicile et de la livraison au bureau, en DZD. |
home_enabled, desk_enabled | Si la boutique propose ce type de livraison dans cette wilaya. |
days | Délai de livraison en jours. |
synced_provider, synced_at | Le 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.
| Champ | Type | Notes |
|---|---|---|
home_price | number | En DZD, arrondi à deux décimales, de 0 à 100000. Une chaîne numérique est acceptée. |
home_enabled | bool | true ou false. 0, 1, "0" et "1" sont aussi acceptés. |
desk_price | number | Mêmes règles que home_price. |
desk_enabled | bool | Mêmes règles que home_enabled. |
days | int | Un 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"
}
}
| Champ | Signification |
|---|---|
free_shipping | true quand la livraison est gratuite pour toutes les commandes. |
free_shipping_threshold | Sous-total de commande en DZD à partir duquel la livraison est gratuite. 0 ou null veut dire pas de seuil. |
free_shipping_threshold_active | true 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
| Champ | Type | Notes |
|---|---|---|
free_shipping | bool | true ou false. 0, 1, "0" et "1" sont aussi acceptés. |
free_shipping_threshold | number ou null | En DZD, arrondi à deux décimales, de 0 à 99999999.99. 0 ou null désactive le seuil. |
wilaya_mode | string | Seulement "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"
}
]
}
}
| Champ | Signification |
|---|---|
family | yalidine, procolis, ecotrack ou standalone. |
credentials | Ce 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_fields | Les 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_sync | Si POST /v1/shipping/rates/sync fonctionne avec ce transporteur. |
linked | Si la boutique a ce transporteur. |
source | store_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_enabled | Si la liaison est activée. |
is_default | Si c'est le transporteur par défaut de la boutique. |
is_send_default | Le transporteur qu'utilise POST /v1/orders/{id}/send-to-delivery quand l'appel n'en nomme aucun. |
delivery_tier, synced_tier, economic_available | Niveau 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_name | Les champs supplémentaires enregistrés pour ce transporteur, null s'ils ne sont pas définis. |
credentials_failed_at | Heure 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_at | YYYY-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
provider | api_id | api_token |
|---|---|---|
yalidine, yalitec, guepex, easyandspeed, economiqua, wecan | API ID | API Token |
zrexpress, abexexpress, leopardexpress, colilog, flashdelivery | Token | Key |
zrexpressnew | API Key (secret key) | Tenant ID |
noest | API Token | User GUID |
colivraison | Public Key | Bearer Token |
ecomdelivery | API Key | API Token |
neardelivery | ApiKey | ApiSecret |
maystro | API Token | aucun |
zimou | Bearer Token | aucun |
elogistia | API Key | aucun |
mdm | x-api-key | aucun |
customecotrack et tous les transporteurs de la famille ecotrack | Bearer Token | aucun |
Champs supplémentaires, tous optionnels sauf indication contraire :
delivery_tier, famille Yalidine :express.guepexaccepte aussieconomic.stock_account, familleecotrack: préparer les commandes depuis le stock du transporteur.auto_validate,noest: valider les commandes automatiquement chez le transporteur.api_urletcustom_name,customecotrack, tous deux requis pour lier : l'adresse Ecotrack https du transporteur (un hôte qui se termine par.ecotrack.dz, ouplatform.dhd-dz.comouapp.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
| Champ | Type | Requis | Notes |
|---|---|---|---|
provider | string | oui | Un slug de GET /v1/shipping/providers. |
api_id | string | sauf si enregistré | Premier identifiant. |
api_token | string | sauf si enregistré | Second identifiant, pour les transporteurs qui en prennent deux. |
api_url | string | customecotrack seulement | L'adresse Ecotrack du transporteur. Quand les identifiants enregistrés sont réutilisés, elle doit correspondre à l'adresse enregistrée. |
delivery_tier | string | non | express 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 :
| Champ | Type | Défaut | Notes |
|---|---|---|---|
enabled | bool | true | Activer ou désactiver la liaison. |
set_default | bool | false | Faire de ce transporteur celui par défaut de la boutique. |
custom_name | string | aucun | customecotrack seulement, requis là. Les balises HTML sont retirées et le nom est coupé à 100 caractères. |
stock_account | bool | valeur enregistrée | Famille ecotrack. |
auto_validate | bool | valeur enregistrée | noest. |
- Un
api_idou unapi_tokenvide 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_defaultvauttrueseulement quand cet appel a fait du transporteur celui par défaut : un transporteur par défaut réenregistré sansset_defaultle reste alors que la réponse ditfalse.GET /v1/shipping/providersmontre l'état réel. zrexpressetzrexpressnewsont un seul transporteur : lier l'un remplace l'autre. Une pairezrexpressnewacceptée par l'ancienne plateforme ZR Express est enregistrée commezrexpress, etproviderdans 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.
- Appelez sans confirmation. La réponse est
422 confirmation_required, et l'objeterrorajouteconfirm_token(usage unique),confirm_token_expires_in(600secondes),actionetwill_change, le résumé à montrer au marchand. - Une fois que le marchand approuve, refaites l'appel avec
confirm_tokendans le corps et une nouvelleIdempotency-Key. La première clé est liée au corps sans le jeton : la réutiliser répond422 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
| Champ | Type | Requis | Notes |
|---|---|---|---|
provider | string | oui | Un transporteur lié depuis la liste des transporteurs et activé. mdm et neardelivery n'ont pas de grille de tarifs. |
confirm_token | string | voir plus haut | Tiré de la réponse confirmation_required. |
confirm | bool | voir plus haut | true, pour les clés non utilisées par l'assistant. |
Ce que change la synchronisation
- Elle écrit
home_priceetdesk_priceet renseignesynced_provideretsynced_at. Les interrupteurs etdaysd'une wilaya qui avait déjà un tarif restent tels quels. Une wilaya qui n'avait pas de tarif reçoit3jours. - Les transporteurs de la famille Yalidine ont besoin de la wilaya de la boutique, réglée avec
wilaya_iddansPATCH /v1/store(voir Boutique). Sans elle, l'appel répond422 store_wilaya_required. - Suivez le résultat avec
GET /v1/shipping/rates: les tarifs écrits par la synchronisation nomment le transporteur danssynced_provideret portent un nouveausynced_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
202avecstatus: already_running, lesync_idde cette synchronisation etchange_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.
providerdans le chemin est le slug du transporteur. Seul un transporteur lié depuis la liste des transporteurs peut être délié ici ; tout autre répond404 provider_not_linked.- Le corps ne porte que la confirmation :
confirm_token, ouconfirm: truepour 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: nulletsend_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
| Param | Type | Défaut | Notes |
|---|---|---|---|
provider | string | aucun | Le slug d'un transporteur lié. Sans lui, le transporteur marqué is_send_default, sinon le premier lié. |
wilaya_id | int | 0 | 0 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 }
]
}
}
| Champ | Signification |
|---|---|
knowledge_synced_at | La 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. |
wilayas | Par 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_allowed | Si 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. |
communes | commune_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à. |
desks | Les 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 avecGET /v1/changes?entity=shipping.ratesouGET /v1/changes?entity=shipping.settings, du plus récent au plus ancien. Lister les changements demandestore:read. - L'annulation demande
shipping:writeet uneIdempotency-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épond422 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
| HTTP | Code | Cause |
|---|---|---|
| 400 | bad_request | Le 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é. |
| 400 | invalid_rates | rates 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, 422 | invalid_wilaya | 400 : une clé de rates n'est pas en chiffres seuls. 422 : aucune wilaya n'a cet id. |
| 400, 422 | invalid_price | 400 : pas un nombre. 422 : négatif ou supérieur à 100000. |
| 400, 422 | invalid_days | 400 : pas un nombre entier. 422 : hors de 0 à 60. |
| 400 | nothing_to_update | PATCH /v1/shipping/settings sans aucun de ses trois champs. |
| 400 | invalid_free_shipping | free_shipping n'est pas un booléen. |
| 400, 422 | invalid_threshold | 400 : ni un nombre ni null. 422 : négatif ou supérieur à 99999999.99. |
| 400 | invalid_wilaya_mode | wilaya_mode n'est ni "58" ni "69". |
| 422 | wilaya_mode_69_unsupported | wilaya_mode vaut "69", qui se règle depuis le dashboard. |
| 400 | provider_required | provider manque. |
| 400 | credentials_required | Aucun api_id envoyé ni enregistré, ou aucun api_token pour un transporteur qui prend deux valeurs. |
| 400 | invalid_credentials_format | Des 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. |
| 400 | api_url_required, custom_name_required | customecotrack sans son adresse, ou une liaison sans son nom. |
| 400, 422 | invalid_delivery_tier | 400 : ni express ni economic. 422 : economic pour un autre transporteur que guepex. |
| 422 | unsupported_provider | Le slug n'est pas dans GET /v1/shipping/providers. |
| 422 | invalid_api_url, api_url_mismatch | L'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. |
| 422 | credentials_rejected | Le transporteur a refusé les identifiants. Rien n'a été enregistré. |
| 422 | rate_sync_unsupported | mdm et neardelivery n'ont pas de grille de tarifs. |
| 422 | provider_not_linked | Synchronisation : le transporteur n'est pas lié depuis la liste des transporteurs, ou est désactivé. |
| 404 | provider_not_linked | Défaut, déliaison ou couverture : la boutique n'a pas lié ce transporteur. |
| 422 | store_wilaya_required | Synchronisation d'un transporteur de la famille Yalidine avant que la wilaya de la boutique soit réglée. |
| 422 | confirmation_required, confirmation_stale | Voir la section sur la confirmation plus haut. |
| 422 | snapshot_too_large, snapshot_failed | Les tarifs précédents n'ont pas pu être conservés : l'écriture a été refusée plutôt que de devenir impossible à annuler. |
| 422 | no_courier_linked | Couverture pour une boutique sans transporteur. |
| 422 | shipping_not_available | Une écriture sur une boutique qui vend des produits numériques. |
| 422 | idempotency_key_reuse | La même Idempotency-Key avec un corps différent. |
| 403 | forbidden | La 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. |
| 404 | not_found | Communes d'une wilaya qui n'existe pas. |
| 404 | store_not_found | La boutique de la clé n'existe plus. |
| 429 | sync_cooldown | Le même transporteur a été synchronisé il y a moins de 5 minutes. Le message indique combien de minutes il reste. |
| 429 | rate_limited, too_many_concurrent | Le budget transporteur ou la limite de requêtes de la boutique est épuisé. Voir Limites de taux. |
| 503 | sync_queue_failed | La synchronisation n'a pas pu démarrer et les tarifs n'ont pas changé. Réessayez plus tard. |
| 500 | server_error | Réessayez avec la même Idempotency-Key. |