# Webhooks des routines

> Lancer une routine depuis Zapier, Make, n8n ou votre code par une requête signée : adresse, en-têtes, signature HMAC, exemples, réponses et erreurs.

Un webhook lance une routine quand un autre service (Zapier, Make, n8n, un script, votre propre serveur) envoie une requête signée à son adresse. Le corps JSON de la requête est transmis à la routine avec son prompt, comme une donnée. La requête répond tout de suite ; l’exécution se fait ensuite, et son résultat arrive dans la conversation de la routine.

## Créer un déclencheur

1. Ouvrez la routine dans « Routines », puis l’onglet « Webhooks ».
2. Cliquez sur « Créer un déclencheur webhook ». Le « Nom » est facultatif : il sert à distinguer vos déclencheurs, par exemple « Zapier nouveaux prospects ».
3. Copiez l’« URL du webhook » et la « Clé de signature ».
4. Cliquez sur « J’ai enregistré la clé ».

> [!WARNING]
> **La clé ne s’affiche qu’une fois**
>
> Moon AI ne garde pas la clé de signature lisible : elle ne sera plus affichée. Si vous la perdez, utilisez « Renouveler la clé de signature ». L’ancienne clé cesse alors de fonctionner immédiatement.

« Voir un exemple d’appel » affiche une commande prête à copier avec votre adresse et votre clé.

