Skip to content

Writings API guide

Status: Live

The reading-detail endpoint is implemented (CSL-208). See API Conventions for auth, errors, and caching.

Orientation for the writing endpoints. Swagger (/api/docs/, /api/redoc/) and the Linear ticket hold the exact request and response schemas. This guide covers what each endpoint is and how it behaves, not every field. For the concept, see the Writings overview.

Reading detail: GET /api/writings/{id}/

The single-piece payload behind the source-work reading screen (essay, letter, or chapter). It is public, app-key-gated (X-API-Key), user-agnostic, and cacheable (Cache-Control: public + ETag). It returns 404 when the id is not a published writing.

How it behaves:

  • Kind decides the attribution fields. A top-level kind of letter, essay, or chapter sets which attribution fields carry a value. Letters add who the letter went to and where it was written from (the origin subline, for example "from Great Bookham, Surrey"). Chapters add their position in the Work. Letters and essays add the date. A field that does not apply to a kind comes back null, so the client reads by kind.
  • source is the full book card. When a piece names a Work, source is the whole Book card: cover, year, synopsis, and the external buy_cta. One object serves both the "Discover about the book" footer and the "Buy the Book" hand-off. source is null for a standalone piece.
  • No interpretation. The "What This Means" layer is passages-only, so writings do not carry it.
  • Two computed onward rails power the footer carousels. more_on_topic returns Lewis's own Writings that share the piece's source book or theme ("more in this area"). related_content returns contributor Articles matched by shared tags, with a theme fallback when the piece has no tags. Each card's supporting_line is the "From {author}" byline. Both are content cards, live-only, self-excluded, and capped at 10, and each is [] when nothing matches.
  • No related_quotes. The curated editorial-quotes rail is passage-only, so this payload omits the field instead of returning it empty. See the Passages API guide.
  • Body is Markdown (ADR-0006), and read time comes from its word count.

See Swagger for the precise field list and status codes.