Skip to content
unzoi docs
Search and navigation
Start here
REST API
MCP
Limits and plans
Agent clients
SDKs
Guides

Time windows

from and to are the two parameters that most change how long a request takes and what it returns. Everything else is a filter.

Format

Both accept 2026-07-09 or 20260709120000, and any digit grouping in between. They are normalised to 14-digit YYYYMMDDHHMMSS in UTC, with from padded to the start of the period you named and to to the end:

You sendIt means
from=2026-07-0920260709000000
to=2026-07-0920260709235959
from=2026-0720260701000000
to=2026-0720260731235959

So from=2026-07-09&to=2026-07-09 is that whole day, which is almost always what you meant.

Why omitting from is expensive

The corpus is partitioned by time, and each partition is served independently — that is what lets the archive be enormous without every query paying for its size. A query is routed only to the partitions its range overlaps.

Relevance ranking has no shortcut across those partitions: an article from 2003 can out-score one from this morning, so a ranked query has to visit every partition overlapping its range. With no range, that is all of them.

Your plan bounds it too

Every plan has an archive depth. A from older than yours is pulled forward rather than refused, and the response says so:

{ "history_days": 30, "from_clamped": true, "results": [...] }

from_clamped: true is the difference between "my plan stopped here" and "there is no coverage". Read it — see Archive depth.

Picking a range

QuestionRange
"What is happening?"Omit both, or from = a few hours ago. Use /top-headlines.
"What happened this week?"from = 7 days ago.
"How was this covered when it broke?"A tight window around the event — a day or two.
"How has coverage changed over a year?"Several requests, one per month, rather than one request spanning the year.

That last row is the one people get wrong. A year-long relevance query is slow, may time out, and returns a single ranked list that tells you nothing about change. Twelve monthly queries are faster individually, likelier to succeed, and give you a series:

for month in 01 02 03 04 05 06 07 08; do
  total=$(curl -s -G "https://api.unzoi.com/stories" -H "x-api-key: $UNZOI_KEY" \
    --data-urlencode "q=port congestion" \
    --data-urlencode "from=2026-$month" \
    --data-urlencode "to=2026-$month" \
    --data-urlencode "limit=1" | jq -r '.total')
  echo "2026-$month  $total stories"
done

When a wide query times out

A 408 means the request exceeded the server's own budget while walking partitions. The fix is a narrower window, not a longer client timeout — the work is proportional to the range.

A very wide query may also return 200 with a partial answer, having reached most of its partitions inside the budget. The response says so — partial: true, with coverage set to timed_out (retry, or narrow) or range_too_wide (narrow; retrying will not help). If completeness matters, narrow it so the whole thing fits, and never read a partial answer as a small one. Reading completeness has the values.

Published, not mentioned

from/to filter on publication time. An article published today can be about a date next year — that is what mentioned_date is for, and the two are genuinely different questions.