Skip to main content

Articles and search

Articles are the core resource. Every article belongs to a source, carries a triage state, and can be annotated with highlights and tags.

Listing articles

GET /api/articles

Returns the standard collection envelope.

ParameterTypeNotes
statusstringFilter by workflow status.
statestringFilter by triage state (new, read, saved, skipped, archived).
starredbooleanRestrict to starred articles.
categorystringFilter by category.
tag_idintegerRestrict to articles carrying a tag.
limitinteger1..500, default 100.
offsetinteger>= 0, default 0.

Reading one article

RouteMethodPurpose
/api/articles/{article_id}GETMetadata for a single article.
/api/articles/{article_id}/bodyGETThe extracted article body.
/api/articles/{article_id}/bodyPOSTTrigger or refresh body extraction.
/api/articles/{article_id}/audioPOSTGenerate a spoken version.

Body text is fetched and extracted separately from ingestion, so a freshly ingested article may have metadata before it has a body. GET returns what is stored; POST asks the backend to (re-)extract from the source URL.

Triage

Triage is the primary write path. Each verb is a narrow PATCH rather than a general article update, which keeps the audit trail meaningful:

RouteMethodPurpose
/api/articles/{article_id}/statusPATCHSet workflow status.
/api/articles/{article_id}/statePATCHSet triage state.
/api/articles/{article_id}/starPATCHToggle starred.
/api/articles/{article_id}/laterPATCHMark for later.

There is also a token-authenticated public route used by email digests, so a "mark as read" link works without a login session:

GET /api/articles/{article_id}/read?token=...

Saving an external URL

POST /api/articles/save-url

Ingests an arbitrary URL as an article for the calling user, without adding a recurring source. This is what the browser extension and share targets use.

GET /api/search
ParameterTypeNotes
qstringSpace-separated search terms.
limitinteger1..200, default 50.
offsetinteger>= 0, default 0.
statesstring[]Repeatable; restrict to these triage states.
categoriesstring[]Repeatable.
sourcesstring[]Repeatable; source slugs.
starred_onlybooleanDefault false.
include_archivedbooleanDefault false. Archived articles are excluded unless set.
date_rangestringDefault all.
tag_idintegerRestrict to a tag.

Repeatable parameters are passed by repeating the key: ?states=new&states=saved.

Saved searches

RouteMethodPurpose
/api/search/savedGETList saved searches.
/api/search/savedPOSTSave the current query and filters.
/api/search/saved/{search_id}PATCHRename or update.
/api/search/saved/{search_id}DELETERemove.

Highlights

RouteMethodPurpose
/api/articles/{article_id}/highlightsGETList highlights on an article.
/api/articles/{article_id}/highlightsPOSTCreate one.
/api/articles/{article_id}/highlights/{highlight_id}DELETERemove one.

Highlights are per-user and anchor into the extracted body, so re-extracting a body can affect how they resolve.

Tags and collections

RouteMethodPurpose
/api/tagsGETList your tags.
/api/tagsPOSTCreate a tag.
/api/tags/{tag_id}PATCHRename or restyle.
/api/tags/{tag_id}DELETEDelete a tag.
/api/tags/{tag_id}/articlesGETArticles carrying a tag.
/api/articles/{article_id}/tagsGETTags on an article.
/api/articles/{article_id}/tagsPOSTAttach a tag.
/api/articles/{article_id}/tags/{tag_id}DELETEDetach a tag.

Reading list

An explicitly ordered queue, separate from tags and triage state:

RouteMethodPurpose
/api/reading-listGETList queued items in order.
/api/reading-listPOSTAdd an item.
/api/reading-list/reorderPOSTReorder the queue.
/api/reading-list/importPOSTBulk import.
/api/reading-list/{item_id}PATCHUpdate an item.
/api/reading-list/{item_id}DELETERemove an item.

AI-derived views

These endpoints run retrieval or generation and are slower than plain reads. They depend on article embeddings, which are produced during ingestion.

RouteMethodPurpose
/api/articles/{article_id}/insightsGETGenerated insights for an article.
/api/articles/{article_id}/perspectivesGETContrasting coverage of the same story.
/api/articles/topic-mapGETTopic clustering across your articles.
/api/askPOSTAsk a question across your corpus.
/api/summaryGETA generated summary view.

Embedding similarity is executed as SQL <=> queries against an HNSW index in PostgreSQL, which is why the pgvector extension is a hard requirement rather than an optional extra.

Reading progress

RouteMethodPurpose
/api/users/me/streakGETCurrent reading streak.
/api/users/me/achievementsGETUnlocked achievements.
/api/users/me/reading-dnaGETAggregate reading profile.