Appuyez sur / pour rechercher

Toute la documentation
docs Surveiller et agir Automatisations et webhooks

S’exécute surWrit CloudAuto-hébergé

Référence & guide

Automatisations & webhooks

Une automatisation relie un événement à une action : un changement détecté, un webhook entrant, une planification ou un événement d’exécution déclenche une règle, ses conditions sont vérifiées, et ses actions s’exécutent. Les webhooks transportent les événements en entrée et les résultats en sortie — signés dans les deux sens.

Déclencheurs, conditions, actions

Une automatisation se compose de blocs : un déclencheur (l’événement qui la fait partir), des conditions optionnelles et une ou plusieurs actions. Les déclencheurs partent sur ces types d’événements — change_detected est le défaut :

Type d’événementPart quand
change_detectedUne vérification de surveillant trouve un changement réel face à sa référence.
webhook_receivedUn système externe appelle votre hook entrant ou une porte custom_path.
ai_session_started / ai_session_completedUne AI session démarre ou se règle.
workflow_started / workflow_completedUne exécution de workflow démarre ou se règle.
monitor_down / monitor_stale / monitor_recoveredUn surveillant cesse de répondre, cesse de rapporter, ou revient.
crawl_started / crawl_completed / crawl_failedUn crawl démarre, se termine ou échoue.
scheduledUn bloc de planification à la racine de l’automatisation part à l’heure.

Les actions sont notification, ai_session, workflow, crawl ou create_persona — plus return_data en forme de bloc pour répondre à un appelant synchrone. Quand plusieurs règles correspondent, la priorité est l’ordre d’exécution. Les conditions utilisent les mêmes onze opérateurs, le même contexte de template et les mêmes filtres que dans surveillants.

Writ s’exécute sur vos propres comptes, avec vos propres identifiants et données, sur les sites que vous êtes autorisé à utiliser.

Webhooks entrants (signés)

Chaque hook entrant possède un secret de signature, attribué à sa création — il ne peut pas être effacé, et les appels non signés sont rejetés. La signature est un HMAC-SHA256, encodé en hexadécimal, sur "{timestamp}." + corps brut :

POST /api/webhooks/hook/{token}
Content-Type: application/json
X-Writ-Timestamp: 1718980000
X-Writ-Signature: sha256=<hex>

{ "sku": "SKU-123" }
  • X-Writ-Timestamp est obligatoire ; absent, invalide ou plus vieux que 300 secondes, la réponse est 401.
  • La même signature revue sous 300 secondes est rejetée avec 403 — un appel capturé ne peut pas être rejoué.
  • Un en-tête X-Hub-Signature-256 à la GitHub est accepté en alternative à X-Writ-Signature.
  • Chaque token de hook est limité à 30 appels par 60 secondes ; au-delà, la réponse est 429.

Portes custom_path

Un déclencheur webhook peut aussi revendiquer un custom_path — un chemin lisible d’au plus 100 caractères, unique dans votre espace de travail — servi à une URL stable et authentifié par une clé API plutôt que par une signature par appel :

POST /api/v1/webhooks/{custom_path}?wait=true&timeout=120
Authorization: Bearer wt_xxxxxxxxxxxx
Content-Type: application/json

{ "sku": "SKU-123" }
  • Authorization: Bearer avec une clé API est obligatoire — sans clé valide, la réponse est 401. Le chemin se résout dans l’espace de travail de la clé appelante.
  • L’action de la porte est run_workflow (défaut) ou check_target.
  • Une porte run_workflow compte dans le quota d’endpoints publiés de votre plan.
  • Appels synchrones : réglez wait_for_result sur le déclencheur (false par défaut) avec wait_timeout de 10 à 300 secondes (120 par défaut) — ou surchargez par appel avec ?wait= et ?timeout=.

Livraisons sortantes

Le canal de notification webhook poste les résultats vers votre endpoint, signés pour que vous puissiez les vérifier. Les livraisons se comportent de façon prévisible :

  • POST ou PUT uniquement, avec User-Agent: Writ-Webhook/1.0 et X-Writ-Timestamp sur chaque requête.
  • Vérifiez X-Writ-Signature-V1 : il couvre « {timestamp}. » + le corps brut, la même matière qu’un appel entrant, donc une seule recette sert les deux directions et une livraison capturée expire avec son horodatage.
  • X-Writ-Signature voyage à côté et couvre le corps JSON uniquement. Il existe pour que les handlers écrits avant V1 continuent de fonctionner — ne l’utilisez pas dans du code neuf.
  • Les redirections ne sont jamais suivies, et les livraisons vers des destinations de réseau privé sont refusées — une destination refusée n’est pas retentée.
  • Jusqu’à 3 tentatives, avec un délai de 30 secondes chacune et un backoff exponentiel plafonné à 30 secondes.

Et ensuite

  • Surveillants : le pipeline de déclenchement, les opérateurs de condition et les filtres de template.
  • Workflows : ce qu’exécute une action run_workflow.
  • Managed endpoints : le quota d’endpoints publiés que partagent les portes custom_path.

Deux directions, deux signatures

Les webhooks circulent dans les deux sens : un système externe peut lancer une automatisation Writ, et Writ peut poster vers votre endpoint. Les deux directions sont signées en HMAC — mais elles ne signent pas la même matière, vérifiez donc chacune correctement.

Entrant — vous appelez Writ