Chaque routine peut avoir jusqu’à 5 déclencheurs. L’onglet « Webhooks » indique combien d’appels chaque déclencheur accepte par minute et par jour : le nombre par jour dépend du forfait du workspace (voir les [formules](https://realmoon.ai/tarifs/)).

## Référence du point d’accès

### `POST /api/v1/routines/hooks/{identifiant}`

Lance une exécution de la routine liée au déclencheur.

| Élément | Valeur |
| --- | --- |
| Adresse complète | `https://chat.realmoon.ai/api/v1/routines/hooks/<identifiant>`, donnée par l’onglet « Webhooks ». Elle ne contient aucun secret. |
| Authentification | La signature HMAC de la requête. Aucun jeton de session ni aucune clé d’API n’est utilisé. |
| Portée | Une seule routine : celle du déclencheur. Le propriétaire de la routine doit être membre actif de son workspace, et le forfait du workspace doit inclure les routines. |
| Corps | Du JSON, 64 Ko au plus. Un corps vide vaut `{}`. |

#### Paramètres

| Nom | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `identifiant` | Chemin | Chaîne | Oui | L’identifiant public du déclencheur, de 16 à 64 caractères (lettres, chiffres, `_` et `-`). |
| `Content-Type` | En-tête | Chaîne | Oui | `application/json`, ou un type `application/…+json`. |
| `X-Moon-Timestamp` | En-tête | Chaîne | Oui | L’heure de l’appel en secondes Unix, en chiffres seulement. Elle doit être à moins de 5 minutes de l’heure du serveur, dans un sens ou dans l’autre. |
| `X-Moon-Signature` | En-tête | Chaîne | Oui | `v1=` suivi de la signature en hexadécimal minuscule (64 caractères). Plusieurs signatures peuvent être séparées par des virgules. |
| Corps | Corps | Objet JSON | Non | Les données de l’événement, transmises à la routine. |

#### Réponse

Une requête acceptée répond `202` avant que la routine ne s’exécute :

```json title="202 Accepted"
{"run_id": "4b0c1f0e-2a7d-4c41-9e3b-6f1d2c8a5b90", "status": "queued"}
```

| Champ | Type | Description |
| --- | --- | --- |
| `run_id` | Chaîne | L’identifiant de l’exécution, visible dans l’onglet « Historique » de la routine. |
| `status` | Chaîne | Toujours `queued` : l’exécution attend son tour. |

L’exécution apparaît dans l’onglet « Historique » de la routine avec le déclencheur « Webhook ». Gardez l’horloge de la machine qui envoie à l’heure.

## La signature

La signature est un HMAC-SHA256 :

- la clé est la clé de signature, telle qu’affichée (elle commence par `mwk_`) ;
- le message est l’horodatage, un point, puis le corps brut, exactement les octets envoyés ;
- le résultat est écrit en hexadécimal minuscule, 64 caractères.

```text title="Message signé"
<X-Moon-Timestamp>.<corps brut>
```

> [!TIP]
> **Signez les octets que vous envoyez**
>
> Calculez la signature sur le texte exact du corps, puis envoyez ce même texte. Si votre bibliothèque reformate le JSON après coup (espaces, ordre des clés), la signature ne correspond plus et la requête est refusée.

Pour vérifier votre calcul, avec ces valeurs d’exemple :

| Élément | Valeur |
| --- | --- |
| Clé | `mwk_exempleDeCle` |
| `X-Moon-Timestamp` | `1762300800` |
| Corps | `{"event":"new_lead","id":"evt_123"}` |
| Signature attendue | `0d61b9fd29504eb3bd85a2e00361373c8f786822ddb73162bb825ca45abfcb67` |

L’en-tête `X-Moon-Signature` peut contenir jusqu’à 5 signatures séparées par des virgules (`v1=…,v1=…`) : la requête est acceptée si l’une d’elles correspond. Une signature sans le préfixe `v1=` est acceptée aussi.

## Exemples

Remplacez l’adresse et la clé par celles de votre déclencheur.

```bash title="cURL"
KEY='mwk_votre_cle'
URL='https://chat.realmoon.ai/api/v1/routines/hooks/votre_identifiant'
BODY='{"event":"new_lead","id":"evt_123"}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$KEY" -hex | sed 's/^.* //')
curl -sS -X POST "$URL" \
  -H 'Content-Type: application/json' \
  -H "X-Moon-Timestamp: $TS" \
  -H "X-Moon-Signature: v1=$SIG" \
  --data-binary "$BODY"
```

```python title="Python"
import hashlib, hmac, json, time, requests

key = "mwk_votre_cle"
url = "https://chat.realmoon.ai/api/v1/routines/hooks/votre_identifiant"
body = json.dumps({"event": "new_lead", "id": "evt_123"}).encode()
ts = str(int(time.time()))
sig = hmac.new(key.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()

r = requests.post(url, data=body, headers={
    "Content-Type": "application/json",
    "X-Moon-Timestamp": ts,
    "X-Moon-Signature": f"v1={sig}",
})
print(r.status_code, r.json())
```

```javascript title="JavaScript"
import { createHmac } from 'node:crypto';

const key = 'mwk_votre_cle';
const url = 'https://chat.realmoon.ai/api/v1/routines/hooks/votre_identifiant';
const body = JSON.stringify({ event: 'new_lead', id: 'evt_123' });
const ts = Math.floor(Date.now() / 1000).toString();
const sig = createHmac('sha256', key).update(`${ts}.${body}`).digest('hex');

const res = await fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Moon-Timestamp': ts,
    'X-Moon-Signature': `v1=${sig}`
  },
  body
});
console.log(res.status, await res.json());
```

En Python, passez le corps déjà encodé dans `data=` (et non `json=`), pour envoyer les octets signés. L’exemple JavaScript tourne avec Node.js 18 ou plus récent.

Dans Zapier, Make ou n8n, utilisez une étape de code ou de requête HTTP qui calcule la signature sur le corps exact, puis l’envoie avec les deux en-têtes.

## Erreurs

Le corps d’une erreur a la forme `{"detail": …}`. Le détail est soit un texte, soit un objet `{"code": …, "message": …}`.

| Statut | Code ou texte | Cause |
| --- | --- | --- |
| `400` | `stale_timestamp` | `X-Moon-Timestamp` est à plus de 5 minutes de l’heure du serveur. |
| `400` | `invalid_json` | Le corps n’est pas du JSON valide. |
| `403` | `feature_scheduled_routines` | Le forfait du workspace n’inclut pas les routines. |
| `404` | « Introuvable. » | Adresse inconnue, déclencheur désactivé ou supprimé, signature absente ou fausse, horodatage absent ou mal formé, routine en pause ou supprimée, ou propriétaire qui ne peut plus l’exécuter. |
| `409` | `replayed` | Cette requête a déjà été reçue (même signature). |
| `413` | « Corps de requête trop volumineux (64 Ko au plus). » | Le corps dépasse 64 Ko. |
| `415` | « Le corps doit être du JSON (application/json). » | `Content-Type` n’est pas un type JSON. |
| `429` | `rate_limited`, « Limite de ce déclencheur atteinte. » | Le déclencheur a reçu trop d’appels dans la minute ou dans la journée. |
| `429` | `rate_limited`, « Trop de requêtes. » | Trop de requêtes refusées depuis votre adresse (plus de 60 par minute). |
| `429` | `queue_full` | 20 exécutions attendent déjà pour cette routine. |
| `503` | « Service momentanément indisponible. Réessayez dans un instant. » | Panne passagère. |

Exemples de corps :

```json title="404 Not Found"
{"detail": "Introuvable."}
```

```json title="429 Too Many Requests"
{"detail": {"code": "rate_limited", "message": "Limite de ce déclencheur atteinte."}}
```

Le même `404` répond pour toutes les causes listées, pour ne rien révéler de l’existence d’un déclencheur. Vérifiez d’abord l’adresse, la clé et le calcul de la signature.

### Renvoyer une requête

- Une requête refusée par `429`, `403` ou `503` ne compte pas dans les limites du déclencheur. Vous pouvez la renvoyer telle quelle tant que son horodatage a moins de 5 minutes, ou la signer de nouveau avec une heure récente.
- Deux requêtes identiques (même corps, même seconde) ont la même signature : la seconde reçoit `409`. Ajoutez un identifiant d’événement unique au corps, par exemple `"id": "evt_123"`.
- Une requête acceptée n’est jamais exécutée deux fois, même renvoyée.

## Ce que fait la routine

La routine reçoit son prompt, suivi du corps de la requête présenté comme des données envoyées par un service externe. L’IA s’en sert comme matière pour la tâche, sans suivre les instructions qu’il pourrait contenir. Le corps passe par [Moon Blur](https://realmoon.ai/documentation/moon-blur/) comme le reste de la requête.

Une exécution lancée par un webhook :

- n’agit jamais dans vos connecteurs (aucun e-mail envoyé, aucun message publié), même si la routine a l’option « Autoriser les actions » ;
- n’ouvre pas de page web, n’exécute pas de code, ne génère ni image ni vidéo ;
- ne crée pas de lien public vers vos fichiers et n’en joint pas à un message ;
- peut lire vos connecteurs et chercher sur le web ;
- n’est pas relancée automatiquement en cas d’erreur ;
- compte dans votre limite d’utilisation comme une exécution normale.

Le prompt et la réponse sont marqués comme contenant un contenu extérieur : rien de distant ne se charge dans la réponse sans votre clic. Tant que ce message reste dans la conversation, les tours suivants gardent les mêmes précautions : chaque action dans vos outils demande votre validation.

> [!NOTE]
> **Pour agir dans vos outils**
>
> Si un événement doit déclencher un envoi ou une création, laissez la routine préparer le contenu, puis faites l’action vous-même depuis la conversation. Pour réagir à un e-mail reçu ou à un commentaire, préférez un [déclencheur d’agent](https://realmoon.ai/documentation/agents/messageries/#declencheurs) : ses actions attendent votre validation.

## Gérer les déclencheurs

| Action | Effet |
| --- | --- |
| « Activer » suivi du nom (interrupteur) | Désactivé, le déclencheur répond `404`. |
| « Renommer » | Change le nom affiché. |
| « Renouveler la clé de signature » | Donne une nouvelle clé. L’ancienne cesse de fonctionner immédiatement. |
| « Supprimer » | Les requêtes envoyées à son adresse sont refusées. Irréversible. |

Désactiver un déclencheur, renouveler sa clé ou le supprimer annule aussi ses exécutions en file qui n’ont pas encore démarré. La liste montre pour chaque déclencheur les « Appels reçus » et la date du dernier appel. Supprimer la routine supprime ses déclencheurs.

## Voir aussi

- [Routines](https://realmoon.ai/documentation/agents/routines/)
- [Messageries et déclencheurs](https://realmoon.ai/documentation/agents/messageries/)

---

Documentation Moon AI › Agents, routines et connecteurs › Webhooks. Page : https://realmoon.ai/documentation/agents/webhooks/. Modifiée le 5 novembre 2026.

© 2026 Stellarr Studio SAS. Tous droits réservés. Moon AI, Moon Blur et Stellarr Studio sont des marques déposées à l’INPI.
