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.
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
eventTypespattern 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.