Skip to content

Home API guide

Status: Live

Today's Quote (CSL-141), Theme of the Week (CSL-137), Featured Journeys (CSL-145), What's New (CSL-142), Featured Books (CSL-143), and Further Reading (CSL-144) are implemented. All six sections are live.

Orientation for the Home section endpoints. Swagger (/api/docs/, /api/redoc/) and the Linear tickets hold the exact request and response schemas. This guide covers what each endpoint is and how it behaves, not every field.

See Home for the concept and the six-section overview, and API Conventions for auth, errors, and caching.

Conventions for all sections

Every Home section endpoint is public, app-key-gated (X-API-Key), user-agnostic, and cacheable. Caching uses Cache-Control: public, max-age=<n> plus an ETag, a tunable window with cheap If-None-Match revalidation. For the details, see the Caching section in API Conventions. No response carries per-user fields. A section with nothing to show returns 200 with {"items": []}, and the FE hides it.

Endpoint map

Section Endpoint Guide
Today's Quote (hero) GET /api/passages/todays-featured/ Passages API
Theme of the Week GET /api/themes/featured/ Themes API
Featured Journeys GET /api/journeys/featured/ below
What's New GET /api/whats-new/ below
Featured Books GET /api/books/featured/ below
Further Reading GET /api/further-reading/ below

Today's Quote and Theme of the Week

These two sections reuse endpoints documented elsewhere, so this guide does not restate them. The Passages API guide covers todays-featured, which returns a rotating pool of up to 10 passages that the FE cycles per session. The Themes API guide covers themes/featured/, which returns the featured theme_id and its slot header, both null when nothing is featured.

Up to 5 journey cards in the editor's Featured Journeys list order.

What appears. The Journeys an editor added to the Featured Journeys list, in the order they arranged them. The list is fully manual, with no auto-fill, like Featured Books. Only published journeys appear: a draft is skipped, and a journey featured twice shows once. Deleting a Journey removes its featured entry automatically.

chapters_count is what a reader can open. For a live journey that is every chapter it was authored with, because the CMS refuses to unpublish a piece a live journey is built on. The count is derived rather than stored so it cannot drift, and a journey with nothing readable left would be dropped from the carousel rather than advertised. See Journeys.

The journey card. A journey has no reading surface of its own, its chapters do, so the card has no body and no read_time_minutes. This is a single-kind list, so the card carries no kind, the same convention as Featured Books. The fields worth knowing:

  • editorial_framing is the pitch shown on the card. The app shows the opening lines behind a "see more". It is an empty string when unset.
  • colour is the journey's own hex colour, for example #2F4858, or null until design supplies one. Because the card is coloured by this, it carries no theme_id.
  • emblem is the journey's artwork as a rendition set of small, medium, large, xlarge, and xxlarge, or null. It is one image doing two jobs: the card artwork and the thing the reader collects at the end. The app blurs it and lifts the blur as chapters complete, so there are no reveal states to serve.
  • chapters_count is how many chapters the reader can open, as above.

No reader state. The response carries no progress, no completed chapters, and no collected emblem, so it stays cacheable for everyone. Reader-specific journey state belongs on a separate per-user endpoint.

What's New: GET /api/whats-new/

Up to 10 content cards for the Home "What's New" carousel.

What appears. Articles (contemporary editorial) and Writings (letters, essays, and chapters). Passages are excluded, because they already headline the hero, so repeating them would be redundant.

Ordering. Pins come first, then auto-fill, capped at 10:

  1. Editor pins hold the front, in the editor's drag order. A pin only needs to be published to show.
  2. Auto-fill takes the remaining slots with the newest eligible pieces (flagged is_new_eligible), by publication date, newest first, merged across Articles and Writings.
  3. Auto-fill never repeats a pinned piece (it is deduped), and a piece pinned twice shows once.

The content card. What's New is a mixed-kind list, so every card carries a top-level kind of article, letter, essay, or chapter. Each card references a theme by theme_id only, and the FE resolves the design from its cached theme set. Three fields are derived, not stored:

  • supporting_line is a short second line: an article's subtitle, who a letter was written to, or the Work a writing is drawn from. It is empty when there is nothing to derive it from. The copy is provisional, pending FE and design.
  • image is the piece's card image (Article featured_image or Writing image) as a rendition set of small, medium, large, xlarge, and xxlarge, or null.
  • read_time_minutes comes from the body word count. It is null when there is no body.

Up to 10 book cards in the editor's Featured Books list order.

What appears. The Books an editor added to the Featured Books list, in the exact order they arranged them. The list is fully manual, with no auto-fill, unlike What's New. Only published books appear. A draft is skipped, and a book featured twice shows once. Deleting a Book removes its featured entry automatically.

The book card. Books are reference and purchase objects, so the card has no reading surface: no body and no read_time_minutes. This is a single-kind list, so the card carries no kind, the same convention as the passage endpoints. The fields worth knowing:

  • synopsis is the Work's blurb, projected to Markdown. It is an empty string when unset.
  • cover is the cover image as a rendition set of small, medium, large, xlarge, and xxlarge, or null.
  • buy_cta is an optional external link to buy this edition, for example on Amazon. When it is set, the FE renders a "buy" CTA that links out of the app. It is null when blank, so the FE omits the CTA. The link is a discovery and buy hand-off, not an in-app purchase or paywall.
  • publication_year is the edition's year, or null.

The cover, publication details, and purchase link should all describe the same edition. Keeping them in step is an editorial responsibility, supported by the cover guidance and validation in the CMS. See the Home editor guide.

Further Reading: GET /api/further-reading/

Up to 10 content cards for the Home "Further Reading" shelf, also called "Keep Discovering". This is the closing discovery section.

What appears. A pool drawn from all live essays and letters (Writing of kind essay or letter). It is auto-pulled, not curated, so there is no editorial list. Chapters (journey-internal), Passages (the hero), Books (no reading surface), and Articles (editorial) are all excluded.

How the pool is drawn. The draw is random but daily-stable. The server shuffles the eligible set with a per-day seed and returns up to 10. The pool is stable for a caller within the day (cacheable, with a steady ETag) and rotates day to day, so the whole corpus surfaces over time. As with the hero, per-session freshness is client-side: the FE cycles within the returned pool. This endpoint has no ?exclude= cursor, unlike the hero, and serves the pool whole.

The content card. The shape is identical to What's New: a mixed-kind card, where kind is letter or essay, with the same derived supporting_line, image, and read_time_minutes fields, and a theme_id reference. An empty pool returns {"items": []}.

See Swagger for the precise field lists, cache windows, and status codes.