Skip to main content

Event Delivery

Event Delivery sends you an HTTP request whenever something changes in your Helix feeds and fact-checks — new articles, event updates, fact-check completions — so your systems can react without polling.

If you used the old webhooks system, unlearn this first

The old system bound one URL to one domain: "my webhook for news" or "my webhook for events." Event Delivery has no such binding. It separates where a delivery goes from what triggers it. If you carry the old mental model into this system, you will misconfigure your first destination — most commonly by assuming a destination only ever receives one kind of event.

Two objects, not one

Destinations — where

A destination is an HTTP endpoint that can receive deliveries: a URL, optional static headers, a debounce window, and one or more signing secrets. A destination knows nothing about which events it will receive — it is purely "here is a place to send things, and here is how to prove it came from us."

POST /events/destinations
{
"name": "Newsroom CMS",
"transport": "webhook",
"config": { "url": "https://cms.acme.com/hx" }
}

Subscriptions — what

A subscription belongs to a destination and declares which events it receives: a set of event-type patterns (exact types or wildcards, such as news.*) and a feed scope (every feed the organization can see, every feed of one kind, or a specific pinned list).

POST /events/destinations/{id}/subscriptions
{
"eventTypes": ["news.*"],
"scopeKind": "feeds",
"feeds": [{ "feedType": "news", "feedId": "…" }]
}

One destination can hold several subscriptions. A single URL can therefore receive news.* from two specific feeds and factcheck.* for the whole organization at once — something the old one-webhook-per-domain model could not express without registering the same URL three times.

Why this split exists

The old system conflated "where to send it" with "what to send" because a webhook row carried both a URL and a domain (news, events, fact_check). Every new routing need — a second feed, a narrower scope, a different combination of event types — meant either a new webhook row pointing at the same URL, or widening an existing one to receive more than you wanted. Splitting the two means:

  • One endpoint, many rules. Register the URL once as a destination, then layer as many subscriptions on it as you need.
  • Routing is data, not a hardcoded per-domain switch. Adding a new event type never requires a new integration point — it is just another value a subscription's eventTypes pattern can match.
  • Scope is explicit. scopeKind: "all", "feed_type", or "feeds" says exactly what an existing subscription can see, rather than leaving "which feeds does this webhook cover" as an implicit property of which resource happened to enable it.

What's next

  • Concepts — the envelope, the event type taxonomy, wildcards, feed scoping, and debounce.
  • Quickstart — create a destination, subscribe, verify, and receive your first delivery.
  • Signature Verification — verify that a delivery came from Helix.
  • Reliability — retries, auto-disable, replay, and backfill.
  • API Reference — the full /events/* surface.