HTTP API
Route handlers validate HTTP input, derive the server actor, enforce access, and call shared commands or database stores.
Review write contract
POST /api/reviews/[reviewKey] accepts a strict body with nonnegative integer
version, UUID requestId, and 1–1000 pending commands. It validates the UUID path, loads
the review, checks access, replaces command actor/time, and calls
saveCommands. A successful response is StoredReview; stale
writes return 409 plus current. Request retries do not execute an accepted
batch twice.
Endpoint map
| Method and route | Access / payload | Implementation |
|---|---|---|
| GET /api/session | Session actor; setup errors include setupFields. | getActor |
| GET /api/reviews | report capability; identity/version rows for intake, not full review bodies. | queryReviewVersions |
| GET/POST /api/reviews/[reviewKey] | Actor plus row scope; UUID only. | loadReviewForActor / saveCommands |
| GET /api/inbox | Actor; page size, section, offsets, since/asOf. | queryInbox |
| POST /api/inbox/seen | Actor; optional asOf. | inboxSeen |
| GET/POST /api/inbox/events | Actor; optional since / clear through timestamp. | queryEvents / clearEvents |
| POST /api/inbox/events/[id]/read | Actor; event ID. | readEvent |
| GET /api/catalog | Actor; queue, branches, examiner/year/month, category, sort, page. | queryCatalog |
| PATCH /api/catalog/flag | Actor plus scoped row; { reviewKey: UUID, flagged: boolean }. | flagReview |
| GET /api/search | Actor; text, filters, sorts, limits and quick mode. | querySearchPage |
| GET /api/search/fields | Public registry, no actor check. | searchFields |
| GET /api/reports | report capability; from/through, examiner, county. | queryReport |
| GET /api/exports | Export role; no kind lists months, kind + months generates TSV in JSON. | queryExportMonths / exportReviews / generateMonthExport |
| GET/POST /api/policy | report capability; GET lists, POST validates new amount table. | listPolicies / publishPolicy |
| POST /api/imports/snap-negative | import capability; files, business identity, expectedVersion, requestId. | promoteSnapNegative |
| POST /api/documents | Upload role; start JSON, completion JSON, or local multipart. | Configured document adapter |
| GET /api/documents/[key] | Current visible review must reference key; PDF or signed redirect. | findReviewForDocument + storage |
| POST /api/demo/view-as | Test Clerk instance and roster; { staffId }. | Clerk sign-in ticket |
Errors and response conventions
Every handler is wrapped in apiRoute, so failures share one JSON
{ error } envelope. AccessError and DocumentError keep their 401/403/4xx
status. RuleError and Zod rejections use 400. Stale saves use 409 with
current. Storage failures and any unknown fault use 503; unknown faults are
logged and return the route's fallback message. Document GET returns the PDF or a redirect
on success.
Several list handlers use serverTiming.json, which sets private/no-store and
auth/data/serialize timings. Dynamic rendering does not replace authorization. A new
handler needs input validation and access enforcement even when its page already checks
the role.