---
title: "Create or update the caller's note on a reading-list entry (auth required)"
method: POST
path: "/api/reading-list/{slug}/notes"
---

# Create or update the caller's note on a reading-list entry (auth required)

`POST /api/reading-list/{slug}/notes`

## Request

- Base URL: `https://www.oxfordledge.com` (the document declares no server; this is the origin it was published from)
- URL: `https://www.oxfordledge.com/api/reading-list/{slug}/notes`
- Auth: none declared

A8 (FAST-TRACK 2026-05-12; spike-ratified Cand. A 2026-05-14):
POST a body + is_public flag; idempotent on (user_id, slug).

CSRF: enforced via `dependencies=[Depends(validate_csrf)]` on the
decorator. The prior in-body `validate_csrf(request)` was a bare call
to an `async def` — it returned a discarded coroutine and NEVER
validated (CSRF was fully bypassed). CISO #49 2026-05-15.

## Path parameters

- `slug` string, required: Reading-list entry slug.

## Request body

- object

## Response `200`

Successful Response

- ReadingListNoteUpsertResponse: `POST /api/reading-list/<slug>/notes` — create or update.
  - `status` string, required: 'ok' on success.
  - `note` ReadingListNote: A single user's note on a single reading-list entry. Spike: `docs/plans/A8_DESIGN_SPIKE_READING_LIST_ANNOTATIONS.md`. DB: `reading_list_notes` table (v77). Body is capped at 500 chars at the API layer (DESIGN ratification 2026-05-14); the DB column is unconstrained TEXT to let the cap rise without a migration.
    - `id` integer, required: Surrogate row ID.
    - `slug` string, required: Reading-list entry slug (e.g., 'most-important-thing-howard-marks').
    - `body` string, required: Note text (≤500 chars at the API layer).
    - `is_public` boolean, required: True if /reading-list/<slug>/notes/<username> is publicly indexable.
    - `created_at` string, nullable: ISO-8601 timestamp; absent on first POST until commit.
    - `updated_at` string, nullable: ISO-8601 timestamp.
    - `username` string, nullable: The note author's display username (public reads only).
  - `error` string, nullable: Validation or persist error.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `404`: Not Found
- `422`: Validation Error

---

[API](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api.md) · [All operations](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/llms.txt) · [OpenAPI document](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/revisions/e832a1260f0b?raw)
