Evaluating coverage
"Was this covered?" is a different question from "what happened?", and it is answered with counts rather than with articles.
Volume is not attention
A search returning 400 articles tells you almost nothing. It could be 400 outlets independently covering something,
or it could be one press release republished 400 times. /stories separates
them:
curl -s -G "https://api.unzoi.com/stories" -H "x-api-key: $UNZOI_KEY" \
--data-urlencode "q=battery plant announcement" \
--data-urlencode "from=2026-08-01" \
--data-urlencode "limit=20" \
| jq -r '.stories[] | "\(.outlets)\t\(.count)\t\(.title)"' | outlets | count | Reading |
|---|---|---|
| 35 | 41 | Independently covered. A real story. |
| 3 | 40 | One wire story or press release, syndicated. High volume, no independent interest. |
| 2 | 2 | Early or niche. Check again tomorrow before drawing a conclusion. |
The outlets/count ratio is the most useful single number this API gives you for judging
attention, and a plain article search discards it entirely.
Who covered it
Facets count over the whole match set, not the page — so one request tells you the shape of the coverage:
curl -s -G "https://api.unzoi.com/search" -H "x-api-key: $UNZOI_KEY" \
--data-urlencode "q=battery plant announcement" \
--data-urlencode "from=2026-08-01" \
--data-urlencode "facets=source,publisher_country,language" \
--data-urlencode "facet_limit=20" \
--data-urlencode "limit=1" \
| jq '.facets | map_values([.values[] | "\(.value): \(.count)"])' limit=1 because you want the counts, not the articles. One billed request either way, and this way you
are not paying context for results you will discard.
Coverage over time
There is no aggregation endpoint. Ask per window — which is also faster and likelier to succeed than one wide query:
for day in $(seq 13 -1 0); do
d=$(date -u -d "$day days ago" +%Y-%m-%d)
n=$(curl -s -G "https://api.unzoi.com/stories" -H "x-api-key: $UNZOI_KEY" \
--data-urlencode "q=port congestion" \
--data-urlencode "from=$d" --data-urlencode "to=$d" \
--data-urlencode "limit=1" | jq -r '.total')
printf '%s %s\n' "$d" "$(printf '%*s' "$n" '' | tr ' ' '#')"
done Fourteen requests for a fortnight's series. Count stories rather than articles: an article series inflates the same event, and it is events you are plotting.
Did the framing differ?
This is the question clustering cannot answer — you need the articles, split by who published them. Expand one cluster and facet it:
# The articles in one story, by publisher country.
curl -s -G "https://api.unzoi.com/search" -H "x-api-key: $UNZOI_KEY" \
--data-urlencode "story_id=s-9f2c" \
--data-urlencode "facets=publisher_country,language" \
--data-urlencode "limit=50"
Then compare titles across the groups. The signal values on each article give
you a second axis — the same event covered with markedly different financial_uncertainty or
conflict intensity is a framing difference you can point at rather than assert.
What you cannot conclude
- Absence of coverage. Zero results may be a wrong filter value, a
plan-clamped window, or a language you did not include. Check
from_clamped, and re-run without filters, before saying "nobody covered this". - Reach.
outletscounts publishers, not readers. A story in three major nationals may reach more people than one in thirty local sites. - Sentiment. Signals measure register, not approval. A high
financial_negativemeans the language is that of financial distress, not that the article disapproves. - Totals from a ranked query.
total_relation: approximatemeans the number is a candidate count. Use a keyword query if the figure needs to be defensible.
A repeatable check
# One question, three numbers: events, articles, independent outlets.
q="grid outage"; from="2026-08-01"
stories=$(curl -s -G "https://api.unzoi.com/stories" -H "x-api-key: $UNZOI_KEY" \
--data-urlencode "q=$q" --data-urlencode "from=$from" --data-urlencode "limit=100")
echo "events: $(echo "$stories" | jq -r '.total')"
echo "articles: $(echo "$stories" | jq '[.stories[].count] | add')"
echo "outlets: $(echo "$stories" | jq '[.stories[].sources[]] | unique | length')" Three numbers, one request. Enough to say whether something was covered, and how widely.