RSS Triggers
Poll HTTP(S) feeds and deliver each item once to a workflow or Command Center.
An RSS trigger polls a feed URL on an interval and enqueues each new item through the same
durable trigger outbox used by mailer. Destinations are workflow, command, or both.
Create and update
In the workflow editor, choose a destination, open Manage versions, and select Add event source → RSS feed. Enter its URL and polling interval. An off destination stays off; adding a feed to an on destination can immediately trigger its currently approved version.
POST /api/v1/rss-triggers requires a workspace API key and an http:// or https:// feedUrl.
destination defaults to workflow. Workflow destinations require a workflowId in the same
workspace.
Add executionTargetId to bind the feed to Production or a named preview of that workflow.
Creating a preview does not copy a feed or its cursor. A configured feed starts polling when
its destination is published and stops when that destination is switched off.
The store upserts on (workspaceId, feedUrl, workflowId, executionTargetId). A later POST with the same key
updates interval, destination, or enabled instead of creating a second row.
PATCH /api/v1/rss-triggers/{id} can change intervalSeconds, enabled, and destination. It
does not change feedUrl or workflowId. Enabling a workflow destination re-validates the stored
workflow.
There is no delete endpoint on /api/v1/rss-triggers. Disable the trigger (enabled: false) to
stop polling.
Default interval is 900 seconds. Allowed range is 60–86400. List pagination uses
cursor / limit (default 25, max 100) and returns nextCursor.
Polling and delivery also require principalEnabled on the trigger record.
Polling
The platform scheduler claims due triggers (30-minute lease, concurrency 4) and calls
pollRssTrigger.
The fetch uses the research egress profile, a 30-second timeout, and
Accept: application/rss+xml, application/atom+xml, application/xml, text/xml. Stored etag and
lastModified are sent as If-None-Match / If-Modified-Since. HTTP 304 advances
nextPollAt and delivers nothing.
The body is limited to 2 MB (declared Content-Length or streamed bytes). Larger feeds fail
and record lastError. Non-OK HTTP statuses fail as RSS feed returned HTTP {status}..
The parser accepts RSS <item> and Atom <entry> blocks. externalId is guid, then id, then
link, then a SHA-256 of the block. Title, link, summary, and publishedAt are taken from the
usual RSS/Atom tags.
Deduplication and errors
Each item is reserved as (triggerId, externalId) plus a SHA-256 of the parsed item JSON.
| Claim | Behavior |
|---|---|
completed | Skip; already delivered |
in_progress | Skip this cycle; do not advance ETag / Last-Modified |
claimed | Dispatch, then completeDelivery |
A target-bound dispatch failure retains the accepted item and its activation for outbox recovery;
a later deployment cannot retarget that item. Legacy deliveries without an activation release
the reservation so the next poll can retry. The trigger poll then
fails, writes lastError, and still advances nextPollAt. A successful poll clears lastError
and stores the response validators unless an in-progress delivery was seen.
Delivery identity is the item externalId (typically the GUID). The same GUID is delivered at
most once after completeDelivery.
Status fields
Serialized triggers include etag, lastModified, nextPollAt, lastPolledAt, lastError,
enabled, principalEnabled, executionTargetId, and targetEnabled. lastError is the last poll failure message, or null after a
successful poll update.
The workflow destination panel lists its feeds. Publication warns when an enabled sibling destination polls the same feed; deduplication applies within each destination, so both can act on the same item when both are on.
