Sujet du TP R5.MTD.14 · Interopérabilité
Instructions à destination des étudiants. Le détail des appels est dans la documentation.
Télécharger la version hors ligne (sujet + documentation) À enregistrer avant la séance : elle sert de plan de secours si la connexion est coupée.
Contexte
Cacaomatic est une entreprise fictive qui fabrique du chocolat. Deux systèmes doivent travailler ensemble sans se connaître :
- la boutique en ligne, qui reçoit les commandes des clients, dans son format (
sku, cartons ou pièces, datesjj/mm/aaaa) ; - l'ERP de l'usine, qui gère commandes, stocks, réservations et fabrication, dans son format (codes article, unités, dates
aaaa-mm-jj).
Votre équipe construit, dans n8n, les workflows qui font dialoguer les deux : lire les commandes de la boutique, les traduire,
les passer à l'ERP, puis renvoyer le résultat à la boutique. Les deux systèmes sont des API (https://cacaomatic.alt4b.fr/api).
Chaque équipe (A à H) dispose de sa clé d'API et de ses propres données : vous ne pouvez pas perturber les autres équipes.
1. Se connecter Ă n8n
- Adresse : https://n8n-tp.alt4b.fr
- Identifiant : l'adresse e-mail reçue par invitation (ou communiquée par l'enseignant) ; mot de passe : celui défini à l'activation du compte.
- Chaque groupe a son propre compte : vous ne voyez que vos workflows et vos credentials.
2. Créer le credential de l'API Cacaomatic (une seule fois)
- Vérifiez d'abord que l'API répond :
/api/ping(sans clé). - Menu de gauche → Credentials → Create credential → cherchez Header Auth.
- Name :
Authorization; Value :Bearer <votre clé d'équipe>(avec l'espace aprèsBearer). - Save, puis nommez-le par exemple « Cacaomatic équipe X ».
- Dans un nœud HTTP Request : Authentication « Generic Credential Type » → Header Auth → ce credential. Adresse de base :
https://cacaomatic.alt4b.fr/api.
Le mĂŞme credential sert pour la boutique et pour l'ERP.
3. Premier workflow : lire la boutique et un stock
- Workflows → Create workflow, nommez-le « Test équipe X ».
- Add first step → Trigger manually.
- Cliquez sur le + → HTTP Request : méthode
GET, URLhttps://cacaomatic.alt4b.fr/api/boutique/commandes, credential de l'étape 2. Execute step : vous voyez les commandes de la boutique. - Ajoutez un second HTTP Request :
GET https://cacaomatic.alt4b.fr/api/stocks/TAB-001. Vous obtenezstock_unites,reserveetdisponible. - Un code article = un type de produit (
TABtablette,BARbarre,BTEboîte,PRApraliné,SACsachet,POUpoudre,PATpâte à tartiner,CALcalendrier) et un numéro. La liste complète est dans l'onglet Stocks. - Vérifiez vos appels dans l'onglet Journal de votre espace équipe, et les commandes dans l'onglet Boutique.
4. Le format de la boutique
La boutique publie ses commandes au fil du temps : relancez la lecture régulièrement (a_venir dit combien restent à venir). Une commande ressemble à :
{
"id": 1,
"id_commande_web": "WEB-2026-0001",
"passee_le": "24/10/2026 09:12",
"client": {"nom": "Épicerie Fictive du Port", "email": "achats@epicerie-port.example"},
"livraison_souhaitee": "15/12/2026",
"articles": [
{"sku": "CHOC-LAIT-100", "designation": "Tablette Lait Onctueux", "quantite": 2, "conditionnement": "carton"},
{"sku": "BARRE-CEREALES-40", "designation": "Barre Croquante aux Céréales", "quantite": 10, "conditionnement": "piece"}
],
"statut": "nouvelle"
}
Pour la passer Ă l'ERP, il faut traduire : le sku en code_article (table ci-dessous), piece en unite, la date en aaaa-mm-jj,
id_commande_web en reference_client, client.nom en client.
Table de correspondance sku → code article
| sku (boutique) | Désignation | code_article (ERP) |
|---|---|---|
CHOC-NOIR-70-100 | Tablette Noir Intense 70 % | TAB-001 |
CHOC-LAIT-100 | Tablette Lait Onctueux | TAB-002 |
CHOC-BLANC-100 | Tablette Blanc Vanille | TAB-003 |
CHOC-NOISETTE-100 | Tablette Lait Noisettes Entières | TAB-004 |
BARRE-CARAMEL-45 | Barre Caramel Fondant | BAR-001 |
BARRE-CEREALES-40 | Barre Croquante aux Céréales | BAR-002 |
COFFRET-TRUFFES-250 | Coffret de Truffes Assorties | BTE-001 |
COFFRET-PRALINES-500 | Grand Coffret de Pralinés | PRA-001 |
PEPITES-NOIR-200 | Pépites de Chocolat Noir | SAC-001 |
CACAO-POUDRE-250 | Cacao en Poudre | POU-001 |
PATE-TARTINER-350 | Pâte à Tartiner Chocolat-Noisette | PAT-001 |
ROCHERS-PRALINES-1KG | Rochers Pralinés (vrac 1 kg) | PRA-002 |
CALENDRIER-AVENT | Calendrier de l'Avent | CAL-001 |
OEUFS-FOURRES-200 | Oeufs Fourrés Assortis | SAC-002 |
COUVERTURE-NOIR-1KG-PRO | Chocolat de Couverture Noir 1 kg (pro) | SAC-003 |
Même table en JSON (à coller dans un nœud « Code » ou « Edit Fields »)
{
"CHOC-NOIR-70-100": "TAB-001",
"CHOC-LAIT-100": "TAB-002",
"CHOC-BLANC-100": "TAB-003",
"CHOC-NOISETTE-100": "TAB-004",
"BARRE-CARAMEL-45": "BAR-001",
"BARRE-CEREALES-40": "BAR-002",
"COFFRET-TRUFFES-250": "BTE-001",
"COFFRET-PRALINES-500": "PRA-001",
"PEPITES-NOIR-200": "SAC-001",
"CACAO-POUDRE-250": "POU-001",
"PATE-TARTINER-350": "PAT-001",
"ROCHERS-PRALINES-1KG": "PRA-002",
"CALENDRIER-AVENT": "CAL-001",
"OEUFS-FOURRES-200": "SAC-002",
"COUVERTURE-NOIR-1KG-PRO": "SAC-003"
}
Un sku absent de cette table est une anomalie Ă signaler, pas Ă deviner.
Phase 0 · Concevoir avant de construire
Avant d'ouvrir n8n, on raisonne sur le papier (ou dans un document) : quels appels, dans quel ordre, avec quelles données, et que faire quand ça se passe mal ? Cette phase ne demande ni n8n ni l'API : elle se fait sans connexion avec ce sujet et la documentation. Elle sert aussi de plan de secours : si les outils sont indisponibles pendant la séance, c'est le TP du jour, et ce que vous concevez ici se réalise ensuite dans n8n.
Les données de départ
Extrait du catalogue de l'ERP (stock initial et unités par carton). Chaque équipe démarre avec les mêmes stocks.
| code_article | Libellé | Stock initial (unités) | Unités par carton |
|---|---|---|---|
TAB-001 | Tablette chocolat noir 70 % 100 g | 400 | 20 |
TAB-002 | Tablette chocolat au lait 100 g | 500 | 20 |
TAB-003 | Tablette chocolat blanc 100 g | 180 | 20 |
TAB-004 | Tablette chocolat noisettes 100 g | 60 | 20 |
BAR-001 | Barre chocolatée caramel 45 g | 300 | 36 |
BAR-002 | Barre croquante céréales 40 g | 720 | 36 |
BTE-001 | Boîte de truffes assorties 250 g | 96 | 12 |
PRA-001 | Boîte de pralinés 500 g | 48 | 8 |
SAC-001 | Sachet de pépites de chocolat noir 200 g | 240 | 24 |
POU-001 | Cacao en poudre 250 g | 150 | 12 |
PAT-001 | Pâte à tartiner chocolat-noisette 350 g | 120 | 6 |
PRA-002 | Rochers pralinés en vrac 1 kg | 35 | 10 |
CAL-001 | Calendrier de l'Avent chocolaté | 0 | 6 |
SAC-002 | Oeufs fourrés assortis 200 g | 90 | 15 |
SAC-003 | Chocolat de couverture noir 1 kg (pro) | 25 | 10 |
Les 8 commandes que la boutique publie, dans l'ordre d'arrivée (à traiter dans cet ordre, les stocks se consomment au fur et à mesure) :
| Commande | Client | Livraison | Articles (sku × quantité) |
|---|---|---|---|
WEB-2026-0001 | Épicerie Fictive du Port | 15/12/2026 | CHOC-LAIT-100 × 2 cartonsBARRE-CEREALES-40 × 10 pièces |
WEB-2026-0002 | Biscuiterie Imaginaire | 20/12/2026 | CHOC-NOIR-70-100 Ă— 5 cartons |
WEB-2026-0003 | Café du Marché | 10/12/2026 | BARRE-CARAMEL-45 × 300 pièces |
WEB-2026-0004 | Boutique Les Délices Fictifs | 18/12/2026 | CHOC-NOISETTE-100 × 61 pièces |
WEB-2026-0005 | HĂ´tel Fictif des Alpes | 22/12/2026 | CALENDRIER-AVENT Ă— 6 cartonsCHOC-BLANC-100 Ă— 1 carton |
WEB-2026-0006 | Épicerie Fictive du Port | 19/12/2026 | SAISON-NOEL-2025 × 1 pièce |
WEB-2026-0002 | Biscuiterie Imaginaire | 20/12/2026 | CHOC-NOIR-70-100 Ă— 5 cartons |
WEB-2026-0008 | Traiteur Fictif Chocolat Pro | 23/12/2026 | COFFRET-PRALINES-500 × 4 cartonsCACAO-POUDRE-250 × 2 cartonsPEPITES-NOIR-200 × 30 pièces |
Les mĂŞmes commandes en JSON (format de la boutique)
[
{
"id_commande_web": "WEB-2026-0001",
"client": {
"nom": "Épicerie Fictive du Port",
"email": "achats@epicerie-port.example"
},
"livraison_souhaitee": "15/12/2026",
"articles": [
{
"sku": "CHOC-LAIT-100",
"quantite": 2,
"conditionnement": "carton"
},
{
"sku": "BARRE-CEREALES-40",
"quantite": 10,
"conditionnement": "piece"
}
]
},
{
"id_commande_web": "WEB-2026-0002",
"client": {
"nom": "Biscuiterie Imaginaire",
"email": "commandes@biscuiterie.example"
},
"livraison_souhaitee": "20/12/2026",
"articles": [
{
"sku": "CHOC-NOIR-70-100",
"quantite": 5,
"conditionnement": "carton"
}
]
},
{
"id_commande_web": "WEB-2026-0003",
"client": {
"nom": "Café du Marché",
"email": "cafe@marche.example"
},
"livraison_souhaitee": "10/12/2026",
"articles": [
{
"sku": "BARRE-CARAMEL-45",
"quantite": 300,
"conditionnement": "piece"
}
]
},
{
"id_commande_web": "WEB-2026-0004",
"client": {
"nom": "Boutique Les Délices Fictifs",
"email": "contact@delices.example"
},
"livraison_souhaitee": "18/12/2026",
"articles": [
{
"sku": "CHOC-NOISETTE-100",
"quantite": 61,
"conditionnement": "piece"
}
]
},
{
"id_commande_web": "WEB-2026-0005",
"client": {
"nom": "HĂ´tel Fictif des Alpes",
"email": "direction@hotel-alpes.example"
},
"livraison_souhaitee": "22/12/2026",
"articles": [
{
"sku": "CALENDRIER-AVENT",
"quantite": 6,
"conditionnement": "carton"
},
{
"sku": "CHOC-BLANC-100",
"quantite": 1,
"conditionnement": "carton"
}
]
},
{
"id_commande_web": "WEB-2026-0006",
"client": {
"nom": "Épicerie Fictive du Port",
"email": "achats@epicerie-port.example"
},
"livraison_souhaitee": "19/12/2026",
"articles": [
{
"sku": "SAISON-NOEL-2025",
"quantite": 1,
"conditionnement": "piece"
}
]
},
{
"id_commande_web": "WEB-2026-0002",
"client": {
"nom": "Biscuiterie Imaginaire",
"email": "commandes@biscuiterie.example"
},
"livraison_souhaitee": "20/12/2026",
"articles": [
{
"sku": "CHOC-NOIR-70-100",
"quantite": 5,
"conditionnement": "carton"
}
]
},
{
"id_commande_web": "WEB-2026-0008",
"client": {
"nom": "Traiteur Fictif Chocolat Pro",
"email": "cuisine@traiteur.example"
},
"livraison_souhaitee": "23/12/2026",
"articles": [
{
"sku": "COFFRET-PRALINES-500",
"quantite": 4,
"conditionnement": "carton"
},
{
"sku": "CACAO-POUDRE-250",
"quantite": 2,
"conditionnement": "carton"
},
{
"sku": "PEPITES-NOIR-200",
"quantite": 30,
"conditionnement": "piece"
}
]
}
]
Exemples de réponses de l'API
Réponses réelles, à connaître pour concevoir les tests de votre workflow. Toutes les erreurs ont le même format {"erreur", "message", "details"}.
201 · POST /api/commandes (cartons déjà convertis en unités par l'ERP)
{"id": 21, "reference_client": "WEB-2026-0002", "client": "Biscuiterie Imaginaire",
"date_livraison_souhaitee": "2026-12-20", "statut": "recue",
"lignes": [{"code_article": "TAB-001", "quantite": 5, "unite": "carton", "quantite_unites": 100}]}
201 · POST /api/reservations
{"id": 13, "reference_commande": "WEB-2026-0002", "lignes": [{"code_article": "TAB-001", "quantite": 100}]}
409 · POST /api/reservations : stock insuffisant (rien n'est réservé)
{"erreur": "stock_insuffisant", "message": "Stock insuffisant : aucune réservation n'a été enregistrée.",
"details": {"lignes": [{"code_article": "TAB-004", "demande": 61, "disponible": 60, "suffisant": false}]}}
409 · POST /api/commandes : référence déjà utilisée
{"erreur": "commande_existante", "message": "Une commande avec la référence client « WEB-2026-0002 » existe déjà .",
"details": {"reference_client": "WEB-2026-0002"}}
422 · données invalides
{"erreur": "validation_echouee", "message": "Les données envoyées sont invalides.",
"details": {"champs": {"lignes.0.unite": ["La valeur du champ lignes.0.unite est invalide (valeurs acceptées : unite, carton)."]}}}
503 · panne simulée (en-tête Retry-After: 30)
{"erreur": "service_indisponible", "message": "Panne simulée : le service est indisponible pendant encore 30 seconde(s).",
"details": {"secondes_restantes": 30}}
201 · POST /api/ordres-fabrication et POST /api/boutique/commandes/{id}/statut (200)
{"id": 7, "code_article": "TAB-004", "quantite": 1, "reference_commande": "WEB-2026-0004", "statut": "planifie"}
Exercices (à rendre, par équipe)
- Traduire. Écrivez le corps JSON du
POST /api/commandescorrespondant à la commandeWEB-2026-0001(sku, conditionnement, date, noms de champs). Quelles transformations avez-vous dû faire ? - Prévoir. Complétez ce tableau pour les 8 commandes, traitées dans l'ordre : appels à faire (dans l'ordre), réponse attendue de chacun, quantités réservées en unités, et statut renvoyé à la boutique.
Indiquez le stock disponible de chaque article touché après chaque commande.
Commande Appels dans l'ordre Réponses attendues Stock après Statut renvoyé WEB-2026-0001WEB-2026-0002WEB-2026-0003WEB-2026-0004WEB-2026-0005WEB-2026-0006WEB-2026-0002WEB-2026-0008 - Dessiner. Représentez votre workflow : la liste des nœuds n8n (déclencheur, HTTP Request, Split Out, Code, IF…), leur ordre, et pour chaque appel de l'ERP ce que vous faites des réponses 201, 409, 422 et 503. Où renvoyez-vous le statut à la boutique ?
- Diagnostiquer. Pour chaque situation, donnez la cause probable et la correction :
- un appel répond
401 non_authentifiealors que la clé semble correcte ; - la création d'une commande répond
422aveclignes.0.uniteinvalide pour une ligne « piece » de la boutique ; - la commande
WEB-2026-0002répond409 commande_existanteau deuxième passage de votre workflow : est-ce un bug ? que faire ? - tous les appels de l'ERP répondent
503avecRetry-After: 30alors que la boutique répond normalement.
- un appel répond
- Réfléchir. L'ERP tombe en panne entre la création de la commande et sa réservation. Que se passe-t-il au passage suivant de votre workflow ? Comment éviter de perdre ou de dupliquer une commande ?
Pourquoi ne faut-il surtout pas envoyer « 5 » (cartons) dans la réservation de la commande
WEB-2026-0002?
6. Travail demandé
Un workflow (ou plusieurs) qui traite toutes les commandes de la boutique. Les 8 commandes ne se ressemblent pas : chacune cache un cas à gérer.
a. Récupérer les commandes à traiter
- Lisez
GET /api/boutique/commandes?statut=nouvelle. Une commande déjà traitée n'y figure plus. - Les commandes arrivent progressivement : faites tourner le workflow à intervalle régulier (Schedule Trigger) ou relancez-le.
b. Traduire et enregistrer dans l'ERP
- Convertissez le format (voir plus haut) puis envoyez la commande avec
POST /api/commandes. Les quantités encartonsont converties par l'ERP. - Une même
reference_clientne peut être utilisée qu'une fois : la boutique peut renvoyer une commande. Traitez le 409 sans réserver deux fois. - Un 422 signale des données invalides : lisez
details.
c. Contrôler le stock et réserver
- La réservation se fait en unités :
POST /api/reservations. Elle est « tout ou rien » : un 409stock_insuffisantdétaille les lignes en cause. - Une quantité exactement égale au disponible est acceptée ; une unité de plus est refusée.
d. Fabriquer ou prévenir
- Stock insuffisant : créez un ordre avec
POST /api/ordres-fabricationpour la quantité manquante. - Informez le bon service avec
POST /api/notifications(adv,productionouclient) : refus, rupture, anomalie.
e. Renvoyer le résultat à la boutique
POST /api/boutique/commandes/{id}/statutavecacceptee,refuseeouen_attente_fabrication(et unmotifpour un refus).- Le tableau de l'onglet Boutique de votre espace équipe doit refléter ces statuts.
f. Rendre le workflow robuste
- Une panne de l'ERP peut être déclenchée sur votre équipe (par vous avec
POST /api/panne, ou par l'enseignant) : l'ERP répond 503 avecRetry-After. La boutique, elle, continue de répondre. Configurez les nouvelles tentatives (Retry On Fail) et une branche d'erreur : aucune commande ne doit être perdue. - La limite est de 120 requêtes par minute : au-delà , 429. Évitez les boucles qui martèlent l'API.
- Un 401 signale une clé absente ou erronée.
7. Outils pour vous aider
- Journal (espace équipe) : tous vos appels avec requête et réponse, pour comprendre ce qui est réellement parti.
- Essayer un appel (espace équipe) : tester un appel sans n8n.
- Boutique, Stocks, Commandes, Réservations, Ordres, Notifications : l'état de vos données après chaque test.
- Les données se remettent à zéro à la demande de l'enseignant (la boutique recommence alors ses publications).
8. À rendre
- Le document de la phase 0 (réponses aux 5 exercices).
- L'export JSON de vos workflows n8n.
- Une capture de l'onglet Boutique avec les statuts des 8 commandes, et un extrait du journal montrant un 409 et une panne (503) gérés.
- Un court compte rendu : choix faits (traduction du format, conversion des cartons, gestion des erreurs) et difficultés rencontrées.
Les modalités exactes (date, format, barème) sont précisées par l'enseignant.
9. Règles à respecter
- Ne saisissez aucune donnée personnelle ni aucun mot de passe réel dans vos workflows : tout est fictif ici.
- Ne partagez pas votre clé d'équipe ; chaque équipe n'utilise que la sienne.
- Une exécution est coupée après 5 minutes. Évitez les boucles infinies.
- Certains nodes sont désactivés (commandes système, fichiers, nodes communautaires, API publique). C'est voulu.
10. En cas de problème
| SymptĂ´me | Que faire |
|---|---|
401 non_authentifie | Vérifiez le credential : nom Authorization, valeur Bearer suivi de la clé, sans espace en trop. |
| « Connection refused » ou délai dépassé | Vérifiez l'URL (https://cacaomatic.alt4b.fr/api/…), puis testez /api/ping dans le navigateur. |
| La liste de la boutique est incomplète | Normal : la boutique publie ses commandes au fil du temps (a_venir). Relancez plus tard ou demandez à l'enseignant de tout libérer. |
| 422 | Le corps JSON est incomplet ou mal typé : lisez details dans la réponse. |
| 503 | Panne simulée de l'ERP sur votre équipe : attendez la durée de Retry-After (visible dans l'espace équipe) ou gérez-la dans le workflow. |
| 429 | Plus de 120 requêtes par minute : attendez une minute et vérifiez qu'une boucle ne tourne pas. |
| Workflow coupé | Il a dépassé 5 minutes : simplifiez-le. |
| Autre erreur | Faites une capture d'écran du message (et du Journal) et appelez l'enseignant. |
Bonus · Ajouter une IA locale
Facultatif, une fois le travail principal terminé : faites classer ou résumer par un modèle local les messages que vos workflows envoient.
Credential Ollama (une seule fois)
- Credentials → Create credential → cherchez Ollama.
- Base URL :
http://ollama:11434(sans espace ni « / » final). - Save : le message « Connection tested successfully » doit s'afficher. Nommez-le par exemple « Ollama équipe X ».
Un assistant qui répond
- Nouveau workflow → On chat message → + → Basic LLM Chain.
- Sous la chaîne, + de Model → Ollama Chat Model : credential ci-dessus, Model =
gemma4:e4b-it-q4_K_M. - Open chat, écrivez un message et vérifiez la réponse.
Exemple de consigne : classer une notification
Classe ce message dans une seule rubrique parmi : adv, production, client.
Réponds uniquement par le nom de la rubrique.
Message : {{ $json.chatInput }}
Idée : utilisez la rubrique renvoyée comme destinataire de POST /api/notifications.
Utilisez uniquement le modèle gemma4:e4b-it-q4_K_M. Tous les groupes le partagent : si la réponse est lente, patientez avant de relancer.
Symptômes : « Connection refused » → vérifiez l'URL ; modèle absent de la liste → sauvegardez le credential, rouvrez le node et rechargez la page.