Home · Docs · Endpoints · archive/trends
archive/trends — the history of a niche, grouped by item
Hourly readings the archive already recorded, replayed for any interval you ask for. The endpoint that answers questions about the past rather than about now.
This is archive data, and that is the point. A live platform API can tell you what is happening now. It cannot tell you what was happening last Tuesday, because it does not keep a record. We wrote down every hour, which is why this endpoint can answer a question about the past at all.
The call
| Path | GET /api/v1/trends/{niche} |
|---|---|
| Catalogue id | archive/trends |
| Cost | 1 credit per call. A call that finds nothing is charged all the same. |
| Key | Required — Authorization: Bearer hk_live_... |
Parameters (4)
| Name | In | Required |
|---|---|---|
niche | path | yes |
from | query | no |
to | query | no |
limit | query | no |
That list is the whole list, and anything else is ignored in silence. An undeclared parameter is not rejected — it produces no error, no warning and no filtering. Check a parameter against this table before assuming a narrower result came back.
What the parameter list does not tell you
This is the endpoint that cannot be replicated by calling a platform API. Hacker News will tell you its front page right now; it will not tell you its front page on 18 September, because it does not keep one. We wrote down every hour, so the question 'what was happening then' has an answer here and nowhere upstream.
GROUPED BY ITEM, NOT BY WINDOW, and that shape is the whole design. A window is how the archive stores — one row per item per hour. An item carrying its own series is how the question gets asked: you want the trajectory of a thing, not a stack of unrelated snapshots. The regrouping happens in the database so you never have to stitch windows together yourself.
`movement` on each item is oldest position minus newest, and positive means it climbed. Read it together with `points` in the series, never alone: a change of position with no change in points is a tie reshuffle, not a trend, and ties are the rule rather than the exception in these rankings.
`left_at` is null while an item is still in the ranking. That null is not a missing value — it is the item not having left yet, which is a fact, and the reason the field is not an empty string or a zero date.
Measured caveats (3)
A nonexistent niche is not a 404 — and it spends the call
Nothing validates the niche name. A typo returns `items: []` with `points: 0` and HTTP 200, AND still spends a call, because the quota counter increments before the archive is read. An empty answer therefore means one of two different things — the niche is quiet, or the niche does not exist — and the response does not distinguish them. This is why step 1 of every recipe here resolves names at `/api/v1/nichos` first: that endpoint is free and needs no key, so the check costs nothing.
Source: The `/api/v1/trends/{niche}` description in the served `/openapi.json`.
An unknown parameter is ignored in silence
`/trends` declares exactly four inputs: `niche`, `from`, `to` and `limit`. Anything else is not rejected — it is ignored. A `?platform=hackernews` produces no error, no warning and no filtering: you get the unfiltered answer and nothing tells you the filter did not apply. Check the parameter against the list before assuming a narrower result.
Source: The declared parameter list in `lib/rotas-da-api.js` and the published `/openapi.json`.
The series is capped, and says when it was cut
`/trends` is capped at 5000 series points and a 90-day span, both enforced in the database. When a cap is hit, `truncated` is true and the series is incomplete — narrow the interval rather than drawing conclusions from a partial series. `limit` is a hint only: the hard cap lives in the database and a larger value does not raise it.
Source: The `/api/v1/trends/{niche}` description in the served `/openapi.json`.
Real responses
Captured, not composed. 1 response we could actually make from this machine:
$ curl "https://honesthook.com/api/v1/trends/ai-agents?hours=168"
{"error":"chave_ausente"}
HTTP 401Why there is no success body on this page
The 200 body for this endpoint is not transcribed here. Reading it needs a client key, and there is no client key on the machine these pages were built from — internal keys exist only as hashes, by design. An example we never received would look exactly like one we did, so instead of composing one, the response shape is documented field by field on the schema pages below. Those are generated from the contract and tested against it in both directions; an invented example would be tested by nothing.
Response shapes (3)
Item— What `archive/trends` returns: an item, when it entered the ranking, when it left, its best position, and the full series of hourly readings behind it.SeriesPoint— A single reading in an item's series: where it sat, how many points it had, how many comments. The archive keeps one of these per item per hour and never deletes them.ApiError— Every 4xx and 5xx from the API carries this object. The `error` value is a stable string you can branch on; the extra fields appear only for the errors that have something to report.
Error codes (8)
Every one of them carries the same body shape: ApiError. The error value is a stable string you can branch on — branch on that, never on the message text.
400 · 401 · 402 · 404 · 405 · 451 · 503 · 502
Machine-readable
This endpoint is in /openapi.json (OpenAPI 3.1), with its cost on the operation itself. If you are generating a client, use the spec rather than this page — and note that the spec is filtered by what is switched on right now, so it is the better answer to "can I call this today".
The other 6 endpoint pages
archive/movers · archive/coverage · profile/history · youtube/channel · pinterest/boards · bluesky/post