Branchez votre système aux automatisations WhatsApp
Votre système signale un fait — une commande passée, une livraison expédiée, un ticket résolu. TEERAL le reçoit, choisit le bon scénario et envoie le message WhatsApp au client. Vous poussez ; TEERAL encaisse.
Contrat public et stable : les évolutions se font par ajout, jamais par rupture. L'ingestion est servie par l'application TEERAL, pas par son Directus — ce sont deux hôtes distincts.
01Démarrage rapide
Trois étapes, du premier événement au message reçu.
- Créez une source. Dans votre espace TEERAL, écran Automatisations → Sources d'événements. Notez l'
identifiant de source(src_…) et lesecret— le secret n'est affiché qu'une seule fois. - Signez et postez votre premier événement sur
/api/events. Vous recevez 202 avechandled. - Vérifiez le journal des exécutions dans TEERAL. Tant qu'un envoi réel n'est pas activé, l'exécuteur reste en dry-run — aucun message ne part, vous validez sans risque.
TEERAL ne traduit pas le format de votre outil et n'interroge jamais votre système. Vous décidez quand émettre et vous mappez vos champs vers le corps ci-dessous.
02Endpoint & authentification
Une seule route reçoit tout. L'URL exacte, l'identifiant de source et le secret figurent dans votre espace TEERAL — recopiez-les de là, pas de cette page.
POST /api/events HTTP/1.1
Content-Type: application/json
x-teeral-source: src_b1f84be9c5c07f2300fe34ce18ae3d97
x-teeral-signature: sha256=9f86d081884c7d659a2feaa0c55ad015…Aucun secret ne circule dans l'URL : il ne doit jamais finir dans un journal serveur ou une capture d'écran. Le secret est régénérable à tout moment, source par source, sans toucher à vos autres intégrations.
03Signature HMAC
La signature est un HMAC-SHA256 du corps brut — les octets exactement tels qu'ils partent — avec votre secret comme clé, en hexadécimal minuscule, préfixé de sha256=.
Le moindre réencodage — ordre des clés, espaces — change la signature et vous vaut un 401. Sérialisez une fois, signez cette chaîne, envoyez cette chaîne.
import { createHmac } from "node:crypto";
// sérialisé UNE fois — c'est cette chaîne exacte qui part
const body = JSON.stringify(payload);
const signature = "sha256=" + createHmac("sha256", secret).update(body).digest("hex");
await fetch(`${TEERAL_URL}/api/events`, {
method: "POST",
headers: {
"content-type": "application/json",
"x-teeral-source": sourceKey,
"x-teeral-signature": signature,
},
body, // le MÊME corps
});node:crypto ? (sandbox Directus Flows, edge…)Utilisez l'API Web Crypto (crypto.subtle avec HMAC) ou une implémentation HMAC-SHA256 autonome. Le résultat doit être identique octet pour octet.
04Corps de la requête
{
"version": "1",
"event_id": "evt_2026_07_21_88213",
"type": "order.created",
"object_ref": "CMD-20260721-0042",
"contact_phone": "221771112233",
"contact_name": "Awa Diop",
"occurred_at": "2026-07-21T14:32:00Z",
"data": { "amount_xof": 15000 }
}| Champ | Requis | Description |
|---|---|---|
version | oui | Toujours "1" pour ce contrat. |
event_id | oui | Identifiant du fait. Le point le plus important — voir la section suivante. |
type | oui | Nommage objet.action en minuscules. Liste ouverte. |
object_ref | non | Référence de la chose dans votre système (le numéro de commande). |
contact_phone | oui | Numéro concerné au format international : indicatif pays + numéro, 8 à 15 chiffres. +, préfixe 00, espaces et tirets tolérés. Un format national (0 initial, sans indicatif) est refusé. |
contact_name | non | Nom affiché. Crée la fiche contact si absente. |
occurred_at | non | Date ISO 8601 du fait. À défaut, TEERAL prend la date de réception et le signale. |
data | non | Objet libre. Les scénarios y puisent les variables du message. |
05event_id vs object_ref
C'est l'erreur qui coûte le plus cher, et elle est silencieuse. Prenez une minute ici.
| Champ | Désigne | Exemple |
|---|---|---|
object_ref | la chose | la commande 123 |
event_id | le fait | « la commande 123 est passée en expédiée » |
Une même commande produit plusieurs événements au cours de sa vie : ils partagent le même object_ref et ont chacun un event_id distinct.
event_id = notification jamais reçue.Si vous réemployez un event_id pour tous les événements d'une commande, TEERAL prend les suivants pour des doublons et les ignore. Votre client ne reçoit jamais sa notification de livraison, et aucune erreur n'est levée.
event_id doit aussi rester stable entre deux tentatives d'envoi du même fait. C'est ce qui rend un rejeu sûr : si votre requête échoue en réseau et que vous la rejouez, le même event_id garantit qu'aucun message en double ne part chez votre client.
L'identifiant de la ligne d'événement dans votre propre base, ou <référence objet>:<transition>:<horodatage du fait>.
06Types d'événements
Un type inconnu de TEERAL est accepté et journalisé sans rien déclencher. Vous pouvez donc émettre plus large que ce que TEERAL consomme aujourd'hui, sans rien changer quand un nouveau scénario sortira.
| Type | Effet |
|---|---|
order.created | Crée la commande. Déclenche la confirmation de commande si vous avez activé ce scénario dans votre espace. |
order.status_changed | Signale un changement de statut. Statut visé dans data.status : chaîne libre, votre vocabulaire tel quel — le déclenchement se configure dans l'automatisation. |
ticket.resolved | Déclenche le suivi de ticket support. |
cart.abandoned | Enregistre un panier abandonné. |
cart.converted | Marque le panier converti. |
Statuts de commande : votre vocabulaire
data.status accepte n'importe quelle chaîne non vide : confirmed, preparing, livré… TEERAL ne traduit rien et n'impose aucune liste. C'est dans l'automatisation, côté espace TEERAL, que se déclarent les statuts qui déclenchent un message — match exact, insensible à la casse, espaces ignorés. Un statut qui ne matche aucune automatisation active est journalisé et répond 202 avec handled: false : aucun message ne part.
{
"version": "1",
"event_id": "CMD-0042:confirmed:2026-07-24T10:05:00Z",
"type": "order.status_changed",
"object_ref": "CMD-0042",
"contact_phone": "221771112233",
"data": { "status": "confirmed" }
}
// Une automatisation configurée sur le statut "confirmed" envoie
// son template ; un statut sans automatisation → 202, handled: false.Pour le suivi interne de la commande (fiche contact, historique), TEERAL reconnaît en plus le cycle created → prepared → shipped → in_transit → delivered, linéaire et sans retour. Un statut hors de ce cycle est conservé au journal sans faire avancer la fiche — cela n'empêche aucun envoi.
amount_xof en francs CFA, entier. Le XOF n'a pas de décimales : une valeur à virgule est refusée plutôt qu'arrondie en silence.
07Codes de réponse
| Code | Signification | Que faire |
|---|---|---|
| 202 | Accepté. Le corps renvoie l'identifiant TEERAL et handled (une automatisation s'en occupe, ou non). | Rien. |
| 400 | Corps mal formé. data.code précise lequel. | Corriger l'émission. Rien n'a été enregistré. |
| 401 | Source inconnue ou signature invalide. | Vérifier l'identifiant de source et le calcul de signature. |
| 403 | Source désactivée. | La réactiver dans l'espace TEERAL. |
| 409 | Événement déjà reçu (même event_id). | Aucune action. Comportement normal d'un rejeu : votre client n'a pas été servi deux fois. |
| 413 | Corps trop volumineux. | Alléger le payload. |
Codes de refus en 400
version_unsupported event_id_missing type_invalid contact_phone_missing contact_phone_invalid occurred_at_invalid data_not_object invalid_json
08Garanties & limites
Ce que TEERAL garantit
- Réponse immédiate. L'ingestion authentifie, valide, enregistre, répond. Aucun appel à WhatsApp pendant votre requête : votre système n'attend jamais Meta.
- Rejeu sans danger. Le même
event_idne produit ni second événement ni second message. - Isolation. Le tenant est déduit de votre source authentifiée, jamais d'un champ du corps.
Ce que TEERAL ne fait pas
- Aucun retour de statut vers votre système : TEERAL ne vous notifie pas de la délivrance du message.
- Aucune traduction depuis le format de votre outil : l'adaptateur vers ce contrat vous appartient.
- Un événement sans numéro exploitable est refusé. Un fait qui ne désigne personne de joignable ne peut rien déclencher.
09Tester l'intégration
Validez en deux temps, sans jamais risquer un envoi accidentel au client.
- Dry-run d'abord. Tant que l'envoi réel n'est pas activé côté TEERAL, l'exécuteur journalise sans envoyer. Émettez, vérifiez 202 +
handled: true, et lisez le journal : un run dry-run y apparaît. - Puis réel. Une fois l'envoi activé, réémettez avec un
event_iddifférent (sinon rejeu neutre) vers un destinataire opt-in. Un humain confirme la réception.
Le template du scénario doit être approuvé par Meta, et le destinataire opt-in. Rien qui puisse dégrader la qualité du numéro ne doit sortir.