Webhook
Déclenchez l'exécution d'un workflow lorsqu'un système externe envoie une requête HTTP vers une URL générée par Scrydon.
Le bloc Webhook génère un point de terminaison HTTP unique. Tout service externe capable d'envoyer une requête HTTP POST peut déclencher votre workflow.
Fonctionnement
- Ajoutez un bloc Webhook à votre workflow.
- Une URL de webhook unique est générée pour ce bloc — copiez-la depuis le champ Lien de déclenchement du bloc.
- Configurez votre service externe (GitHub, Stripe, tout système personnalisé) pour envoyer un POST à cette URL.
- Lorsque la requête arrive, le workflow démarre et le corps de la requête, les fichiers qu'elle transmet, les en-têtes, la méthode et les paramètres de requête sont injectés comme sorties du bloc.
L'éditeur enregistre le webhook une fois que les modifications en attente ont fini d'être sauvegardées. Tant que le serveur n'a pas confirmé l'enregistrement, le Lien de déclenchement reste vide au lieu d'afficher une URL fictive. Si l'enregistrement échoue, le bloc affiche une erreur avec une action permettant de réessayer. Les webhooks gérés par un déclencheur font partie du cycle de vie du bloc ; supprimez le bloc déclencheur plutôt que son webhook séparément.
Test dans un environnement modifiable
Vous n'avez pas besoin de déployer ou de promouvoir pour tester un webhook. Dans tout environnement modifiable, appeler l'URL de webhook exécute le workflow live/brouillon — exactement ce qui est sur le canvas — afin que vous puissiez itérer et tester de bout en bout pendant la construction.
Dans tout environnement en lecture seule, le webhook exécute plutôt le snapshot déployé et nécessite une version de déploiement active. Sans elle, l'appel renvoie 403 avec le code WORKFLOW_NOT_DEPLOYED ; la page Monitor marque un tel workflow Non déployé — déclencheurs bloqués et propose une action Déployer qui crée le snapshot sans modifier l'URL du webhook. Les noms d'environnements tels que Développement, Test, Staging et Production sont des conventions choisies par votre organisation, pas des rôles fixes de la plateforme. Chaque environnement possède sa propre URL de webhook, et promouvoir à nouveau le workflow dans le même environnement conserve cette URL — vous configurez le système externe une fois par environnement. Une exécution déclenchée par webhook agit sous l'identité Run As de l'environnement (le propriétaire du workflow si aucune n'est définie), exactement comme une exécution planifiée ou déclenchée par API ; voir Run As. Voir Déclencheurs → Environnements et test pour le modèle complet.
Appel depuis Monitor
Dans Monitor, développez un workflow — dans la vue Table ou la vue Timeline, qui listent toutes deux les mêmes déclencheurs — pour afficher l'URL, la méthode HTTP, le mode d'authentification et le support de l'identifiant de chaque déclencheur webhook. Copy URL copie l'URL nue et Copy example request copie un exemple curl qui conserve des espaces réservés tels que $WEBHOOK_TOKEN ou $WEBHOOK_SECRET, afin que l'identifiant ne soit jamais rendu sur la page. Dans une expression comme '…?token='"$WEBHOOK_TOKEN", les fragments entre guillemets adjacents constituent une syntaxe shell qui forme un seul argument d'URL ; les guillemets ne font pas partie de l'URL.
Cette surface génère une URL de test et une commande curl exécutable ; elle n'envoie pas une
deuxième requête HTTP et n'affiche pas un résultat séparé dans l'éditeur. Exécutez la commande dans
votre client HTTP pour voir le corps de réponse canonique. L'exécution est persistée et peut être
ouverte dans Monitor via son executionId, y compris après un rechargement.
Lorsque le webhook exige un identifiant configuré, utilisez Copier le jeton du webhook ou Copier le secret HMAC pour copier la valeur effectivement déployée. Utilisez Copier la commande cURL exécutable pour copier une commande complète dans laquelle cette même valeur est déjà insérée. Pour l'authentification par jeton d'URL, Copier l'URL authentifiée copie l'URL complète avec le jeton inséré pour les systèmes qui acceptent uniquement une URL. Scrydon ne récupère l'identifiant qu'après un clic sur l'une de ces actions. Il n'affiche ni ne met en cache sa valeur dans Monitor. Une référence vers un secret d'espace de travail est résolue dans l'espace de travail actuellement affiché dans Monitor.
Toute personne autorisée à voir ce workflow dans Monitor peut utiliser ces actions de copie. Pour modifier ou renouveler l'identifiant, mettez à jour le bloc Webhook source ou le secret d'espace de travail qu'il référence.
Un jeton, un secret HMAC, une URL authentifiée ou une commande exécutable
copiés constituent des données sensibles dans le presse-papiers. Une URL
authentifiée peut aussi être enregistrée dans l'historique du navigateur,
les journaux des proxys et les en-têtes Referer. Collez-les uniquement dans une
destination de confiance et effacez votre presse-papiers dès que vous n'en
avez plus besoin.
Qui a appelé votre webhook
Pour chaque appel à une URL de webhook — accepté, en double ou refusé — Scrydon enregistre qui l'a appelée : l'adresse de l'appelant telle que vue par la périphérie de la plateforme, la chaîne User-Agent du client, si l'authentification a réussi, et le statut HTTP par lequel Scrydon a répondu. Cela inclut les appels qui n'ont jamais démarré d'exécution, comme un échec de la vérification d'authentification ou une adresse absente de la liste d'autorisation. Les authentifications refusées sont enregistrées pour une rafale de 20 appels, puis 10 par minute et par webhook. Tant qu'un webhook dépasse une limite de débit, ou que la limite de débit ne peut pas être vérifiée, un seul appel refusé par minute est enregistré. Dans les deux cas, les autres appels sont refusés sans être enregistrés, afin qu'un afflux d'appels n'inonde pas l'historique.
L'adresse enregistrée est celle depuis laquelle la périphérie de la plateforme a vu arriver la requête. Si l'appel est passé par un autre proxy ou équilibreur de charge en amont de Scrydon, c'est l'adresse de ce saut qui est enregistrée — pas nécessairement celle du client d'origine qui se trouve derrière.
L'appelant apparaît à trois endroits :
- Détail de l'exécution — une exécution démarrée par un webhook s'ouvre sur une section Caller (From, Client, Auth, Event ID) au-dessus de la sortie. La barre supérieure de la fiche d'exécution ne nomme que le déclencheur ; l'adresse de l'appelant se trouve dans le champ From de cette section.
- Monitor — la ligne de chaque déclencheur webhook affiche son appel le plus récent (
Last call <time> from <address>) et le nombre d'appels rejetés au cours des dernières 24 heures, avec un lien vers l'historique complet des appels de ce déclencheur. - Deliveries — ouvre l'historique complet d'un déclencheur webhook : les appels regroupés par adresse d'appelant et par client, puis chaque appel individuel du plus récent au plus ancien, filtrables sur All ou Rejected, sur les dernières 24 heures, 7 jours ou 30 jours. Sélectionner un appel l'ouvre dans la fiche d'exécution — un appel qui a démarré une exécution ouvre cette exécution.
Les enregistrements d'appelants sont conservés 30 jours, la même durée de rétention que le reste de l'historique des déclencheurs d'un workflow. Ils sont visibles par quiconque peut consulter ce workflow dans Monitor. L'API des journaux (GET /api/v1/logs/{id}) ne les renvoie pas : une clé d'API ou un compte de service lit l'événement d'un appel sans l'adresse ni le client de l'appelant.
Les appels refusés n'apparaissent pas sur la chronologie de Monitor, qui montre les exécutions et les appels acceptés. Une rafale d'appelants rejetés ne marque donc pas un workflow sain comme défaillant. Les appels refusés restent dans l'historique Deliveries du déclencheur.
L'adresse de l'appelant et son User-Agent arrivent également sous forme d'en-têtes de requête ordinaires
(X-Forwarded-For, X-Real-IP, User-Agent), et le bloc webhook transmet
ses en-têtes de requête à l'exécution — seuls les en-têtes d'identifiants et les cookies sont
supprimés. Les blocs en aval peuvent les lire via <webhook1.headers>, et
ils sont stockés avec le journal de l'exécution aussi longtemps que les journaux d'exécution sont conservés, visibles
partout où le journal de cette exécution l'est.
Variables disponibles
Référencez la requête entrante dans les blocs en aval en utilisant le nom du bloc comme préfixe :
| Variable | Description |
|---|---|
<webhook1.body> | Le corps de la requête, décodé selon son Content-Type — voir Corps de requête et fichiers |
<webhook1.files> | Les fichiers transmis par la requête, sous forme de liste (vide s'il n'y en a aucun) |
<webhook1.headers> | En-têtes de la requête sous forme d'objet JSON |
<webhook1.method> | Méthode HTTP (POST) |
<webhook1.query> | Paramètres de la chaîne de requête sous forme d'objet JSON |
<webhook1.remoteAddress> | L'adresse de l'appelant, telle que vue par la périphérie de la plateforme |
<webhook1.receivedAt> | L'heure d'arrivée de la requête, au format ISO-8601 |
Remplacez webhook1 par le nom que vous avez donné au bloc.
Corps de requête et fichiers
Un webhook accepte du JSON, des formulaires, du texte brut et des fichiers. L'en-tête Content-Type détermine ce que reçoit le workflow :
| Requête | <webhook1.body> | <webhook1.files> |
|---|---|---|
JSON (application/json, application/*+json) | Le JSON analysé | Vide |
Formulaire (application/x-www-form-urlencoded) | Les champs sous forme d'objet JSON | Vide |
Formulaire multipart (multipart/form-data) | Les champs texte sous forme d'objet JSON | Une entrée par partie fichier |
Texte (text/*, XML, ou sans Content-Type) | Le texte brut, sous forme de chaîne | Vide |
Tout autre type (audio/*, image/*, application/pdf, …) | {} | Le corps, comme un seul fichier |
Un corps qui s'analyse comme du JSON est toujours traité comme du JSON, quel que soit son type déclaré. Un corps déclaré application/json qui ne s'analyse pas renvoie 400 Invalid payload format et ne démarre pas le workflow.
Chaque fichier de <webhook1.files> a la même forme que les fichiers reçus par un bloc Start : name, type, size, une clé de stockage key et une url de téléchargement. Passez <webhook1.files> à un bloc qui accepte une liste de fichiers, ou <webhook1.files[0]> à un bloc qui accepte un seul fichier, comme un bloc de transcription vocale. Les octets du fichier sont stockés avec l'exécution et ne sont pas copiés dans <webhook1.body>. L'url de téléchargement expire 10 minutes après l'arrivée de la requête.
# Envoi multipart : les champs texte arrivent dans <webhook1.body>, le fichier dans <webhook1.files>
curl -X POST "https://app.scrydon.com/agentic/api/webhooks/trigger/{path}" \
-H "Authorization: Bearer $WEBHOOK_TOKEN" \
-F "unit=7" \
-F "audio=@call-42.wav;type=audio/wav"
# Corps de fichier brut : nommé d'après Content-Disposition, ou upload.<extension> à défaut
curl -X POST "https://app.scrydon.com/agentic/api/webhooks/trigger/{path}" \
-H "Authorization: Bearer $WEBHOOK_TOKEN" \
-H "Content-Type: audio/mpeg" \
-H 'Content-Disposition: attachment; filename="call-42.mp3"' \
--data-binary @call-42.mp3La limite de taille du webhook, 10 Mo sauf si le bloc en fixe une autre, s'applique à la requête entière, fichiers compris. Pour un fichier plus volumineux, comme un long enregistrement, utilisez une session d'envoi. Une requête multipart peut transporter au plus 20 fichiers ; au-delà, elle renvoie 400. Les noms de fichiers ne conservent que leur dernier segment de chemin : ../../clip.wav est stocké sous clip.wav. Deux fichiers portant le même nom dans une même requête sont stockés sous clip.wav et clip-2.wav.
Les champs texte d'un formulaire multipart sont aussi accessibles directement via <webhook1.nomDuChamp>, comme les clés de premier niveau d'un corps JSON. <webhook1.files> contient toujours les fichiers de la requête : la clé files d'un corps JSON se lit via <webhook1.body.files>.
Limite de taille
Le champ Max Request Size (MB) du bloc Webhook fixe la plus grande requête que le webhook accepte, fichiers compris : 1, 5, 10, 25, 50 ou 100 Mo. Il vaut 10 Mo par défaut. Un mégaoctet vaut ici 1 048 576 octets : 10 Mo font donc 10 485 760 octets.
- Un bloc en mode d'authentification Aucune accepte au plus 10 Mo, quel que soit le réglage. Scrydon lit le corps d'une requête avant de vérifier l'identifiant, car une signature HMAC se calcule sur le corps. Une URL que n'importe qui peut appeler ne fait donc jamais conserver plus de 10 Mo à Scrydon.
- Les déclencheurs spécifiques aux fournisseurs acceptent 10 Mo.
- La périphérie de la plateforme accorde 60 secondes à une requête entière : 100 Mo demandent un débit montant d'environ 14 Mbit/s. Sur une liaison plus lente, ou pour un fichier de plus de 100 Mo, utilisez une session d'envoi.
Une requête plus volumineuse répond 413 Payload Too Large en indiquant la limite (Payload too large: this webhook accepts requests up to 25 MB) et ne démarre pas le workflow. Le refus est enregistré dans l'historique Deliveries du déclencheur. Une requête vers une URL qui ne correspond à aucun webhook répond 404 sans que son corps soit lu. Comme les champs d'authentification, la limite est lue dans le bloc à l'arrivée de chaque requête.
Fichiers volumineux : sessions d'envoi
Un fichier plus grand que ce qu'une seule requête peut transporter, jusqu'à 5 GiB, est envoyé en plusieurs parties via une session d'envoi. L'exécution le voit dans <webhook1.files> exactement comme un fichier envoyé en une seule requête.
Les sessions d'envoi sont disponibles sur le bloc Webhook générique, et seulement lorsque le bloc a une authentification configurée : un bloc en mode Aucune répond 403. Le stockage de l'organisation doit être un stockage objet (S3 ou Azure Blob) ; le stockage local répond 501.
| Étape | Requête | Identifiant |
|---|---|---|
| 1. Ouvrir | POST /api/webhooks/trigger/{path}/uploads | L'authentification propre au webhook |
| 2. Envoyer chaque partie | PUT /api/webhooks/uploads/parts/{partNumber} | Authorization: Bearer <jeton d'envoi> |
| 3. Terminer | POST /api/webhooks/uploads/complete | Authorization: Bearer <jeton d'envoi> |
| Annuler (facultatif) | POST /api/webhooks/uploads/abort | Authorization: Bearer <jeton d'envoi> |
1. Ouvrir la session. Envoyez le nom du fichier, son type de média et sa taille exacte en octets, authentifiés exactement comme une livraison normale vers ce webhook (pour un webhook HMAC, signez ce corps JSON). type est facultatif et vaut par défaut application/octet-stream.
{ "name": "call-42.wav", "type": "audio/wav", "size": 734003200 }Une réponse 201 Created décrit la session :
{
"executionId": "5b0f…",
"token": "eyJhbGciOiJIUzI1NiJ9…",
"expiresAt": "2026-10-10T09:00:00.000Z",
"partSize": 8388608,
"partCount": 88,
"urls": {
"part": "https://app.scrydon.com/agentic/api/webhooks/uploads/parts/{partNumber}",
"complete": "https://app.scrydon.com/agentic/api/webhooks/uploads/complete",
"abort": "https://app.scrydon.com/agentic/api/webhooks/uploads/abort"
}
}2. Envoyer chaque partie comme corps brut de la requête, numérotée de 1 à partCount. Chaque partie fait exactement partSize octets (8 MiB), sauf la dernière, qui contient le reste du fichier ; une partie d'une autre longueur répond 400 ou 413. Chaque partie répond { "partNumber": 3, "tag": "…" } ; conservez chaque tag. Les parties peuvent être envoyées dans n'importe quel ordre et en parallèle. Renvoyer une partie la remplace : utilisez alors le tag de son dernier envoi. Un 502 signifie que la partie n'a pas été stockée : renvoyez-la.
3. Terminer la session avec le tag de chaque partie et, éventuellement, le JSON que le workflow lit dans <webhook1.body> :
{
"parts": [
{ "partNumber": 1, "tag": "…" },
{ "partNumber": 2, "tag": "…" }
],
"body": { "unit": 7 }
}parts doit lister chaque partie de 1 à partCount, chacune une seule fois. La réponse est exactement celle d'une livraison en une seule requête : 200 {"message":"Webhook processed"}, ou le résultat du workflow lorsque Wait for Completion est activé. Terminer de nouveau la même session ne démarre jamais une seconde exécution ; la réponse est {"message":"Webhook already processed","duplicate":true}. Un complete qui a expiré ou renvoyé un 5xx peut donc être renvoyé sans risque.
Si le filtre de type d'événement du bloc écarte la requête de fin, les parties sont supprimées et aucune exécution ne démarre.
URL="https://app.scrydon.com/agentic/api/webhooks/trigger/{path}"
FILE=call-42.wav
SIZE=$(wc -c < "$FILE" | tr -d ' ')
session=$(curl -sf -X POST "$URL/uploads" \
-H "Authorization: Bearer $WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\":\"$FILE\",\"type\":\"audio/wav\",\"size\":$SIZE}")
UPLOAD_TOKEN=$(jq -r .token <<<"$session")
PART_SIZE=$(jq -r .partSize <<<"$session")
PART_URL=$(jq -r .urls.part <<<"$session")
parts="[]"
for n in $(seq 1 "$(jq -r .partCount <<<"$session")"); do
tag=$(dd if="$FILE" bs="$PART_SIZE" skip=$((n - 1)) count=1 2>/dev/null \
| curl -sf -X PUT "${PART_URL%"{partNumber}"}$n" \
-H "Authorization: Bearer $UPLOAD_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @- \
| jq -r .tag)
parts=$(jq -c --argjson n "$n" --arg tag "$tag" '. + [{partNumber: $n, tag: $tag}]' <<<"$parts")
done
curl -sf -X POST "$(jq -r .urls.complete <<<"$session")" \
-H "Authorization: Bearer $UPLOAD_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"parts\":$parts,\"body\":{\"unit\":7}}"Le jeton d'envoi est un identifiant propre à cette session : quiconque le détient
peut envoyer des parties et terminer l'exécution. Il expire à expiresAt, 24 heures
après l'ouverture de la session, et ne peut pas être révoqué plus tôt. Annulez une
session dont vous n'avez plus besoin. Scrydon masque le jeton dans <webhook1.headers>.
Seule l'ouverture d'une session compte dans la limite de débit du webhook. Dans le monitor du workflow, l'ouverture d'une session n'est enregistrée que lorsqu'elle est refusée. La fin est enregistrée comme une livraison : celle qui a démarré l'exécution, un doublon ou un refus, affichée avec l'authentification Bearer, car c'est le jeton d'envoi que présente la requête de fin. Une requête dont le jeton d'envoi est absent, invalide ou expiré ne peut être rattachée à aucun webhook et n'est pas enregistrée. Les parties et l'annulation ne le sont pas non plus.
Authentification
Les points de terminaison des webhooks génériques acceptent uniquement POST. Dans le champ Authentification du bloc, choisissez l'un des modes suivants :
Les nouveaux blocs Webhook utilisent par défaut le mode Jeton Bearer et génèrent automatiquement un jeton. Le corps de la requête est limité à 10 Mo par défaut ; voir Limite de taille.
Chaque URL de webhook possède son propre compartiment de jetons pour son producteur : elle accepte une rafale de 20 requêtes authentifiées et récupère 10 jetons toutes les 60 secondes. Seule une requête qui a passé l'authentification le consomme : une personne qui connaît l'URL mais pas son identifiant ne peut donc pas épuiser le quota de votre producteur. Chaque requête est aussi comptée par adresse d'appelant, avant d'être authentifiée : une rafale de 40 requêtes, avec 20 jetons récupérés toutes les 60 secondes. Lorsque l'un des deux compartiments est épuisé, Scrydon renvoie 429 Too Many Requests avec un en-tête Retry-After, sans démarrer le workflow. Si l'application de la limite est temporairement indisponible, Scrydon échoue en mode fermé avec 503 Service Unavailable et Retry-After: 5. Le producteur doit attendre l'intervalle indiqué avant de réessayer dans les deux cas.
| Mode | Configuration du bloc | Requête entrante |
|---|---|---|
| Jeton Bearer | Jeton Bearer généré lors de la création du bloc | Envoyez Authorization: Bearer <token>. Il s'agit du mode par défaut et recommandé. |
| En-tête statique | Nom de l'en-tête et Valeur de l'en-tête | Envoyez l'en-tête configuré avec la valeur exacte configurée. Les noms d'en-têtes sont insensibles à la casse ; les valeurs sont sensibles à la casse. |
| Signature HMAC | En-tête HMAC, Secret HMAC et Algorithme HMAC | Envoyez un HMAC des octets exacts du corps de la requête dans l'en-tête configuré. |
| Jeton d'URL | Paramètre du jeton (token par défaut) et Valeur du jeton | Envoyez le jeton comme paramètre de requête configuré. |
| Aucune | Aucun champ supplémentaire | Aucun identifiant d'authentification n'est requis. |
Le jeton d'URL est le mode le moins sûr — utilisez-le en dernier recours.
Un identifiant placé dans une URL peut apparaître dans les journaux d'accès
des proxys inverses, l'historique du navigateur et les en-têtes Referer,
que Scrydon ne contrôle pas. Ce mode existe pour les producteurs qui
acceptent uniquement une URL et ne peuvent ni envoyer un en-tête ni signer un
corps. Si le producteur accepte les en-têtes, utilisez plutôt un Jeton
Bearer, une Signature HMAC ou un En-tête statique.
Scrydon masque le paramètre du jeton configuré dans <webhook1.query> et dans
les journaux d'exécution. Il ne peut pas masquer le journal d'accès d'un proxy
en amont.
Jeton d'URL
# As a query parameter — for producers that only accept a URL
curl -X POST "https://app.scrydon.com/agentic/api/webhooks/trigger/{path}?token=$WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"event": "order.created", "orderId": "42"}'Utilisez une référence vers un secret d'espace de travail telle que {{GENERIC_WEBHOOK_TOKEN}} comme Valeur du jeton, exactement comme pour les autres modes.
Un Paramètre du jeton mal formé est rejeté comme configuration invalide au lieu de revenir silencieusement à la valeur par défaut. Un nom de paramètre qui ne pourrait jamais correspondre à la requête entrante empêcherait toute vérification de l'identifiant alors que la requête serait tout de même signalée comme authentifiée.
Avant d'exposer <webhook1.headers> au workflow, Scrydon masque l'en-tête d'authentification configuré et les en-têtes standards susceptibles de contenir des identifiants, tels que Authorization, Proxy-Authorization, Cookie et Set-Cookie.
Utilisez une référence vers un secret d'espace de travail Scrydon, comme {{GENERIC_WEBHOOK_TOKEN}} pour le Jeton Bearer, la Valeur de l'en-tête ou la Valeur du jeton, ou {{GENERIC_WEBHOOK_HMAC_SECRET}} pour le Secret HMAC. Scrydon résout la référence lors de l'authentification de la requête. Une référence manquante ou indisponible est rejetée.
Les champs de type mot de passe masquent uniquement leur contenu dans l'éditeur. Une valeur littérale est stockée en clair dans le JSON du workflow. Utilisez une référence vers un secret d'espace de travail afin que le secret reste protégé par le coffre-fort de secrets Scrydon.
Jeton Bearer
Le jeton Bearer généré peut être copié depuis Monitor après le déploiement du workflow :
curl -X POST "https://app.scrydon.com/agentic/api/webhooks/trigger/{path}" \
-H "Authorization: Bearer $WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"event": "order.created", "orderId": "42"}'En-tête statique
Par exemple, configurez Nom de l'en-tête sur X-Webhook-Token et Valeur de l'en-tête sur {{GENERIC_WEBHOOK_TOKEN}}, puis envoyez la valeur résolue :
curl -X POST "https://app.scrydon.com/agentic/api/webhooks/trigger/{path}" \
-H "Content-Type: application/json" \
-H "X-Webhook-Token: $WEBHOOK_TOKEN" \
-d '{"event": "order.created", "orderId": "42"}'Signature HMAC
Scrydon calcule le HMAC sur les octets exacts reçus, avant l'analyse JSON, le décodage du texte, la normalisation ou la resérialisation. Les espaces, l'ordre des propriétés, l'encodage Unicode et un saut de ligne final modifient donc la signature.
Les algorithmes pris en charge sont sha1, sha256 et sha512. Utilisez sha256, sauf si l'appelant nécessite un autre algorithme pris en charge. L'en-tête de signature accepte soit une empreinte hexadécimale seule, soit une empreinte préfixée par l'algorithme :
<hex-digest>
sha256=<hex-digest>Lorsqu'un préfixe est présent, il doit correspondre à l'algorithme configuré. Les chiffres hexadécimaux sont insensibles à la casse. Cet exemple signe et envoie exactement les octets contenus dans body :
body='{"event":"order.created","orderId":"42"}'
signature="$(printf '%s' "$body" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | awk '{print $NF}')"
curl -X POST "https://app.scrydon.com/agentic/api/webhooks/trigger/{path}" \
-H "Content-Type: application/json" \
-H "X-Hub-Signature-256: sha256=$signature" \
--data-binary "$body"Toute erreur d'authentification — en-tête manquant ou incorrect, signature mal formée, configuration invalide ou secret indisponible — renvoie la même réponse et ne démarre pas le workflow :
HTTP/1.1 401 Unauthorized
Content-Type: text/plain; charset=utf-8
Cache-Control: no-store
UnauthorizedLe HMAC authentifie le corps et la possession du secret partagé, mais il n'empêche pas le rejeu. Un appelant peut renvoyer un corps et une signature précédemment valides, car ce mode n'utilise ni horodatage ni nonce.
Livraisons en double
La livraison des webhooks est de type « au moins une fois » ; Scrydon déduplique donc les livraisons répétées d'un même événement. Il identifie un événement à partir du premier des éléments suivants qu'il trouve :
- un en-tête d'identifiant de livraison —
webhook-id,x-webhook-id,x-event-id,x-github-delivery,x-shopify-webhook-id,x-teams-notification-id - un champ d'identifiant dans le corps JSON —
eventId,event_id,messageId,notificationId,deliveryIdouid(également un niveau plus bas sousdata) - une empreinte du corps de la requête, lorsque la requête ne porte aucun des éléments ci-dessus
Une répétition d'un événement que Scrydon a déjà accepté renvoie 200 OK avec :
{ "message": "Webhook already processed", "duplicate": true }Le workflow n'est pas démarré une seconde fois, et la livraison est enregistrée dans le
monitor du workflow comme push_duplicate.
Cela vaut quel que soit le serveur Scrydon qui reçoit la répétition, et après un redémarrage :
- Une exécution encore en cours n'est jamais redémarrée, quelle que soit sa durée.
- Une exécution terminée n'est pas redémarrée pendant les 24 heures qui suivent l'acceptation de sa livraison. Une répétition qui arrive plus tard démarre une nouvelle exécution.
- Une livraison dont l'exécution n'a pas pu être démarrée peut être renvoyée : sa répétition démarre l'exécution.
L'étape 3 explique pourquoi renvoyer un corps identique ne démarre pas une seconde exécution : en l'absence d'identifiant de livraison dans la requête, le corps est la seule chose qui puisse distinguer une nouvelle tentative du fournisseur d'un événement réellement nouveau ; Scrydon traite donc des octets identiques comme le même événement.
Si vous effectuez des tests et souhaitez que chaque envoi démarre sa propre exécution, faites varier l'identifiant
de livraison — ajoutez un en-tête x-event-id, ou modifiez le champ id / eventId dans le
corps. Modifier une partie sans rapport du corps ne suffit pas lorsque le corps
porte déjà un champ d'identifiant, car l'étape 2 l'emporte sur l'étape 3.
Déclencheurs spécifiques aux fournisseurs
Pour les services disposant d'une intégration Scrydon dédiée (GitHub, Microsoft Graph, Atlassian, etc.), préférez le bloc de déclencheur du fournisseur au bloc Webhook générique. Les déclencheurs de fournisseurs analysent et valident automatiquement le payload d'événement et exposent des variables typées.
Voir Fournisseurs pour la liste complète des intégrations avec prise en charge des déclencheurs.
Répondre avec le résultat du workflow
Par défaut, un webhook répond immédiatement avec 200 {"message":"Webhook processed"} et le workflow s'exécute en arrière-plan. Activez Attendre la fin de l'exécution sur le bloc pour répondre avec le résultat :
{ "executionId": "…", "status": "completed", "outputs": { "response": { … } } }La sortie d'un bloc Response apparaît sous outputs. Si l'exécution dépasse 30 secondes, la requête renvoie 202 avec { "executionId", "status": "running" }. L'exécution se poursuit et l'identifiant permet de la suivre.
Un workflow qui atteint un échec terminal renvoie tout de même HTTP 200, car la requête webhook
a été acceptée et le workflow s'est terminé. La réponse contient la raison sûre pour le client :
{
"executionId": "…",
"status": "failed",
"error": {
"code": "INTEGRATION_ACCOUNT_NOT_WORKSPACE_ENABLED",
"message": "Service account sa_… has no Microsoft Teams (org:scrydon:microsoft:teams) account it can use in this workspace. Link one to it under Settings → Members → Service Accounts → Credentials, or assign an execution credential to the workspace under Settings → Workspaces → Execution credentials.",
"retryable": false,
"blockId": "teams-1"
}
}L'authentification, une entrée mal formée et le rejet par la file ou l'infrastructure conservent
leurs statuts 4xx/5xx habituels. Une réponse 202 running indique seulement l'expiration du délai
de polling synchrone ; consultez ensuite l'état d'exécution ou ouvrez le run dans Monitor pour voir
l'erreur terminale persistée. Monitor affiche le même code et message après rechargement et met en
évidence le bloc en erreur lorsque blockId est présent.
Lorsqu'un bloc échoue parce que le compte par lequel il agit ne peut pas servir
l'appel, error.code peut être l'un de ces codes. Chacun indique quoi corriger :
| Code | Quoi corriger |
|---|---|
INTEGRATION_ACCOUNT_NOT_CONNECTED | La connexion n'a aucun compte utilisable. Connectez-en un dans Paramètres → Compte → Comptes connectés, ou attribuez-en un à l'espace de travail. |
INTEGRATION_ACCOUNT_REAUTHORIZATION_REQUIRED | La connexion du compte a expiré ou a été révoquée. Reconnectez le compte. |
INTEGRATION_ACCOUNT_MISSING_SCOPES | L'autorisation du compte ne couvre pas toutes les permissions dont l'extension a besoin. Reconnectez-le en acceptant toutes les permissions demandées. |
INTEGRATION_ACCOUNT_NOT_WORKSPACE_ENABLED | Aucun compte utilisable par l'exécution n'est attribué à cet espace de travail. Attribuez-en un dans Paramètres → Espaces de travail → Identifiants d'exécution. |
Laissez cette option désactivée, sauf si l'appelant attend une réponse. Les producteurs de webhooks sont généralement des machines dont le délai d'attente client est court — celui de Keel est de 5 secondes. Keel considère une réponse lente comme un échec de livraison et réessaie ; une réponse synchrone peut donc transformer un événement en une tempête de nouvelles tentatives. L'accusé de réception immédiat existe pour cette raison.