Files
bookhoard/docs/developer/api/collections/list_collections.md
T
John O'Keefe cc893f758e feat(docs): drift gate — docs frontmatter validated against real routes
Every API doc that declares frontmatter (method/path/auth/area) is now
checked by a unit test against three sources of truth:

1. Route registration: internal/router/*.go is parsed the way echo resolves
   it (group prefixes concatenate; scanner.go's parameterized groups seeded).
   Doc paths that no longer exist fail. (This is the check that would have
   caught the /api/api/admin/hash-conflicts split.)
2. Auth: frontmatter auth label must match the middleware chain
   (none|jwt|jwt+admin|device-token|optional-jwt).
3. Shapes: internal/docs/schema.go registry — example-request decoded with
   unknown fields DISALLOWED (typo guard), required-by-validate fields must
   appear (staleness guard), example-response top-level key set compared
   both directions against the marshaled handler type (or a RawMessage pin
   for hand-built map responses).

Five collections docs are the pilots with real handler shapes; notable
corrections they pin: update returns 201 (not 200), list excludes smart
collections unless include_auto=true, rule priority is 1-10 higher-wins
(docs claimed 1=highest), created_at is Go time.String() not RFC3339,
hide_finished/show_up_next toggles documented. CollectionResponse hoisted
out of GetCollections/GetBookCollections as CollectionSummary /
BookCollectionSummary so the registry can pin real types.

The gate fails on missing registry entries by design — that is the
maintenance contract. Known pre-existing (not this commit): vet copy-lock
warnings in media.go.
2026-10-24 14:41:02 -04:00

2.0 KiB

method, path, auth, area
method path auth area
GET /api/collections jwt collections

List Collections

Lists the signed-in user's collections with live book counts. Smart (rule-driven) collections are excluded by default so legacy readers never see stale membership — pass include_auto=true to include them.

Example request

GET /api/collections?include_auto=true&sort_by=name

Example response

{
  "collections": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "To Read",
      "description": "Books I want to read soon",
      "color": "#00FF00",
      "icon": "📖",
      "auto_assign_rules": null,
      "created_at": "2026-10-24 13:57:01.81234 +0000 UTC",
      "book_count": 12,
      "is_smart": false
    }
  ],
  "total": 1
}

created_at uses Go's time.String() format, not RFC3339.

Query parameters

Param Type Default Notes
include_auto boolean false include smart collections
sort_by string — name sorts alphabetically; otherwise service order
library_id uuid — scopes book counts to one library (smart collections only)

Response fields

Field Type Notes
collections array CollectionSummary objects, see below
total number length of collections

Collection item

Field Type Notes
id string (uuid)
name string
description string
color string
icon string
auto_assign_rules array | null raw rules JSON; non-null implies smart
created_at string Go time.String() format
book_count number live count; respects library_id for smart collections
is_smart boolean

Errors

Status Body When
500 {"error": "..."} unexpected server error