Scrydon
IntegrationsCapabilities

Webhook

Verify, transform, and (optionally) subscribe to vendor webhooks.

For vendors that send webhooks into the platform — verify the signature, transform the body, and optionally manage the subscription lifecycle.

Define the capability

import { defineCapabilityWebhook } from "@scrydon/sdk-authoring/integrations/define";

const webhookCapability = defineCapabilityWebhook({
  // 1. Verify incoming webhook authenticity
  async verify(request) {
    const signature = request.headers["x-webhook-signature"];
    const isValid = verifyHmac(request.rawBody, signature, request.secret);
    return { valid: isValid, error: isValid ? undefined : "Invalid signature" };
  },

  // 2. Transform raw body into structured data
  async transform(body, context) {
    const event = body as { type: string; data: unknown };
    return { eventType: event.type, data: event.data, timestamp: Date.now() };
  },

  // 3. (Optional) Subscription lifecycle
  subscription: {
    async subscribe(request) {
      const response = await fetch("https://api.example.com/webhooks", {
        method: "POST",
        headers: { Authorization: `Bearer ${request.credentials.accessToken}` },
        body: JSON.stringify({ url: request.webhookUrl, events: request.events }),
      });
      const data = await response.json();
      return { subscriptionId: data.id, expiresAt: new Date(data.expiresAt) };
    },
    async unsubscribe(subscriptionId, credentials) {
      await fetch(`https://api.example.com/webhooks/${subscriptionId}`, {
        method: "DELETE",
        headers: { Authorization: `Bearer ${credentials.accessToken}` },
      });
    },
  },

  // 4. Idempotency — prevent duplicate processing
  extractIdempotencyKey(headers, body) {
    return headers["x-webhook-delivery-id"] ?? null;
  },
});

Required vs optional

MethodRequiredPurpose
verifyyesReject forged / replayed webhooks before they hit the workflow
transformyesShape the body into the trigger payload your blocks expect
subscription.subscribe / unsubscribenoImplement only if the vendor's API supports programmatic subscription
extractIdempotencyKeynoWithout it, retries from the vendor may fire workflows twice
On this page

On this page