News Reader Open News

News Reader API

Three endpoints, served by every News Reader installation – JSON for Collector and articles, an encrypted binary blob for sync. No API key. Errors come back as {"error":{"code","message"}}.

Collector

Any website or feed URL → normalized entries. Works for sites without an RSS feed, too.

GET /api/collect?url=https://example.com/blog[&limit=1..100][&refresh=1]
{
  "source":  { "url": "…", "type": "rss", "strategy": "discovered", "feedUrl": "…", "title": "…", "siteUrl": "…", "icon": "…" },
  "entries": [ { "id": "…", "url": "…", "title": "…", "publishedAt": "…", "updatedAt": "…", "summary": "…", "image": "…", "author": "…" } ],
  "meta":    { "count": 20, "cached": true, "nextRefreshAfter": "…" }
}

limit defaults to 100. refresh=1 bypasses the cache once it is older than 15 minutes. The cache is shared per source: every address that leads to the same feed (or page) uses one copy. The scheme defaults to https://.

If the source turns the server away (UPSTREAM_HTTP_ERROR with upstreamStatus 401/403), the error lists clientTry: addresses a browser may fetch itself (the site often still allows it via CORS, e.g. the WordPress REST API). Post the body you got to have it parsed – for you only, nothing is cached:

POST /api/collect?url=https://example.com/&from=<one of clientTry>   (body: the raw response, max. 1 MB)

Article

A readable copy of one article, e.g. for offline reading. With feed and id, a full text the feed already carries is served without fetching the page.

GET /api/article?url=https://example.com/blog/post[&feed=<feed url>&id=<entry id>]
{ "article": { "url": "…", "title": "…", "byline": "…", "content": "<p>…</p>", "words": 812, "partial": false } }

Status codes

Sync

Stores one end-to-end encrypted blob per vault (one group of paired devices). The server never sees the key.

Authorization: Bearer <token>
GET    /api/sync   → blob + ETag (304 with If-None-Match, 404 if none)
PUT    /api/sync   If-Match: "<etag>" or If-None-Match: *   (412 conflict, 410 forwarded)
DELETE /api/sync   → 204

Full details: README on GitHub.