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
- Sources: You add websites to your feed through the API; our team adds listing pages, sitemaps and social accounts on request (see Sources)
- 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
- Continuous monitoring: Sources are continuously monitored for new events
- Event extraction: Events are automatically extracted with dates, times, and locations
- 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.
| Field | Description |
|---|---|
id | Feed-item identifier (per feed). Use it for feedback and per-feed dedup. |
eventId | Underlying event identifier. The same event in two feeds has different ids but the same eventId. |
addedToFeedAt | When the event was added to this feed |
updatedAt | When the item last changed in a way subscribers are notified of |
status | active, or cancelled when the whole event was cancelled |
title | Event title |
description | Event description |
shortDescription | One-sentence summary (omitted when none) |
completeness | { score, missing[] }: how complete the data is (omitted for events not yet scored) |
when | Schedule: pattern, timezone, displayText, recurrence, next, occurrences[], upcomingCount |
where | Location: 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 feedevent.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 updateevent.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
- Quickstart Guide: Build a feed end to end
- Feed Configuration: Processors, filters, opt-in filters, areas and sources
- API Reference: Complete endpoint documentation
- Event Delivery: Configure destinations and subscriptions to receive events in real time
- Authentication: API key management and best practices
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