Skip to main content

Event Feeds

Aggregate and monitor events from websites, sitemaps, and social media with structured event data including dates, times, and locations.

Getting Started: You create a feed, add its websites and decide what it carries through the API. See the Quickstart to build one end to end.

Overview​

Event feeds collect events from multiple sources into a single, organized stream. Each feed continuously monitors its sources for new events, automatically extracting structured data including titles, descriptions, dates, times, and geographic locations.

Key benefits:

  • Automatic discovery: New events are detected and processed without manual intervention
  • Rich event data: Structured information with dates, times, locations, and occurrences
  • Flexible retrieval: Access via API polling or webhooks
  • Historical backfill: Automatically includes the past 14 days of events from each source, once: when you enable the feed, or when you add or enable a source on an enabled feed

Quick Example​

Once your feed is set up, retrieving events is straightforward:

# Retrieve events from your feed
curl "https://api.feeds.onhelix.ai/feeds/events/{feedId}/items?limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"

See the Quickstart Guide for a complete walkthrough.

How It Works​

  1. Sources: You add websites to your feed through the API; our team adds listing pages, sitemaps and social accounts on request (see Sources)
  2. Automatic backfill: Events from the past 14 days of a source are added to your feed once: when you enable the feed, or when you add or enable the source on an enabled feed
  3. Continuous monitoring: Sources are continuously monitored for new events
  4. Event extraction: Events are automatically extracted with dates, times, and locations
  5. Your filters decide: Processors answer questions about each event, and your feed's filters include or exclude events on those answers (see Which Events a Feed Carries)

Event Feed Items​

Each item in your feed has a source-agnostic shape. Optional fields are omitted (not nulled) when missing; arrays are always present (empty when no data), except when.recurrence.exceptions, which is omitted when there are none.

FieldDescription
idFeed-item identifier (per feed). Use it for feedback and per-feed dedup.
eventIdUnderlying event identifier. The same event in two feeds has different ids but the same eventId.
addedToFeedAtWhen the event was added to this feed
updatedAtWhen the item last changed in a way subscribers are notified of
statusactive, or cancelled when the whole event was cancelled
titleEvent title
descriptionEvent description
shortDescriptionOne-sentence summary (omitted when none)
completeness{ score, missing[] }: how complete the data is (omitted for events not yet scored)
whenSchedule: pattern, timezone, displayText, recurrence, next, occurrences[], upcomingCount
whereLocation: venue, address, geo, online, multipleVenues, displayText (omitted when nothing is known)
links{ best, all[] }: the recommended "more info" link and every known URL, ranked, with who published each
media{ cover, images[] }: the event's images; cover can be null even when images has entries (see the API reference)

Example event feed item:

