Automation platforms

Turn a Hypeline change event into a trigger on Inngest, Zapier, Make, and Trigger.dev. A signed webhook destination is all any automation platform needs to run when a watched page changes.

A change event should be the thing that wakes an automation. Hypeline delivers every matched event as a signed HTTP POST, and any platform that can receive one becomes a trigger: "a watched page changed" runs your workflow, with the signature verified so you can trust the delivery. This group has a copy-paste recipe for each platform, built on one mental model.

The mental model

You create an alert (what to watch plus a filter), then add a webhook destination to it. Every event that alert matches is delivered to the destination as a signed POST. The destination URL is the automation platform's inbound webhook URL, so the platform receives the event directly. Nothing about the wire payload changes per platform: each recipe consumes the same signed body.

text
watched source changes  ->  alert matches  ->  signed POST to your platform's webhook URL  ->  your workflow runs

Register a destination once, per platform, using the same alert API the webhook delivery page documents:

bash
# 1. Create an alert (or reuse one). source_ids empty = your whole library.
curl -X POST https://api.hypeline.io/v1/alerts \
  -H "Authorization: Bearer $YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"filter_query":"outage","language":"en","source_ids":[]}'

# 2. Add a webhook destination whose url is the platform's inbound webhook URL.
#    delivery_mode instant is the shape every recipe here assumes.
curl -X POST https://api.hypeline.io/v1/alerts/{alert_id}/destinations \
  -H "Authorization: Bearer $YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"webhook","url":"https://hooks.example-platform.com/abc123","delivery_mode":"instant"}'

The create response reveals the whsec_ signing secret EXACTLY once. Store it: it is what your recipe uses to verify each delivery.

Destinations need a public HTTPS URL

Registration validates the destination URL and rejects private, loopback, and link-local addresses (SSRF protection on user-supplied URLs). A self-hosted automation platform on a LAN or localhost URL cannot be registered directly. Use a hosted platform, or expose your instance through a public HTTPS tunnel.

The delivered body

An instant webhook delivery carries a single StreamEvent as the raw JSON body. Its id is a UUIDv7 and doubles as the webhook-id header and your dedup key. The fields every recipe maps from:

FieldMeaning
idEvent UUIDv7. Same value as webhook-id. Your idempotency anchor.
source_idStable UUID of the source that changed.
source_typeThe source tier: push, feed, or html.
urlThe URL of the new or changed content.
titleTitle of the content, when available.
contentExtracted main content (capped).
diff / deltaStructured change on an HTML change event (present only there).
tagsThe event's tags, for example topic:test, region:se.
emitted_atWhen the event was emitted (RFC 3339, UTC).
signature / key_id / signed_atThe Ed25519 content signature (see below).
alert_typeSet only on an engine alert notification (for example source_quiet); absent on a normal match.

The full schema is in the API reference.

Recipes pin instant delivery

Every recipe here assumes delivery_mode: "instant", one event per POST. A digest destination (15min, hourly, or daily) posts a different wire shape: a batch wrapper with a destination_id and an events array. That shape is out of scope for these recipes; pin instant when you register the destination.

Two trust layers

Every delivery carries two independent signatures, and the recipes use whichever the platform makes easy:

LayerWhat it provesHow to verify
Standard Webhooks HMACThis exact POST reached you intact and is not a replay.HMAC-SHA256 over the raw body with the whsec_ secret. Needs the unparsed body bytes.
Event Ed25519 signatureThe event content is authentic Hypeline, on any transport.Public-key check over the canonical event. Survives a platform re-serializing the JSON.

The HMAC secures a single delivery, so it needs the raw request bytes. Some platforms parse the body before your code sees it, which makes the HMAC impossible to recompute there. The Ed25519 signature is attached to the event content and verified against a JCS-canonicalized copy, so it holds even after a platform re-encodes the JSON. That property is what the Inngest and Trigger.dev recipes lean on. See verifying events for the full Ed25519 recipe.

The signing headers

Each POST carries three headers. webhook-id is the same UUIDv7 as the event id, so it is both your signature input and your dedup key:

HeaderValue
webhook-idThe event UUID (also your idempotency / dedup key).
webhook-timestampUnix-seconds time the delivery was signed.
webhook-signatureOne or more space-delimited v1,<base64> tokens.

Dedup on the event id

Delivery is at-least-once, so the same event can arrive more than once. Every recipe dedups on the event id (the webhook-id): n8n static data, an Inngest event id, a Trigger.dev idempotencyKey, or a Zapier Storage check. Treat a repeated id as already handled.

Try it before you wire a platform

Prove the loop end to end before pointing a real workflow at it:

  • Register a destination, then fire a real sample delivery with POST /v1/destinations/{id}/test. The signed sample is byte-identical to a live delivery, which is exactly what Make's "determine data structure" step needs.
  • Point the destination at a webhook bin (POST /v1/webhook-bins mints a capture URL; GET /v1/webhook-bins/{id}/captures shows what arrived) to inspect headers and body without leaving Hypeline.
  • Or run the bundled whreceiver command locally: it prints each delivery and whether the signature verified.

Pick your platform

  • Inngest: a transform turns the POST into an Inngest event; durable functions subscribe by name.
  • Zapier and Make: Catch Hook (fast) or Catch Raw Hook plus a verifier step (Zapier), and a custom webhook module (Make).
  • Trigger.dev: a route in your own code verifies with the standardwebhooks library and calls tasks.trigger().