CLSTR API
Structured "what is happening": ~100k articles/day deduplicated into multi-source events, grouped into situations with memory. 30 to 90 minutes behind the wires by design. Verified shape, not breaking-news speed.
Authentication
Every request needs an API key. Create a free one in Settings (sign in first, no card needed). Send it as a bearer token or an X-Api-Key header.
Authorization: Bearer clstr_YOUR_KEY
Responses allow any origin (Access-Control-Allow-Origin: *) so you can call the API from a browser during development. Keys are secrets: a key shipped inside front-end JavaScript is a key you have published. Call the API from your own server for anything real.
Endpoints
Base URL: https://api.clstr.news/v1
Four read-only endpoints. All responses are JSON: data on success, error.code + error.message on failure, including 404s on unknown paths and server errors. Timestamps are ISO-8601 UTC.
List situations
Top developing situations. Params: limit (1-50, default 20), days (1-30 on Hobby, default 7. The history window per tier is below), sort (relevance | recent), category, country (comma ISO codes), cursor.
curl -s "https://api.clstr.news/v1/situations?days=1&category=international&sort=relevance&limit=5" \ -H "Authorization: Bearer clstr_YOUR_KEY"
Returns: id, slug, title, summary_preview, cluster_count, source_count, first_seen, last_updated, status (ACTIVE | QUIET), category, categories, countries, significance_score, latest_cluster_title, url; plus next_cursor.
Cursor pagination stops after 8 pages: past that, next_cursor comes back null. Narrow with days, category or country rather than paging deeper.
Situation detail + timeline
One situation (by id or slug) with its ordered timeline of member events, newest first. Params: timeline_limit (1-500, default 100), timeline_before (cluster id cursor).
curl -s "https://api.clstr.news/v1/situations/SITUATION_ID_OR_SLUG" \ -H "Authorization: Bearer clstr_YOUR_KEY"
Returns id, slug, title, summary (full), summary_preview, cluster_count, source_count, first_seen, last_updated, status, category, categories, latest_cluster_title, significance_score, url, is_timeline_page (false), timeline[] (id, slug, title, summary, category, countries, significance_score, sources, published_at, updated_at, url), timeline_cursor (has_more, next_before, remaining_count, total_count), day_span. Situation-wide countries is a list-endpoint field only; each timeline entry carries its own.
A timeline_before request is a continuation page: it returns only id, slug, is_timeline_page: true, timeline[] and timeline_cursor. The header fields are deliberately absent rather than zeroed: keep the ones you got from page one instead of overwriting them.
A situation that was merged into another returns the successor with merged_into_shown: true and requested_id set to what you asked for. A retired situation whose successor is an event answers 404 with error.moved_to. A concluded situation whose archive was removed answers 410.
Cluster detail
One event (a cluster of articles from many outlets reporting the same thing), with its source articles.
curl -s "https://api.clstr.news/v1/clusters/CLUSTER_ID_OR_SLUG" \ -H "Authorization: Bearer clstr_YOUR_KEY"
Returns: id, slug, title, summary, summary_full, keywords, category, countries, significance_score, sources, published_at, updated_at, url, articles[] (source_host, url, title, published_at), situation (id, title, slug, cluster_count) or null. A merged-away cluster returns its successor with merged_into_shown: true; a retired one answers 410.
Search
Semantic search over recent events. Params: q (required, max 200 chars), days (1-30, default 7), limit (1-30).
curl -s "https://api.clstr.news/v1/search?q=venezuela%20oil%20sanctions&days=7" \ -H "Authorization: Bearer clstr_YOUR_KEY"
The search index only reaches back 30 days, on every tier. query.days in the response is the window actually searched, not what you asked for.
Limits & pricing
Caps are hard limits: requests past the cap get a 429, and there are no overage charges, ever. Search is capped separately because each search runs an embedding.
| Tier | Price | Requests/day | Requests/min | Searches/day | History window |
|---|---|---|---|---|---|
| Hobby | Free | 500 | 20 | 25 | 30 days |
| Starter | $99/mo | 20,000 | 300 | 2,000 | 90 days |
| Growth | $299/mo | 100,000 | 1,000 | 10,000 | 90 days |
Caps apply per key, and an account may hold up to 5 active keys. The history window is the widest days value a tier can ask for; larger values are clamped, not rejected. Search reaches back at most 30 days on every tier.
Hobby is live today. Paid tiers open soon: if the free caps are in your way, get in touch and we will set you up directly.
Free-tier use must link back to clstr.news when displayed publicly.
Every authenticated response carries X-RateLimit-Limit-Day and X-RateLimit-Remaining-Day (both exposed to browsers via CORS). Responses rejected before authentication (a missing or invalid key) carry neither, because there is no key to report usage for. There is also a generous per-address ceiling in front of authentication; a normal client reaches its own tier cap long before it.
Errors
Every failure is {"error": {"code": "…", "message": "…"}} with a matching HTTP status. Branch on code; message is for humans and may change.
| Status | code | Meaning |
|---|---|---|
| 400 | bad_request | Missing or malformed parameter (e.g. no q on search). |
| 401 | unauthorized | No key, or the key is unknown or revoked. |
| 404 | not_found | Unknown id, slug, or endpoint. May carry moved_to. |
| 410 | gone | The record existed and was retired. Do not retry. |
| 429 | rate_limited | A cap was reached. The message names which one. |
| 500 | internal_error | Our fault. Safe to retry with backoff. |
| 502 | upstream_error | An upstream (embeddings) failed. Retry shortly. |
| 503 | unavailable | Temporarily unavailable. Retry shortly. |
Versioning & stability
v1 is stable: we only add fields, never rename or remove them within v1. Breaking changes get a new version prefix and at least 90 days' notice here and via a Sunset header. Caps are hard limits. No overage charges, ever.
MCP server
The same data is available to AI agents over MCP. See the setup on this page once it ships, or watch the About page for updates.
Questions or a use case the caps don't fit? Contact us.