{
"id": "3f6c1d52-7a0e-4b8e-9d1c-5a2b8e4f6a10",
"eventId": "9b2e7c44-1d3a-4f65-8a7b-0c5d2e9f1b33",
"addedToFeedAt": "2026-10-20T14:03:00.000Z",
"updatedAt": "2026-10-24T09:12:00.000Z",
"status": "active",
"title": "Toddler Story Time",
"description": "Stories, songs and rhymes for children ages 1 to 3 and their caregivers at the Main Library. Free, no registration needed.",
"shortDescription": "Stories and songs for ages 1 to 3.",
"completeness": {
"score": 0.85,
"missing": ["ticketUrl"]
},
"when": {
"pattern": "recurring",
"timezone": "America/New_York",
"displayText": "Alternating Wednesdays, 9:00 AM – 9:45 AM",
"recurrence": {
"description": "9-9:45 a.m. on alternating Wednesdays",
"startDate": "2026-03-04",
"endDate": "2026-12-31",
"exceptions": ["2026-07-08"],
"patterns": [
{
"rule": "FREQ=WEEKLY;INTERVAL=2;BYDAY=WE",
"startTime": "09:00",
"endTime": "09:45",
"description": "Alternating Wednesdays"
}
]
},
"next": {
"start": "2026-11-11T14:00:00.000Z",
"end": "2026-11-11T14:45:00.000Z",
"allDay": false,
"status": "scheduled"
},
"occurrences": [
{
"start": "2026-11-11T14:00:00.000Z",
"end": "2026-11-11T14:45:00.000Z",
"allDay": false,
"status": "scheduled"
},
{
"start": "2026-11-25T14:00:00.000Z",
"end": "2026-11-25T14:45:00.000Z",
"allDay": false,
"status": "scheduled"
},
{
"start": "2026-12-09T14:00:00.000Z",
"end": "2026-12-09T14:45:00.000Z",
"allDay": false,
"status": "scheduled"
},
{
"start": "2026-12-23T14:00:00.000Z",
"end": "2026-12-23T14:45:00.000Z",
"allDay": false,
"status": "scheduled"
}
],
"upcomingCount": 4
},
"where": {
"displayText": "Main Library, 310 North Tryon Street, Charlotte, NC 28202",
"venue": {
"name": "Main Library"
},
"address": {
"display": "310 North Tryon Street, Charlotte, North Carolina 28202, United States",
"street": "310 North Tryon Street",
"city": "Charlotte",
"region": "North Carolina",
"postcode": "28202",
"country": "United States",
"countryCode": "US"
},
"geo": {
"lat": 35.2271,
"lng": -80.8431,
"precision": "address"
}
},
"links": {
"best": {
"url": "https://www.cmlibrary.org/events/toddler-story-time",
"kind": "event_page",
"official": true,
"relation": "confirmed",
"publisher": {
"name": "Charlotte Mecklenburg Library",
"domain": "cmlibrary.org",
"platform": "web",
"role": "organizer",
"roleConfidence": "verified"
},
"publishedAt": "2026-10-01T12:00:00.000Z",
"reason": "official_event_page"
},
"all": [
{
"url": "https://www.cmlibrary.org/events/toddler-story-time",
"kind": "event_page",
"official": true,
"relation": "confirmed",
"publisher": {
"name": "Charlotte Mecklenburg Library",
"domain": "cmlibrary.org",
"platform": "web",
"role": "organizer",
"roleConfidence": "verified"
},
"publishedAt": "2026-10-01T12:00:00.000Z"
}
]
},
"media": {
"cover": {
"url": "https://example.r2.cloudflarestorage.com/media/2026-10/abc.jpg?X-Amz-Signature=...",
"expiresAt": "2026-10-28T12:00:00.000Z",
"usage": "cover_eligible",
"kind": "flyer",
"width": 1080,
"height": 1350,
"source": {
"imageUrl": "https://www.cmlibrary.org/sites/default/files/story-time.jpg",
"pageUrl": "https://www.cmlibrary.org/events/toddler-story-time",
"publisher": {
"name": "Charlotte Mecklenburg Library",
"domain": "cmlibrary.org",
"platform": "web",
"role": "organizer",
"roleConfidence": "verified"
}
}
},
"images": [
{
"url": "https://example.r2.cloudflarestorage.com/media/2026-10/abc.jpg?X-Amz-Signature=...",
"expiresAt": "2026-10-28T12:00:00.000Z",
"usage": "cover_eligible",
"kind": "flyer",
"width": 1080,
"height": 1350,
"source": {
"imageUrl": "https://www.cmlibrary.org/sites/default/files/story-time.jpg",
"pageUrl": "https://www.cmlibrary.org/events/toddler-story-time",
"publisher": {
"name": "Charlotte Mecklenburg Library",
"domain": "cmlibrary.org",
"platform": "web",
"role": "organizer",
"roleConfidence": "verified"
}
}
}
]
}
}

See the API reference for every field and filter.

Use Cases​

Event Discovery Platform​

Build comprehensive event listings with a feed that aggregates events from multiple venue websites and keeps to your city's area. You then retrieve all city events through a single API endpoint.

