Webhooks
Recevoir des notifications HTTP quand des événements se produisent sur vos automations et pipelines.
Webhooks
Les webhooks vous permettent de recevoir des notifications HTTP en temps réel quand des événements se produisent dans Gurren. Configurez une URL cible et choisissez les événements qui vous intéressent.
Les endpoints webhooks nécessitent un JWT Bearer token (pas une API key). Gérez vos webhooks depuis le dashboard ou via les endpoints ci-dessous.
Créer un webhook
POST /webhooks
curl -X POST https://api.gurren.leandre.io/webhooks \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Notification Slack",
"url": "https://example.com/webhook",
"events": ["automation.completed", "automation.failed"]
}'
Body :
| Paramètre | Type | Requis | Description |
|---|---|---|---|
name | string | oui | Nom du webhook |
url | string | oui | URL cible (HTTPS recommandé) |
events | string[] | oui | Liste des événements souscrits |
Réponse :
{
"_id": "665a...",
"name": "Notification Slack",
"url": "https://example.com/webhook",
"events": ["automation.completed", "automation.failed"],
"isActive": true,
"secret": "whsec_a1b2c3d4e5f6...",
"failureCount": 0,
"lastTriggeredAt": null,
"lastStatus": null,
"createdAt": "2024-06-01T10:00:00.000Z"
}
Important : Le champ
secretn'est retourné qu'à la création. Conservez-le pour vérifier les signatures.
Lister les webhooks
GET /webhooks
curl https://api.gurren.leandre.io/webhooks \
-H "Authorization: Bearer <jwt_token>"
Détail d'un webhook
GET /webhooks/:id
Mettre à jour un webhook
PATCH /webhooks/:id
curl -X PATCH https://api.gurren.leandre.io/webhooks/665a... \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '{
"events": ["automation.completed", "pipeline.completed"],
"isActive": true
}'
Champs modifiables : name, url, events, isActive, secret
Supprimer un webhook
DELETE /webhooks/:id
Tester un webhook
POST /webhooks/:id/test
Envoie un événement de test à l'URL configurée pour vérifier que votre endpoint fonctionne.
curl -X POST https://api.gurren.leandre.io/webhooks/665a.../test \
-H "Authorization: Bearer <jwt_token>"
Payload envoyé à votre URL :
{
"event": "webhook.test",
"timestamp": "2024-06-01T10:00:00.000Z",
"data": {
"message": "This is a test event from Gurren",
"webhookId": "665a..."
}
}
Réponse API :
{
"status": 200
}
Le champ status contient le code HTTP retourné par votre endpoint.
Événements disponibles
| Événement | Description |
|---|---|
automation.completed | Une automation s'est terminée avec succès |
automation.failed | Une automation a échoué |
pipeline.completed | Un pipeline s'est terminé avec succès |
pipeline.failed | Un pipeline a échoué |
execution.started | Une exécution a démarré |
execution.selfheal.started | L'IA commence à réparer une étape cassée |
execution.selfheal.succeeded | Une étape a été réparée (sélecteur relocalisé/agi) |
execution.selfheal.failed | La réparation d'une étape a échoué |
intent.received | Un intent a été accepté (job créé) |
intent.resolved | Une automation existante a matché l'intent |
intent.generation.started | Aucune correspondance → génération lancée |
intent.generation.completed | Nouvelle automation générée (à valider) |
intent.generation.failed | La génération a échoué |
intent.completed | État final de l'intent (outcome: executed/generated) |
intent.failed | L'intent a échoué |
job.enqueued | Un job a été ajouté à la file d'attente |
job.completed | Un job en file d'attente s'est terminé |
job.failed | Un job en file d'attente a échoué |
Format des payloads
Chaque notification webhook est envoyée en POST. Le contenu varie selon l'événement.
automation.completed / automation.failed
{
"event": "automation.completed",
"timestamp": "2024-06-01T10:01:30.000Z",
"data": {
"executionId": "777b2c3d4e5f6a7b8c9d0eee",
"sessionId": "999c3d4e5f6a7b8c9d0e1fff",
"automationId": "665a1b2c3d4e5f6a7b8c9d0e",
"automationName": "Login et extraction",
"status": "completed",
"error": null,
"extractedData": {
"email": "john@example.com",
"prix": "29.99€"
},
"selfHeal": {
"occurred": true,
"count": 1,
"healedActions": [
{ "actionName": "Accepter les cookies", "newSelector": "button.cookie-accept" }
]
}
}
}
Le bloc selfHeal indique si la run s'est auto-réparée et quels sélecteurs
ont été persistés sur l'automation (donc ce qui a changé). Le détail
événement par événement est disponible via les webhooks execution.selfheal.* et
dans selfHealEvents de GET /api/v1/executions/:id.
Payload des
execution.selfheal.*(dansdata) :{ jobId, executionId, automationId, actionName, newSelector?, message }.
Enveloppe uniforme : tous les webhooks (events ET
job.*) ont la même forme{ event, timestamp, data }. Lisez toujours les champs sousdata(ex.data.jobId). Quand un job est à l'origine,data.jobIdest présent dès le premier événement.
| Champ | Type | Description |
|---|---|---|
executionId | string | ID de l'exécution |
sessionId | string | null | ID de la session sauvegardée à la fin du run (état final, ex. connecté). À repasser comme sessionId du run suivant pour chaîner la session. null si aucune session n'a été sauvegardée |
automationId | string | ID de l'automation |
automationName | string | Nom de l'automation |
status | string | completed ou failed |
error | string | null | Message d'erreur (null si succès) |
extractedData | object | Données extraites par les actions extractText |
pipeline.completed / pipeline.failed
{
"event": "pipeline.completed",
"timestamp": "2024-06-01T10:05:00.000Z",
"data": {
"pipelineId": "888a1b2c3d4e5f6a7b8c9d0e",
"pipelineName": "Pipeline inscription",
"status": "completed",
"extractedData": {}
}
}
| Champ | Type | Description |
|---|---|---|
pipelineId | string | ID du pipeline |
pipelineName | string | Nom du pipeline |
status | string | completed, failed, ou partial_failed |
extractedData | object | Données extraites agrégées |
execution.started
{
"event": "execution.started",
"timestamp": "2024-06-01T10:00:01.000Z",
"data": {
"executionId": "777b2c3d4e5f6a7b8c9d0eee",
"automationId": "665a1b2c3d4e5f6a7b8c9d0e",
"status": "running"
}
}
job.enqueued
{
"event": "job.enqueued",
"timestamp": "2024-06-01T10:00:00.000Z",
"data": {
"jobId": "aaa1b2c3d4e5f6a7b8c9d0e1",
"type": "automation",
"targetId": "665a1b2c3d4e5f6a7b8c9d0e",
"status": "pending"
}
}
| Champ | Type | Description |
|---|---|---|
jobId | string | ID du job |
type | string | automation ou pipeline |
targetId | string | ID de l'automation ou du pipeline |
status | string | Toujours pending |
job.completed / job.failed
{
"event": "job.completed",
"timestamp": "2024-06-01T10:01:30.000Z",
"data": {
"jobId": "aaa1b2c3d4e5f6a7b8c9d0e1",
"type": "automation",
"targetId": "665a1b2c3d4e5f6a7b8c9d0e",
"executionId": "777b2c3d4e5f6a7b8c9d0eee",
"sessionId": "999c3d4e5f6a7b8c9d0e1fff",
"status": "completed",
"result": { "status": "completed" },
"error": null,
"completedAt": "2024-06-01T10:01:30.000Z"
}
}
| Champ | Type | Description |
|---|---|---|
jobId | string | ID du job |
type | string | automation ou pipeline |
targetId | string | ID de l'automation ou du pipeline |
executionId | string | null | ID de l'exécution associée |
sessionId | string | null | ID de la session sauvegardée à la fin du run, pour chaîner la session au run suivant (null si aucune) |
status | string | completed ou failed |
result | object | null | Résultat du job |
error | string | null | Message d'erreur |
completedAt | string | null | Date de fin au format ISO |
Headers envoyés
| Header | Description |
|---|---|
Content-Type | application/json |
User-Agent | Gurren-Webhook/1.0 |
X-Gurren-Event | Nom de l'événement (ex: automation.completed) |
X-Gurren-Signature | Signature HMAC SHA-256 du body |
Vérification de signature
Chaque requête est signée avec le secret de votre webhook. Vérifiez la signature pour vous assurer que la requête provient bien de Gurren.
La signature est au format sha256=<hex_hmac>.
Webhooks de job (livrés au
webhookUrlfourni à/enqueue) : ils sont signés avec le secret du webhook enregistré pour cette même URL. Enregistrez donc un webhook (même URL, secret voulu) pour que lesjob.*arrivent signés et passent votre vérification. (À défaut,WEBHOOK_SIGNING_SECRETcôté serveur sert de repli.)
Exemple en Node.js
const crypto = require('crypto');
function verifySignature(secret, body, signature) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Dans votre handler Express
app.post('/webhook', (req, res) => {
const signature = req.headers['x-gurren-signature'];
const body = JSON.stringify(req.body);
if (!verifySignature('whsec_votre_secret', body, signature)) {
return res.status(401).send('Invalid signature');
}
// Traiter l'événement
console.log(req.body.event, req.body.data);
res.status(200).send('OK');
});
Retry et fiabilité
En cas d'échec de livraison (timeout, erreur HTTP 5xx), Gurren retente automatiquement avec un backoff exponentiel :
| Tentative | Délai |
|---|---|
| 1 | 5 secondes |
| 2 | 30 secondes |
| 3 | 2 minutes |
| 4 | 10 minutes |
| 5 | 30 minutes |
Après 5 tentatives échouées, la livraison est abandonnée. Le compteur failureCount du webhook est incrémenté à chaque échec et remis à zéro après une livraison réussie.
Consultez le champ
failureCountetlastStatusdans le détail du webhook pour diagnostiquer les problèmes.