Skip to headlines
NEWZ
Scroll

Developers

Rwandan headlines, one endpoint

Every story NEWZ aggregates, available as JSON. Free, no key, no sign-up — just a rate limit and an expectation that you credit the newsroom that did the work.

curl https://api.newz.dushv.dev/v1/articles?limit=3

Quick start

The API is read-only and needs no authentication. Everything lives under /v1, which is versioned and stable — new fields may appear, but existing ones will not change type or vanish without a new version.

Latest ten Kinyarwanda headlines

curl "https://api.newz.dushv.dev/v1/articles?language=rw&limit=10"

The unversioned endpoints this site uses internally are not part of the contract and will change without notice. Build on /v1.

Rate limits

60 requests per 60 seconds, per IP. Every response tells you where you stand, so you can slow down before you are cut off.

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1787734140

Exceed it and you get a 429 with how long to wait:

{
  "error": "rate_limited",
  "message": "Too many requests. The limit is 60 per 60s.",
  "retryAfterSeconds": 48
}

Ingestion runs every 20 minutes, so polling faster than that returns the same stories. Cache on your side and the limit will never trouble you.

Articles

GET/v1/articles

The fresh feed, newest first. Only stories inside the freshness window.

ParameterTypeNotes
categorystringnational, world, politics, economy, sports, entertainment, health, tech, opinion…
languagestringen, rw, fr, sw
outletstringExact outlet name, e.g. KT Press
limitintDefault 30, maximum 100
cursorstringFrom nextCursor — see pagination

Response

{
  "items": [
    {
      "id": "b1f0…",
      "url": "https://igihe.com/amakuru/article/…",
      "title": "…",
      "excerpt": "…",
      "imageUrl": "https://igihe.com/IMG/…jpg",
      "outlet": "Igihe",
      "sourceKey": "igihe_rw",
      "category": "national",
      "language": "rw",
      "publishedAt": "2026-08-26T09:47:06.000Z",
      "isVideo": false,
      "videoId": null
    }
  ],
  "nextCursor": "MjAyNi0wOC0yNlQwOTo0Nzow…",
  "freshnessWindowHours": 48
}

GET/v1/articles/:id

A single article. Returns 404 with {"error":"not_found"} if it does not exist or has aged out of the window.

Sources

GET/v1/sources

The outlets being aggregated and what each publishes — useful for building a filter. Operational detail such as health and scraper configuration stays internal.

{
  "items": [
    { "key": "ktpress_national", "outlet": "KT Press",
      "language": "en", "category": "national", "kind": "rss" }
  ]
}

Pagination

Keyset, not offset, so a page cannot shift under you when new stories arrive mid-scroll. Pass back the nextCursor you were given; null means you have reached the end.

curl "https://api.newz.dushv.dev/v1/articles?limit=50"
curl "https://api.newz.dushv.dev/v1/articles?limit=50&cursor=MjAyNi0wOC0yNlQ…"

Using the data

NEWZ aggregates; it does not license. Every headline, excerpt and image belongs to the newsroom that published it, so two things are not optional:

  • Attribute each item to its outlet.
  • Link to its url, so readers reach the original.

Excerpts identify a story; they are not the article and must not be presented as one. No endpoint returns article text — we have no right to give it to you. Bulk mirroring and reselling are not permitted; see the terms.