Webhooks Aillo
Aillo transmet les demandes de cueillette de vos succursales à votre système en JSON signé. Configurez l’adresse dans API et webhooks.
Événements
message.created— Un appelant a laissé un message (par exemple : nom, numéro de commande, place de stationnement), ou toutes les lignes étaient occupées.message.claimed— Une personne de votre équipe a appuyé sur « Je m’en occupe »; claimed_by indique qui.message.handled— Votre équipe a fermé la demande : outcome vaut « served » (« Servi ✓ ») ou « left » (« Client parti »).ping— Un événement d’essai envoyé depuis votre espace.
Champs de l’appel-cueillette
Sur une ligne d’appel-cueillette, data.details contient les champs séparés recueillis par l’assistante; votre système n’a jamais à lire le texte :
type— toujours « pickup »order_number— le numéro de commande, tel que confirmé par l’appelantparking_spot— le numéro de la place, ou l’endroit où est la voiturecustomer_name— le nom donné par l’appelantvehicle— n’est plus demandé ; toujours vide (gardé par compatibilité)phone— le numéro de l’appelant s’il était affiché, sinon vide
Pour les autres messages, details vaut null. claimed_by, claimed_at et outcome sont null tant que personne n’a pris ou fermé la demande.
La requête
Aillo envoie un POST HTTPS avec un corps JSON à votre adresse. Répondez avec un statut 2xx en moins de 10 secondes; le contenu de votre réponse est ignoré. En-têtes :
Aillo-Event— le type d’événementAillo-Delivery— un identifiant unique de cet envoi, pour ignorer les doublonsAillo-Signature— t=<secondes unix>,v1=<signature>
Exemple de corps
{
"id": "5b0d7c1e-9f4a-4a53-9a7e-2f1c8f0e6b11",
"type": "message.created",
"created_at": "2026-10-09T14:05:12.481Z",
"business": { "id": "8f3e…", "name": "Magasin 214 – Laval" },
"data": {
"message_id": "c41a…",
"body": "Commande 4821 · Place 6 · Julie Tremblay · Honda CR-V grise · +15145550123",
"urgent": true,
"call_id": null,
"created_at": "2026-10-09T14:05:12.402Z",
"handled_at": null,
"details": {
"type": "pickup",
"order_number": "4821",
"parking_spot": "6",
"customer_name": "Julie Tremblay",
"vehicle": "",
"phone": "+15145550123"
},
"claimed_by": null,
"claimed_at": null,
"outcome": null
}
}Vérifier la signature
Calculez un HMAC-SHA256 de l’horodatage, d’un point et du corps brut, avec votre secret de signature (whsec_…), et comparez-le à v1. Refusez les requêtes de plus de 5 minutes.
Node.js
import crypto from "node:crypto";
function verify(rawBody, header, secret) {
const { t, v1 } = Object.fromEntries(header.split(",").map(p => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}Python
import hashlib, hmac, time
def verify(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(secret.encode(), parts["t"].encode() + b"." + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])Nouvelles tentatives
Si votre système ne répond pas 2xx, Aillo réessaie après 30 secondes, 2 minutes, 10 minutes, 30 minutes, 1, 3, 6 et 12 heures, puis s’arrête. Un événement peut arriver plus d’une fois ou dans le désordre : utilisez Aillo-Delivery et created_at.
Sécurité et confidentialité
- Seules les adresses https publiques sont acceptées.
- Les événements contiennent des renseignements personnels de vos appelants : conservez-les selon votre politique de confidentialité. Aillo garde l’historique des envois 30 jours.
- Vous pouvez suspendre les envois ou créer un nouveau secret en tout temps.
Questions : [email protected]