Skip to content
unzoi docs

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)"'
outletscountReading
3541Independently covered. A real story.
340One wire story or press release, syndicated. High volume, no independent interest.
22Early 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. outlets counts 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_negative means the language is that of financial distress, not that the article disapproves.
  • Totals from a ranked query. total_relation: approximate means 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.