Webhooks
Mooteck expose un point de réception pour recevoir vos événements (nouvelle réservation, mise à jour de stock) depuis votre boutique ou vos outils. Chaque requête doit être signée.
Sens des webhooks
Mooteck reçoit des webhooks ; il n'en émet pas vers votre boutique. La propagation Mooteck → boutique (catalogue, stock, commandes) se fait par des appels REST des connecteurs, pas par des webhooks sortants.Endpoint
POST
/api/web-integrations/webhook?key={uuid}L'URL exacte (avec sa key) et le secret de webhooksont générés à la création de l'intégration dans Mooteck (Web → Connecter un site). Lakey identifie l'intégration ; le secret sert à la signature.
Signature
- En-tête :
x-mooteck-signature. - Algorithme : HMAC-SHA256, encodage hexadécimal.
- Corps signé : le corps brut de la requête (octets exacts, avant tout parsing).
- Format accepté : hex nu, ou préfixé
sha256=<hex>. - Secret : le
webhookSecretde votre intégration.
Vérifier / signer (Node.js)
import crypto from "crypto";
// Côté émetteur : signer le corps AVANT l'envoi
const raw = JSON.stringify(payload); // le corps EXACT que vous enverrez
const signature = crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(raw, "utf8")
.digest("hex");
await fetch(webhookUrl, { // webhookUrl contient déjà ?key=...
method: "POST",
headers: {
"Content-Type": "application/json",
"x-mooteck-signature": "sha256=" + signature,
},
body: raw,
});Comparez en temps constant
Mooteck vérifie la signature avec une comparaison à temps constant. De votre côté, si vous recevez un jour des webhooks, faites de même (crypto.timingSafeEqual) et gardez le secret hors du code client.Pas d'anti-rejeu horodaté
Le point de réception ne vérifie pas d'horodatage : une requête correctement signée est acceptée quel que soit son âge. Traitez vos événements de façon idempotente(déduplication par identifiant métier) pour éviter les doublons en cas de renvoi.Événements
Le corps est { "event": "...", "data": { ... } }.
appointment_created
Requiert syncAppointments. Crée un rendez-vous.
Exemple
{
"event": "appointment_created",
"data": {
"date": "2026-07-20T14:30:00+02:00",
"type": "SERVICE",
"clientName": "Jean Dupont",
"clientPhone": "+32470000000",
"notes": "Vidange"
}
}stock_update
Requiert syncStock. Met à jour la quantité d'un produit par référence (entier ≥ 0).
Exemple
{
"event": "stock_update",
"data": { "reference": "FIL-001", "quantity": 12 }
}Réponse 200
{ "success": true }Erreurs : 401 (key/signature/secret manquants ou invalides),400 (JSON, date ou quantité invalide).