POST vers votre URL de hook avec un en-tête d’horodatage et une signature sur « {timestamp}. » + le corps brut. L’horodatage doit être frais (moins de 300 secondes) et une signature répétée est rejetée comme rejeu.

Sortant — Writ vous appelle

Writ livre un payload JSON avec une signature sur le corps uniquement. L’horodatage voyage en en-tête à côté de la signature, pas dans le MAC.

Signer un appel de déclenchement entrant

Calculez un HMAC-SHA256 avec le secret du hook sur "{timestamp}." + body, encodez-le en hexadécimal et envoyez les deux en-têtes. La signature est obligatoire — les appels non signés sont rejetés, et le secret est attribué avec le hook sans pouvoir être désactivé. Un en-tête X-Hub-Signature-256 à la GitHub est accepté en alternative.

send.py

import hashlib, hmac, json, os, time
import requests

secret = os.environ["WEBHOOK_SECRET"]        # shown when the inbound hook is created
body = json.dumps({"sku": "SKU-123"})
ts = str(int(time.time()))
sig = hmac.new(secret.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()

requests.post(
    "https://api.usewrit.app/api/webhooks/hook/{token}",
    data=body,
    headers={
        "Content-Type": "application/json",
        "X-Writ-Timestamp": ts,
        "X-Writ-Signature": f"sha256={sig}",
    },
    timeout=30,
)

Vérifier une livraison sortante

Prenez X-Writ-Signature-V1, retirez le préfixe sha256=, recalculez un HMAC-SHA256 sur « {timestamp}. » + le corps brut avec le secret de votre endpoint, et comparez en temps constant. L’ancien X-Writ-Signature couvre le corps seul et reste envoyé pour les handlers écrits avant V1 — le code neuf doit vérifier V1.

verify.py

import hashlib, hmac, os

def verify(raw_body: bytes, signature: str) -> bool:
    secret = os.environ["WRIT_WEBHOOK_SECRET"].encode()
    expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
    # Constant-time compare - never use ==
    return hmac.compare_digest(expected, signature)

Vérifiez toujours avant d’agir. Utilisez le corps brut, non analysé — l’analyser puis le re-sérialiser change les octets et casse la signature. Contrôlez la fraîcheur de X-Writ-Timestamp et ignorez les payloads déjà traités.

À quoi ressemble une livraison

Une livraison change_detected porte l’événement, un horodatage, le target, le sélecteur qui a changé, et le contenu avant/après avec leurs empreintes. Les livraisons partent en POST ou PUT, avec User-Agent Writ-Webhook/1.0, et les redirections ne sont jamais suivies.

POST /your/webhook/handler HTTP/1.1
Content-Type: application/json
User-Agent: Writ-Webhook/1.0
X-Writ-Timestamp: 1718980000
X-Writ-Signature-V1: sha256=6b3a9c…
X-Writ-Signature: sha256=9f86d0…

{
  "event": "change_detected",
  "timestamp": "2026-08-03T14:02:11Z",
  "target": { "id": 42, "url": "https://example.com/pricing", "name": "Pricing page" },
  "selector": { "css": ".price", "name": "price" },
  "change": {
    "content_before": "$129",
    "content_after": "$119",
    "content_hash": "…",
    "previous_hash": "…"
  }
}

Ce qui déclenche une automatisation

Webhook entrant

Un système externe poste vers votre URL de hook signée — ou vers une porte custom_path authentifiée par Bearer.

Changement détecté

Une vérification de moniteur trouve un changement réel face à sa référence et le pipeline de déclenchement distribue l’automatisation.

Événements d’exécution

Les événements de cycle de vie des workflows, sessions IA et crawls — démarré, terminé, échoué — et les transitions d’état des moniteurs.

Voir le modèle complet des déclencheurs et actions dans automations et le motif watch-and-act dans moniteurs.

FAQ Webhooks

Comment les livraisons sortantes sont-elles authentifiées ?
Chaque livraison porte X-Writ-Signature-V1 : sha256=<hex> — un HMAC-SHA256 sur « {timestamp}. » + le corps JSON brut avec le secret de votre endpoint. Retirez le préfixe sha256=, recalculez sur les octets bruts et comparez en temps constant. Rejetez tout ce qui ne correspond pas. Un X-Writ-Signature sur le corps seul voyage à côté, pour les handlers écrits avant V1.
Comment les rejeux sont-ils empêchés sur les appels entrants ?
L’en-tête X-Writ-Timestamp est obligatoire et doit dater de moins de 300 secondes — un horodatage absent, invalide ou périmé reçoit 401. La même signature revue sous 300 secondes est rejetée avec 403. Chaque token de hook est aussi limité à 30 appels par 60 secondes (429 au-delà).
Quel en-tête de signature sortante faut-il vérifier ?
X-Writ-Signature-V1. Il lie l’horodatage au MAC, donc une livraison capturée ne peut plus être rejouée dès que X-Writ-Timestamp est périmé, et il signe exactement la même matière qu’un appel entrant — une seule recette pour les deux directions. X-Writ-Signature couvre le corps seul et n’est conservé que pour les handlers écrits avant V1.
Où s’exécute le workflow déclenché ?
Sur votre propre agent local ou BYO sans frais de calcul, ou sur le cloud managé facturé au temps d’exécution. Writ s’exécute sur vos propres comptes, avec vos propres identifiants et données, sur les sites que vous êtes autorisé à utiliser.