The model
Create a collection with
POST /v1/cms/collections, add fields with POST /v1/cms/collections/{collectionId}/fields, then create items with POST /v1/cms/collections/{collectionId}/items. GET /v1/cms/collections returns each collection’s active item count. GET /v1/cms/schema returns the whole schema, including collections and fields, in one call.
Slugs and keys are load-bearing: page code queries collections by slug and reads values by field key. Renames go through the normal update endpoints — slug on PATCH /v1/cms/collections/{collectionId}, key on PATCH /v1/cms/fields/{fieldId}, and slug on PATCH /v1/cms/items/{itemId} — and migrate stored data atomically.
Fields
A field has atype (immutable after create), required, and isUnique flags, an optional description, an optional example value (any JSON, a design-phase placeholder that reads back as null when unset), and a position you change by passing position (with anchorFieldId for before/after) to PATCH /v1/cms/fields/{fieldId}. Reference fields also declare an immutable targetCollectionId.
To change a field’s type, create a new field, migrate the data, and delete the old one. isUnique is not available on plain_text, markdown, or the multi-valued and asset-backed types.
Field keys match ^[a-z][a-z0-9_]{0,63}$. The keys id, slug, publishedAt, publishAt, createdAt, updatedAt, and position are reserved for item metadata.
Field types
All 14 field types, with write-time validation and exact limits:
Scalar values live in the item’s
data object. Reference and asset values are stored relationally and written through dedicated request properties: references, images, and files on POST .../items and PATCH /v1/cms/items/{itemId}. Image writes accept an asset id, { "assetId": "...", "altText": "..." }, or null to clear. See Assets.
Items: drafts, scheduling, publishing, ordering
An item has one of three publication states:- Draft:
publishedAtandpublishAtare bothnull. - Scheduled:
publishedAtisnullandpublishAtis a future timestamp. Cactal promotes the item shortly after that time, clearspublishAt, and records the actual time inpublishedAt. - Published:
publishedAtis set andpublishAtisnull.
POST /v1/cms/items/{itemId}/set-published with { "published": true } to publish immediately, { "publishAt": "2026-08-10T15:00:00Z" } to schedule a draft, or { "published": false } to unpublish or cancel a schedule. Published items must be unpublished before scheduling because scheduled publication promotes the latest saved item rather than a frozen revision. Item data remains patchable in every state.
DELETE /v1/cms/items/{itemId} soft-deletes: the item leaves all reads and backreference results, but POST /v1/cms/items/{itemId}/restore brings it back with its references intact. Items order by a position you change on PATCH /v1/cms/items/{itemId} using { "position": "first" | "last" | "before" | "after", "anchorItemId": "..." }.
Published websites render only items with
publishedAt set. Draft, scheduled, unpublished-again, and soft-deleted items never appear on the live site. API reads include every state by default; filter with published=true or published=false on GET /v1/cms/collections/{collectionId}/items. Scheduled items match published=false until promotion.References and hydration
Reference fields link items across collections. Reads return them by id atdepth=0 (the default): a single reference is an item id string, a multi-reference is an array of ids. Pass depth up to 3 to hydrate referenced items in place, one level per unit.
null (single) or is omitted from the array (multi). GET /v1/cms/items/{itemId}/backreferences returns the active items that point at an item. It uses the standard { items, nextCursor } envelope; follow every cursor before deleting content that other items link to.
Deleting a collection is refused with 409 while reference fields in other collections target it; the error lists the blocking fields. Reads never break on schema drift: unknown keys are stripped and missing values read as null.
Querying items
GET /v1/cms/collections/{collectionId}/items supports cursor/limit pagination plus:
Field operators:
eq, neq, in, nin, exists on all types; gt/gte/lt/lte on number and date; contains, startsWith, endsWith on text-like types. Reference fields also accept slug for one-level equality matching, such as {"author":{"slug":"jane"}}. Metadata keys accept a narrower set: id and slug take eq, in, and startsWith; publishedAt and publishAt take exists, gt, gte, lt, and lte; createdAt and updatedAt take gt, gte, lt, and lte. Any other operator on a metadata key returns 400. GET /v1/cms/items/find fetches one item by itemId, or by collectionId plus slug.
Limits
Next steps
Manage CMS content
Model a collection and run the full content workflow.
Assets
Upload images and files to use in image, gallery, and file fields.