Aller au contenu principal

API d'intégration

Cette API permet à un connecteur de boutique en ligne de lire le catalogue et le stock de Nadigit IMS, de réserver du stock pour un panier et d'enregistrer des commandes. Nadigit IMS notifie en retour le connecteur par des webhooks signés. C'est l'API qu'utilise le connecteur Bagisto ; elle sert aussi à développer un connecteur pour une autre plateforme.

Cette page ne documente que l'API d'intégration : les autres API de Nadigit IMS sont réservées à la console web.

Avant de commencer​

  • Formule Enterprise.
  • Une intégration déclarée et provisionnée dans Intégrations e-commerce. Le provisionnement fournit la configuration du connecteur. Voir Intégration e-commerce.
Champ de la configurationUsage
backendUrlAdresse de base de l'API : les chemins ci-dessous s'y ajoutent
keycloakTokenUrlAdresse d'obtention des jetons
keycloakClientId, keycloakClientSecretIdentifiants du connecteur
webhookSecretSecret de vérification des webhooks

Authentification​

Le connecteur obtient un jeton d'accès par le flux OAuth 2.0 client credentials, puis l'envoie dans l'en-tête Authorization de chaque appel.

curl -s -X POST "$KEYCLOAK_TOKEN_URL" \
-d grant_type=client_credentials \
-d client_id="$CLIENT_ID" \
-d client_secret="$CLIENT_SECRET"
GET /api/ecommerce/catalog HTTP/1.1
Authorization: Bearer <access_token>
  • Le jeton a une durée de vie courte (expires_in, en secondes) : conservez-le et renouvelez-le juste avant son expiration, plutôt qu'à chaque appel.
  • Périmètre. Le connecteur n'accède qu'à l'API d'intégration, et seulement pour l'entrepôt et le magasin liés à l'intégration. L'entrepôt n'est jamais un paramètre de requête : il est fixé par l'identité du connecteur.

Conventions​

  • Échanges en JSON, encodage UTF-8.
  • Le SKU est la référence de l'article dans Nadigit IMS, unique dans l'entrepôt.
  • Les quantités sont exprimées dans l'unité de vente de l'article, avec des décimales pour les articles vendus au poids ou à la mesure (fractional).
  • Les montants sont dans la devise de l'organisation.

Points d'accès​

MéthodeCheminRôle
GET/api/ecommerce/catalogCatalogue publiable, paginé
GET/api/ecommerce/catalog/{sku}Un article
GET/api/ecommerce/stock?skus=…Stock de 200 articles au plus
PUT/api/ecommerce/reservations/{cartId}Réserver le stock d'un panier
POST/api/ecommerce/ordersEnregistrer une commande
POST/api/ecommerce/orders/{reference}/cancelAnnuler une commande

Catalogue​

GET /api/ecommerce/catalog?page=0&size=100
GET /api/ecommerce/catalog/ACC-POIG-BL

Le catalogue contient les articles actifs et physiques de l'entrepôt lié ; les services en sont exclus. La liste est paginée (page à partir de 0, size de 1 à 200, 100 par défaut) et triée par SKU. Un SKU inconnu, inactif ou d'un autre entrepôt renvoie 404.

{
"sku": "ACC-POIG-BL",
"name": "Poignée de fenêtre à crémone – blanc",
"description": "…",
"category": "Accessoires",
"categoryPath": ["Accessoires"],
"price": 45.0,
"taxRate": 20.0,
"taxClass": "…",
"taxInclusive": false,
"allocatable": 146.0,
"measureUnit": "Unité",
"fractional": false,
"quantityPrecision": 0,
"primaryImageUrl": "https://…",
"imageUrls": ["https://…"],
"barcodes": ["…"]
}

La liste renvoie ces objets dans une page (content, totalElements, totalPages, number, size). Le catalogue ne propose pas encore de filtre « modifié depuis » : synchronisez-le entièrement, puis appuyez-vous sur les webhooks pour les changements.

Stock​

GET /api/ecommerce/stock?skus=ACC-POIG-BL,SIL-NEU-280,INCONNU
[
{ "sku": "ACC-POIG-BL", "found": true, "sellable": 148.0, "reservedByOthers": 2.0, "allocatable": 146.0 },
{ "sku": "INCONNU", "found": false, "sellable": null, "reservedByOthers": null, "allocatable": null }
]
ChampSignification
sellableStock vendable dans l'entrepôt
reservedByOthersQuantité réservée par d'autres paniers ou ventes en cours
allocatableCe qui peut encore être vendu : c'est la quantité à afficher
foundfalse pour un SKU inconnu : retirez-le de la vente

Jusqu'à 200 SKU par appel, séparés par des virgules.

Réservations​

Réserver le stock d'un panier évite de vendre en ligne un article déjà parti. Appelez ce point d'accès à chaque modification du panier et juste avant le paiement.

PUT /api/ecommerce/reservations/panier-8841
Content-Type: application/json

{ "lines": [ { "sku": "ACC-POIG-BL", "quantity": 2 } ] }
  • 204 : la réservation du panier est remplacée par ces lignes.
  • 409 : le paiement doit être bloqué.
{
"code": "insufficient_stock",
"message": "…",
"lines": [ { "sku": "ACC-POIG-BL", "requested": 2, "allocatable": 1 } ]
}

