POST | /v1/comments | Add a threaded comment (nested reply via parent_id; max depth 5; max length 5000 chars). |
GET | /v1/comments | List top-level comments (with nested replies attached) for an article, oldest first. |
GET | /v1/comments/flagged | The admin moderation queue — status='flagged', non-deleted, newest first. |
GET | /v1/comments/count | Non-deleted, non-rejected comment count for an article. |
DELETE | /v1/comments/{comment_id} | Soft-delete a comment (admin any; a user only their own). |
POST | /v1/comments/{comment_id}/moderate | Admin moderation — approve |
GET | /v1/locks/{article_id} | Check the current edit-lock for an article (evicts an expired lock). |
POST | /v1/locks/{article_id} | Acquire an edit lock (store-authoritative, atomic per org+article; granted to the holder or when expired). |
DELETE | /v1/locks/{article_id} | Release an edit lock (only the holder may release). |
POST | /v1/locks/{article_id}/force-release | Force-release a lock (admin). |
GET | /v1/locks | All currently-held locks for the org (evicts expired). |
POST | /v1/edit-sessions | Save an edit-session audit record (a held lock must be owned by this user). |
GET | /v1/edit-sessions | Edit history for an article, newest first. |
POST | /v1/submissions | Submit an article for editorial review (duplicate non-rejected URL refused). |
GET | /v1/submissions | List submissions (optionally by status). |
POST | /v1/submissions/{submission_id}/review | Approve or reject a pending submission. |
GET | /v1/submissions/user/{user_id} | List a user's submissions. |
GET | /v1/submissions/{submission_id} | Get a single submission by id. |
POST | /v1/content/types | Define a content type (a JSON Schema 2020-12 for entry fields). A change appends an immutable new version; an identical definition returns the current version unchanged. |
GET | /v1/content/types | The latest version of every content type in the org. |
GET | /v1/content/types/{type_key} | One content type — the latest version, or a pinned version. |
POST | /v1/content/entries | Create an entry of a type, optionally with its first revision (validated against the type schema). |
GET | /v1/content/entries | List entries in the org. |
GET | /v1/content/entries/{entry_id} | One entry with its workflow state, review, published pointer and latest revision per locale. |
DELETE | /v1/content/entries/{entry_id} | Archive an entry. It stops being served; a pending review is closed. Revisions are kept. Publishing again restores it. |
POST | /v1/content/entries/{entry_id}/revisions | Append an immutable revision for one locale. Refused while another user holds the edit lock on cms-entry:<entry_id>. Supersedes a pending review. |
GET | /v1/content/entries/{entry_id}/revisions | Revisions of an entry, newest first. |
POST | /v1/content/entries/{entry_id}/submit | Submit a draft for review. Opens a request in the submissions FSM, decided through /v1/submissions/{submission_id}/review. |
POST | /v1/content/entries/{entry_id}/publish | Publish the latest revision of every locale atomically and write a cms.entry.published outbox event. An entry in review needs an approved review; a require_review type needs one to publish at all. |
GET | /v1/content/collections | Collections in the org. |
PUT | /v1/content/collections/{collection_key} | Create or update a collection's metadata. |
GET | /v1/content/collections/{collection_key}/items | Every item of a collection in rank order, with whether each is live and inside its featured window. |
PUT | /v1/content/collections/{collection_key}/items | Replace the ordered item set atomically and write a cms.collection.updated outbox event. |
POST | /v1/content/assets | Upload a PNG, JPEG, WebP or GIF image of at most 1 MiB, content-addressed by SHA-256 (re-uploading the same bytes returns the existing asset). |
GET | /v1/content/assets | Asset metadata in the org, newest first (never the bytes). |
GET | /v1/content/public/{organization_id}/collections/{collection_key} | PUBLIC — a collection's live items in rank order, limited to published, non-archived entries inside their featured window, each in the requested locale with fallback. |
GET | /v1/content/public/{organization_id}/assets/{sha256} | PUBLIC — image bytes, only while referenced by a published, non-archived entry. Immutable caching. |
GET | /v1/content/public/{organization_id}/{type_key}/{entry_key} | PUBLIC — the published content of an entry. Locale fallback goes exact tag, shorter prefixes, then the entry's default locale. Drafts, entries in review, archived entries and unpublished locales are never served. |
GET | /health | Liveness + store/tenancy posture (never the DSN). |
GET | /metrics | Prometheus metrics. |