Webhook
Vérifiez, transformez, abonnez, interrogez, testez et formatez les webhooks d'un fournisseur avec une seule capacité.
Utilisez la capacité webhook pour les fournisseurs qui envoient des événements vers la plateforme. Chaque implémentation vérifie et transforme les événements entrants. Les méthodes optionnelles couvrent les défis de validation, la correspondance des déclencheurs, l'idempotence, le cycle de vie des abonnements, l'interrogation de secours, les payloads de test et les réponses propres au fournisseur.
Définir la capacité
import { defineWebhooks } from "@scrydon/sdk-authoring/extensions/define";
const webhookCapability = defineWebhooks({
async verify(request) {
const signature = request.headers["x-webhook-signature"];
const valid = verifyHmac(request.rawBody, signature, request.secret);
return { valid, error: valid ? undefined : "Invalid signature" };
},
async transform(body, context) {
const event = body as { id: string; type: string; data: unknown };
return { id: event.id, eventType: event.type, data: event.data };
},
async challengeHandler(request) {
const token = new URL(request.url).searchParams.get("challenge");
return token ? new Response(token, { status: 200 }) : null;
},
matchEvent(event, trigger) {
return event.eventType === trigger.config.eventType;
},
subscription: {
async subscribe(request) {
return createVendorSubscription(request);
},
async renew(subscriptionId, request) {
return renewVendorSubscription(subscriptionId, request);
},
async unsubscribe(subscriptionId, credentials) {
await deleteVendorSubscription(subscriptionId, credentials.accessToken);
},
},
extractIdempotencyKey(headers) {
return headers["x-webhook-delivery-id"] ?? null;
},
async buildTestPayload(request) {
return {
status: 200,
payload: { type: "webhook.test", webhookId: request.webhookId },
};
},
polling: {
async initialize(request) {
return { cursor: { since: new Date().toISOString() } };
},
async poll(request) {
return pollVendorEvents(request.credentials.accessToken, request.cursor);
},
},
responseFormatter: {
formatSuccess() {
return new Response(null, { status: 202 });
},
formatError(error) {
return Response.json({ error: error.message }, { status: 400 });
},
},
});
// Attach it to a toolkit: defineToolkit({ ..., webhooks: webhookCapability })subscribe, renew, les méthodes d'interrogation et de test reçoivent les identifiants
résolus pour le tenant courant dans la frontière d'exécution de la plateforme. Ne les
persistez, ne les journalisez et ne les retournez jamais. verify reçoit séparément le
secret webhook configuré afin qu'une requête entrante ne puisse pas fournir elle-même la
valeur utilisée pour l'authentifier.
Surface complète des méthodes
La plateforme associe chaque méthode d'authoring à une opération fermée et typée. Le code applicatif doit utiliser la capacité au lieu de charger des versions de code ou d'appeler directement les utilitaires du fournisseur.
| Méthode d'authoring | Obligatoire | Opération de plateforme | Objectif |
|---|---|---|---|
verify | oui | extensions.webhooks.verify | Authentifier la requête brute avant son traitement |
transform | oui | extensions.webhooks.transform | Convertir le corps fournisseur en événement de workflow |
challengeHandler | non | extensions.webhooks.challenge | Répondre aux défis de validation du fournisseur |
matchEvent | non | extensions.webhooks.match | Déterminer si un événement correspond à un déclencheur configuré |
extractIdempotencyKey | non | extensions.webhooks.idempotency.extract | Dériver une identité de livraison stable pour dédupliquer les nouvelles tentatives |
subscription.subscribe | non | extensions.webhooks.subscriptions.create | Créer un abonnement fournisseur |
subscription.renew | non | extensions.webhooks.subscriptions.renew | Renouveler un abonnement arrivant à expiration |
subscription.unsubscribe | non | extensions.webhooks.subscriptions.delete | Supprimer un abonnement fournisseur |
polling.initialize | non | extensions.webhooks.polling.initialize | Établir le premier curseur d'interrogation |
polling.poll | non | extensions.webhooks.poll | Récupérer les événements lorsque la livraison push n'est pas disponible |
buildTestPayload | non | extensions.webhooks.test.build | Construire un événement de test adapté au fournisseur |
responseFormatter | non | extensions.webhooks.response.format | Formater les accusés de réception de succès ou d'erreur |
Lorsqu'une méthode optionnelle est absente, elle renvoie explicitement not_supported à la
frontière de la plateforme. Les erreurs du fournisseur restent des erreurs ; elles ne sont
pas interprétées comme une capacité non prise en charge ni comme un succès implicite.
Valeurs à l'exécution
WebhookSubscription.expiresAtest unDatedans le code d'authoring. La frontière du worker le sérialise en horodatage ISO 8601 pour les appelants de la plateforme.- Les méthodes de défi et de formatage de réponse peuvent retourner un
Responsestandard. Le statut, les en-têtes et le corps sont sérialisés à travers la frontière du worker. transformpeut retournernullpour ignorer volontairement un événement.- L'interrogation retourne
payloads, le prochain curseurchangesetapiCallCount; gardez le curseur sérialisable en JSON, car il est persisté entre les exécutions. - L'interrogation se déclare sur le toolkit et couvre tous les déclencheurs qu'il
possède. Déclarer
webhooks.pollingmet chacun des blocs déclencheurs du toolkit en mode interrogation, et la plateforme appelle l'uniquepoll()pour tous. Branchez surrequest.triggerId— le type de bloc déclencheur interrogé, par exemplesharepoint-new-file-trigger— plutôt que de deviner d'après les clés présentes dansproviderConfig. Il n'est facultatif que pour les toolkits à déclencheur unique. defineTriggern'accepte plus de champruntime. Il n'était jamais lu : un déclencheur qui définissaitruntime.pollingpassait la vérification de types mais ne pouvait pas se déclencher. Déclarez plutôtdefineToolkit({ webhooks: defineWebhooks({ polling }) }).- Le manifeste construit enregistre
webhooks.verifypour chaque toolkit qui déclarewebhooks. Une plateforme en versionv1.3.25-rc.46ou antérieure refuse cette clé : une extension construite avec ce SDK nécessite une version ultérieure de la plateforme. - La livraison est « au moins une fois ». Donnez à chaque payload interrogé un
eventId(ouid) stable : la plateforme en dérive l'identité de l'exécution, de sorte qu'une livraison répétée du même événement est enregistrée comme doublon au lieu de démarrer une seconde exécution.