Overview
The RSS Subscriptions API allows you to subscribe channels to RSS or Atom feeds. New feed items are automatically posted to the subscribed channel at regular intervals.
Hazel Chat polls feeds periodically and posts new items as messages. Each subscription tracks the last fetched item to avoid duplicates.
Subscribe a channel to an RSS or Atom feed.
Channel to receive feed items
URL of the RSS or Atom feed
How often to check the feed for new items (in minutes)
The created subscription Unique subscription identifier
Channel receiving feed items
Organization that owns this subscription
Feed title (auto-detected from feed)
Feed icon URL (auto-detected from feed)
Last time the feed was successfully fetched
Publication date of the last item posted
GUID of the last item posted (to detect duplicates)
Number of consecutive fetch errors (resets on success)
Last error message if fetching failed
Whether subscription is active
Polling interval in minutes
User who created the subscription
Transaction ID for optimistic updates
Errors:
ChannelNotFoundError - Channel doesn’t exist
RssSubscriptionExistsError - Channel is already subscribed to this feed
RssFeedValidationError - Feed URL is invalid or feed cannot be parsed
UnauthorizedError - User is not authorized
InternalServerError - Server error
Example
Default Polling Interval
const result = await client . rpc ( "rssSubscription.create" , {
channelId: "channel_123" ,
feedUrl: "https://blog.example.com/feed.xml" ,
pollingIntervalMinutes: 30 // Check every 30 minutes
})
console . log ( "Subscribed to:" , result . data . feedTitle )
console . log ( "Polling every:" , result . data . pollingIntervalMinutes , "minutes" )
List all RSS subscriptions for a specific channel.
Array of subscriptions for the channel
Errors:
ChannelNotFoundError - Channel doesn’t exist
UnauthorizedError - User is not authorized
InternalServerError - Server error
const result = await client . rpc ( "rssSubscription.list" , {
channelId: "channel_123"
})
for ( const sub of result . data ) {
console . log ( `Feed: ${ sub . feedTitle || sub . feedUrl } ` )
console . log ( `Status: ${ sub . isEnabled ? "Active" : "Disabled" } ` )
if ( sub . consecutiveErrors > 0 ) {
console . log ( `⚠️ ${ sub . consecutiveErrors } consecutive errors` )
}
}
List all RSS subscriptions across all channels in your organization.
Array of all subscriptions in the organization
Errors:
UnauthorizedError - User is not authenticated
InternalServerError - Server error
const result = await client . rpc ( "rssSubscription.listByOrganization" , {})
console . log ( `Total RSS subscriptions: ${ result . data . length } ` )
// Find feeds with errors
const failing = result . data . filter ( s => s . consecutiveErrors > 3 )
console . log ( `Feeds with errors: ${ failing . length } ` )
for ( const sub of failing ) {
console . log ( `❌ ${ sub . feedUrl } : ${ sub . lastErrorMessage } ` )
}
Update an RSS subscription’s settings.
id
RssSubscriptionId
required
Subscription identifier
Enable or disable the subscription
New polling interval in minutes
Updated subscription object
Transaction ID for optimistic updates
Errors:
RssSubscriptionNotFoundError - Subscription doesn’t exist
UnauthorizedError - User is not authorized
InternalServerError - Server error
Temporarily Disable
Change Polling Interval
Re-enable After Errors
await client . rpc ( "rssSubscription.update" , {
id: "rsssub_abc123" ,
isEnabled: false
})
console . log ( "Feed temporarily paused" )
Delete an RSS subscription (soft delete). The channel will stop receiving feed items.
id
RssSubscriptionId
required
Subscription identifier
Transaction ID for optimistic updates
Errors:
RssSubscriptionNotFoundError - Subscription doesn’t exist
UnauthorizedError - User is not authorized
InternalServerError - Server error
await client . rpc ( "rssSubscription.delete" , {
id: "rsssub_abc123"
})
console . log ( "RSS subscription removed" )
Polling Behavior
How Polling Works
Hazel Chat fetches the feed at the specified interval
Compares new items against lastItemGuid to detect duplicates
Posts new items to the channel
Updates lastFetchedAt and lastItemPublishedAt
On error, increments consecutiveErrors and stores error message
Error Handling
When a feed fails to fetch:
consecutiveErrors is incremented
lastErrorMessage and lastErrorAt are updated
Polling continues at the same interval
When fetch succeeds, consecutiveErrors resets to 0
const result = await client . rpc ( "rssSubscription.list" , {
channelId: "channel_123"
})
for ( const sub of result . data ) {
if ( sub . consecutiveErrors >= 5 ) {
console . log ( `⚠️ Feed may be broken: ${ sub . feedUrl } ` )
console . log ( `Last error: ${ sub . lastErrorMessage } ` )
console . log ( `Failed since: ${ sub . lastErrorAt } ` )
// Consider disabling the subscription
await client . rpc ( "rssSubscription.update" , {
id: sub . id ,
isEnabled: false
})
}
}
Recommended Polling Intervals
High-Frequency Feeds (News, Social)
Blog Feeds
Low-Frequency Feeds (Releases, Announcements)
// Check every 5-15 minutes
await client . rpc ( "rssSubscription.create" , {
channelId: "news_channel" ,
feedUrl: "https://news.ycombinator.com/rss" ,
pollingIntervalMinutes: 10
})
Example: Multi-Feed News Channel
Subscribe to Multiple Sources
const newsFeeds = [
{ url: "https://news.ycombinator.com/rss" , interval: 15 },
{ url: "https://lobste.rs/rss" , interval: 30 },
{ url: "https://www.reddit.com/r/programming/.rss" , interval: 20 },
{ url: "https://thenewstack.io/feed/" , interval: 60 }
]
const channelId = "tech_news_channel"
for ( const feed of newsFeeds ) {
try {
await client . rpc ( "rssSubscription.create" , {
channelId ,
feedUrl: feed . url ,
pollingIntervalMinutes: feed . interval
})
console . log ( `✓ Subscribed to ${ feed . url } ` )
} catch ( error ) {
if ( error . _tag === "RssFeedValidationError" ) {
console . error ( `✗ Invalid feed: ${ feed . url } ` , error . message )
} else if ( error . _tag === "RssSubscriptionExistsError" ) {
console . log ( `- Already subscribed: ${ feed . url } ` )
} else {
throw error
}
}
}