code vaut insufficient_stock (stock insuffisant, ligne par ligne) ou reservations_disabled (les réservations souples sont désactivées dans Nadigit IMS). Une réservation expire d'elle-même : un panier abandonné libère son stock sans action du connecteur.

Commandes​

POST /api/ecommerce/orders
Content-Type: application/json

{
"reference": "WEB-1000231",
"cartId": "panier-8841",
"orderDate": "2026-09-24T18:40:00",
"customer": { "email": "client@exemple.ma", "firstName": "Salma", "lastName": "Idrissi", "phone": "+212600000000" },
"lines": [ { "sku": "ACC-POIG-BL", "quantity": 2, "unitPrice": 45.0 } ],
"declaredTotal": 108.0,
"paymentMethod": "card",
"paymentReference": "ch_3Q…"
}
ChampObligatoireRemarque
referenceOuiRéférence de la commande sur la boutique, 64 caractères au plus. Sert de clé d'unicité
cartIdNonLe panier dont la réservation est consommée
customerNonClient retrouvé par e-mail, ou créé
linesOuiSKU et quantités. unitPrice est indicatif
shipping, declaredTotalNonIndicatifs, comparés au total recalculé
paymentMethodNonVoir ci-dessous
paymentReferenceNonRéférence de la transaction, conservée sur le paiement

Comportement :

  • Nadigit IMS recalcule les prix et les taxes. Si declaredTotal diffère, la commande est acceptée et priceMismatch vaut true.
  • La commande sort le stock de l'entrepôt et est rattachée au magasin lié.
  • Idempotence : renvoyer la même reference renvoie la commande existante (alreadyExisted: true), sans créer de doublon. Un connecteur peut donc rejouer une commande en toute sécurité.
  • paymentMethod : card, wallet, stripe, paypal, online, transfer ou cash enregistrent un paiement : la commande est payée. cod (paiement à la livraison), une valeur vide ou inconnue n'enregistrent rien : la commande reste impayée.
{
"reference": "WEB-1000231",
"status": "Processing",
"paymentStatus": "PAID",
"totalAmount": 108.0,
"dutyFreeAmount": 90.0,
"taxAmount": 18.0,
"alreadyExisted": false,
"priceMismatch": false,
"declaredTotal": 108.0
}

Annulation​

POST /api/ecommerce/orders/WEB-1000231/cancel

Annule la commande et remet son stock dans l'entrepôt. Une commande déjà annulée renvoie un succès avec alreadyExisted: true ; une référence inconnue dans l'entrepôt renvoie 404. Le remboursement éventuel n'est pas automatique.

Webhooks​

Nadigit IMS appelle le connecteur à l'adresse URL de la boutique + Chemin du webhook déclarés dans l'intégration, en POST, après chaque changement enregistré.

Événements​

product.updated : un article a changé (stock, prix, état).

{ "event": "product.updated", "action": "upsert", "sku": "ACC-POIG-BL", "occurredAt": "2026-09-24T18:41:07Z" }
  • action: "upsert" : relisez l'article avec GET /api/ecommerce/catalog/{sku} et appliquez-le.
  • action: "unpublish" : retirez l'article de la vente (désactivé, épuisé ou absent de l'entrepôt).

order.status : une commande web a changé de statut.

{ "event": "order.status", "reference": "WEB-1000231", "status": "Delivered", "paymentStatus": "PAID", "occurredAt": "2026-09-25T10:02:13Z" }
statusSignification
ProcessingEn cours de préparation (statut à l'enregistrement)
Delivered, CompletedLivrée, terminée
CanceledAnnulée
Return_Pending, Returned, Partial_ReturnRetour en cours, retournée, partiellement retournée

paymentStatus vaut UNPAID, PARTIALLY_PAID ou PAID.

Vérifier la signature​

Chaque webhook porte deux en-têtes :

  • X-Timestamp : l'heure d'envoi, en secondes depuis le 1er janvier 1970 ;
  • X-Signature : HMAC-SHA256(webhookSecret, X-Timestamp + "." + corps), en hexadécimal minuscule.

Recalculez la signature sur le corps brut reçu, comparez-la en temps constant, et refusez un horodatage trop ancien (par exemple plus de cinq minutes).

$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $ts . '.' . $body, $webhookSecret);
if (!hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
http_response_code(401);
exit;
}
const crypto = require('crypto');
function isValid(rawBody, ts, sig, secret) {
const expected = crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
return sig.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
&& Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
}

Réponse et nouvelles tentatives​

Répondez 2xx rapidement, puis traitez le webhook. En cas d'échec ou de non-réponse, Nadigit IMS réessaie plusieurs fois en espaçant les tentatives. Chaque tentative est tracée côté Nadigit IMS. Traitez les webhooks de façon idempotente : le même événement peut arriver deux fois.

Codes d'erreur​

CodeCause
400Requête invalide (champ manquant ou mal formé) ; le corps détaille les champs
401Jeton absent, expiré ou invalide : renouvelez le jeton
403Accès refusé, ou fonction non incluse dans la formule de l'installation
404SKU ou commande inconnus dans l'entrepôt lié
409Stock insuffisant ou réservations désactivées (voir Réservations)
503Installation sans licence active

Les erreurs autres que 409 renvoient un corps de la forme :

{ "timestamp": "…", "status": 403, "error": "Forbidden", "message": "…", "path": "/api/ecommerce/catalog", "errorCode": "…" }

Voir aussi​