Community Calendar​

Aggregate local community events by fetching events from your feed, filtering for upcoming occurrences, and sorting by start date.

Tourism and Travel​

Aggregate events for travel planning by fetching events in a destination and grouping them by date for easy itinerary creation.

Venue Management​

Monitor competitors or industry events with feeds that track competitor venue schedules, allowing you to stay informed about industry trends and competitor activities.

Supported Source Types​

A feed's sources are listed, enabled, disabled and removed through the API (see Sources). You add websites yourself; our team adds the other types on request. Helix supports the following source types:

Website Sources​

Monitor an entire domain for event pages. Add one with POST /feeds/events/{feedId}/sources and { "type": "site", "url": "https://www.carolinatheatre.org/events" }: the whole site is added, whatever the path.

Use when:

  • You want to track all events published by a venue or organization
  • The site has clear, dedicated event pages
  • You don't need to limit monitoring to a specific page or section

Helix crawls the domain to discover event pages and extracts structured event data (dates, times, locations) as new pages are published.

Sitemap Sources​

Track a specific XML sitemap for event URLs.

Use when:

  • The site publishes a sitemap listing event pages
  • You want faster, more targeted event discovery than a full-site crawl

Helix monitors the sitemap for new URLs and extracts event data from the pages it references.

Index Page Sources​

Watch a calendar or events listing page.

Use when:

  • The site organizes events on a dedicated calendar or listing page
  • You want focused monitoring of that page instead of the whole domain

Helix monitors the index page for links to individual event pages and processes new events as they're added to the listing.

Instagram Sources​

Monitor an Instagram account for event announcements.

Helix watches the account's posts and reels for event announcements and extracts structured event data (dates, times, locations) when found.

Facebook Sources​

Track events from Facebook pages.

Helix monitors the Facebook page's published events and extracts structured event data as new events are posted.

To add a listing page, a sitemap or a social account to your feed, contact Helix support.

Feed Management​

Enabling and Disabling Feeds​

Temporarily pause all monitoring without deleting the feed:

# Disable a feed
curl -X PATCH https://api.feeds.onhelix.ai/feeds/events/{feedId} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'

# Re-enable later
curl -X PATCH https://api.feeds.onhelix.ai/feeds/events/{feedId} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'

A new feed starts disabled: POST /feeds/events with enabled: true is refused with 422 and creates nothing. Add its sources and at least one include filter, then enable it with PATCH; enabling a feed that has no include filter is a 422 too.

When disabled, the feed stops monitoring for new events and takes none in. When you enable a feed, it receives the events each enabled source brought in during the past 14 days, once per source. Re-enabling a feed you disabled resumes monitoring; sources it already received the past 14 days of are not brought in again, so events published while it was disabled are not added, while a source added while it was disabled is brought in.

Which Events a Feed Carries​

Each feed decides for itself which events it carries, and you set it up through the API. Processors answer questions about every event, such as whether it is in your area (places and circles, anywhere in the world), how complete its details are, or whether it fits a topic you describe. Filters on the feed include or exclude events on those answers: an event is in the feed when no exclude filter matches and at least one include filter does. Your own include widens the feed: it lets in what it matches, alongside what the other includes let in. You can write your own filters, add our opt-in filters, or both.

A safety floor applies to every feed and cannot be switched off: it excludes events flagged as unsafe. It checks the event's text (its title and description) and the images the event serves (up to six, the cover first), each image on its own. An image check has two possible outcomes:

  • An image our moderation does not allow is not served. It leaves the event's media, and the cover and gallery are chosen again from the other images. The event itself stays in your feed, judged on its text and the images that remain. An image that cannot be read, or that our moderation repeatedly refuses to check, is treated the same way.
  • A locked category keeps the event out of every feed. Graphic violence in an image, explicit sexual content in an image, and sexual content involving minors in the text lock the event. It stays out of every feed until our team reviews it and clears the lock. An image that locks the event is also not served, and stays off after the lock is cleared unless our team allows that image.

