Recipes / Follow one story as coverage accumulates
Follow one story as coverage accumulates
/stories in hybrid mode. This page is the
operational half — what comes back, how it breaks, and what running it for real takes.
The request
GET /stories
?q=<topic>
&mode=hybrid
&from=<last poll timestamp>
# then, for the story you care about:
GET /stories/<id>?limit=1 As a call you can paste:
curl -s -G "https://api.unzoi.com/stories" \
-H "x-api-key: $UNZOI_KEY" \
--data-urlencode "q=<topic>" \
--data-urlencode "mode=hybrid" \
--data-urlencode "from=<last poll timestamp>"
For an agent rather than a script, the same query is the list_stories
MCP tool with these as its arguments.
Parameters used here
What comes back
From the topic poll, new stories only. From /stories/{id}, the story as it stands now: count, outlets, every source, first_seen and last_seen, and what it is about. Watching outlets grow between polls is the useful signal: a story that keeps acquiring outlets after the first hour is behaving differently from one that was picked up widely and immediately, and the second is usually just distribution. last_seen tells you whether it is still moving at all.
Field by field: the /stories response reference.
How this goes wrong
Re-running the full query each poll and diffing on headline. Editions rewrite headlines, so the diff reports the same story as new repeatedly, and the alert channel becomes noise. Diff on the story identifier.
Adapting it
The same approach works for tracking an ongoing situation rather than a single event: poll the topic query for new stories, then track the ones that matter by identifier. For a story that splits into several — a company announcement that becomes a regulatory story and a labour story — expect new identifiers rather than growth in the original, and treat that divergence as signal.
Running it for real
Store the last-seen timestamp per query, not globally, or a slow query will suppress a fast one. Keep the story identifier alongside whatever you persist so that a later re-poll can be reconciled without re-fetching. If coverage stops growing for a full day the story is usually over; continuing to poll it indefinitely is the most common source of wasted request budget in this pattern.
Related recipes
- Build a morning digest someone will actually read
- Track a brand across every language you don't read
Why this approach
The case for these parameters over the obvious alternatives — and when this recipe is the wrong tool entirely — is on the recipe's page on unzoi.com. It is kept there rather than repeated here, so the argument and the operations cannot drift apart.