An event whose image is no longer served is sent as event.item.updated (with media in changedFields), and an event that is locked is sent as event.item.removed.

Every new event feed also starts with the completeness opt-in filter, which excludes events with too little detail to be useful; such an event appears in the feed once its details become complete enough. Remove it if your feed should not have it. An event that stops passing is removed from the feed and an event.item.removed is sent for it.

A change to a feed's filters or processors applies going forward only: to new events, and to events already in the feed when they next change.

Labels, category and checks​

Beyond the safety floor and completeness, a feed's filters can read more answers about each event, from our built-in processors (see Processors). The answers are read by filters only: they are not part of feed items.

  • Labels. Eleven yes/no judgements, each with a confidence: adult content, age restricted, promotional, not an occasion, virtual only, fundraiser, religious service, political campaign, civic and government, business and professional, and family friendly. A filter excludes (or includes) on a label once its confidence reaches a cut-off. You choose the cut-off in your own filters. The cut-offs of our opt-in filters are set from our measurements on real events and approved by our team; a label we have not yet seen often enough on real events to measure has no opt-in filter.
  • Category. One of 17 categories (music, performing arts, visual arts, film, food and drink, markets and fairs, festivals, sports and recreation, fitness and wellness, family and kids, education and talks, community and volunteering, civic and government, nightlife, business and networking, religious and spiritual, other), with an optional second category. A feed can include or exclude by category.
  • Three checks that need no model. Whether the event serves a cover image, whether it has an official source (the page we found the event on, or another page confirming the same event, published by the event's organizer, venue, performer or ticket seller; a page that only mentions the event does not count), and whether it is free or paid (or unknown, when no price is shown).

Labels and the category are judged from the event's text and, where the model they run on supports images, its cover image. See Concepts.

The "Community events" set​

For a feed of local community events, add the Community events set of opt-in filters (POST /feeds/events/{feedId}/filter-sets/community_events). It adds:

  • the completeness exclude (the safety floor is always there);
  • exclusions for age restricted, promotional and not-an-occasion events, each at its own cut-off;
  • the "In the area" include: the event is in the feed when it is in your area, by place (an area match processor you pass as areaMatch) or, if you pass an area relevance processor, by the event's own text. When you also pass a relevance processor, the event must pass it too, and that processor leaves geography to the area.

Members your feed already has are skipped. Each one added is an ordinary opt-in filter you can remove on its own. The category is not part of the set: write your own filter to filter on it. See Opt-in filters for the conditions and cut-offs.

Event Delivery​

Get notified in real time when events in your feed change, instead of polling for changes.

Event types:

  • event.item.added: an event entered your feed
  • event.item.updated: something you can see in the item changed; changedFields (title, description, when, where, links, status, media) is a hint, so fetch the item again on every update
  • event.item.removed: an event left your feed, or the feed was deleted

Payloads carry ids (feedId, the item id and eventId; an update adds changedFields; a removal carries feedId and eventId). Fetch the item with GET /feeds/events/{feedId}/items/{itemId} for its current data. See Event feed changes for when each is sent.

Having an event feed does not, by itself, cause anything to be delivered. Event Delivery only sends an event to a destination that has a subscription matching this feed — you register the destination once, then subscribe it to the feeds and event types you care about. See Event Delivery: Two objects, not one for details.

To receive only this feed's events, pin it in the subscription with "feedType": "events":

curl -X POST https://api.feeds.onhelix.ai/events/destinations/{destinationRef}/subscriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"eventTypes": ["event.*"],
"scopeKind": "feeds",
"feeds": [{ "feedType": "events", "feedId": "{feedId}" }]
}'

See the Event Delivery quickstart to set up a destination and verify its signatures.

Next Steps​

Need Help?​

Contact Helix Support to:

  • Add listing pages, sitemaps or social accounts to your feeds (the API adds websites)
  • Get help choosing processors and filters for your feed