Skip to content

Content model

Everything you read or write through CM Box’s APIs is an item: a document, an image, an article, a folder. Items live in a content repository, are shaped by a content type, carry a common set of system fields, and move through a draft/published version lifecycle. This page defines those concepts so the GraphQL API and REST API make sense.

A content repository is an independent namespace with its own content types, items, taxonomies, and search indexes (see the architecture overview).

A content type defines the custom fields an item of that type carries — each field has a name, a datatype (text, number, date, reference, and so on), and settings such as whether it holds one value or a list. Reference fields hold the IDs of other items, which the GraphQL API resolves into nested objects.

An item is an instance of a content type. Item IDs are generated by the platform and are prefixed by kind: content items start with ITEM_ and folders with FOLDER_. An item’s payload combines the system fields below with the custom field values defined by its type.

Every item carries these platform-managed fields:

Field Type Meaning
id string Unique item identifier, stable across versions
name string Display name
type string Content type name
description string Optional description
slug string URL-friendly identifier; auto-generated if you don’t supply one (maximum 128 characters); the REST API provides a check-slug endpoint to test whether a slug is already in use
status string Publication status — see the lifecycle
language string Item language
createdDate number Creation timestamp (Unix epoch milliseconds)
updatedDate number Last-update timestamp (Unix epoch milliseconds)
publishedDate number Publication timestamp (Unix epoch milliseconds), when present
createdByUser / updatedByUser object { userName, displayName, email } of the creating / last-updating user
taxonomies array Assigned taxonomies and categories — see Taxonomies
renditions array Files attached to the item (the native upload plus generated renditions), each with name, type, format, url, mimeType, size, and fileName
currentVersion string The version number of this record
latestVersion string The highest version number that exists for the item
publishedVersion string The most recently published version number
isLatestVersion boolean Whether this record is the item’s newest version
isLatestPublished boolean Whether this record is the newest published version
isPublished boolean Whether this version is published
isArchived boolean Whether the item is archived
isPreview boolean Whether this is a preview (unpublished) version
autoPublishDate number Optional scheduled publish time (epoch milliseconds)
autoArchiveDate number Optional scheduled archive time (epoch milliseconds)
parent string ID of the containing folder, or null — see Folders
readPerm / writePerm / deletePerm array Role names granted read / write / delete on the item; defaulted from the repository’s security settings when not supplied

The REST item response also includes versionHistory — a list of { version, status, updatedDate, updatedByUser } entries for the item’s versions.

Content types cannot define custom fields with system-managed names. The reserved list is:

id, slug, name, type, repositoryId, status, description, language, createdDate, updatedDate, createdByUser, updatedByUser, taxonomies, renditions, external, publishedVersion, currentVersion, latestVersion, isLatestVersion, isLatestPublished, taxonomiesChanged, isPublished, isArchived, autoArchiveDate, autoPublishDate, isPreview, extractedText, cardPreview, parent, isPackaged, _packages, _mediaTimestamps

Custom field values sent under any of these names are ignored on create and update. The current list is also available from the REST API’s reserved field names endpoint.

Items are versioned with major.minor numbers, and every version is kept as its own record:

  • Create — a new item starts as version 0.1 with status: "draft" (isPublished: false, isPreview: true).
  • Save — each update creates a new draft version, incrementing the minor number (1.01.11.2).
  • Publish — publishing creates a new published version, incrementing the major number and resetting the minor (0.11.0, 1.22.0). The new version gets status: "published", and publishedVersion and isLatestPublished are updated. Earlier published versions remain readable by version number.
  • Archive — archiving sets isArchived: true. Queries exclude archived items by default; the showArchive and showArchiveOnly query settings include or isolate them.

The status field values are draft, published, and archived.

Because old versions are retained, a query must say which version it wants. Whenever isLatestVersion is true you are looking at the newest version (possibly an unpublished draft); whenever isLatestPublished is true you are looking at what site visitors see. In queries this is the difference between latest (the default) and latestPublished — see latest vs. latestPublished. REST item endpoints accept the same choice through their version query parameter (a version number or latestpublished).

A taxonomy is a named hierarchy of categories managed per repository (for example, a “Topics” taxonomy containing nested topic categories). Each taxonomy has a shortName used in APIs, and each category has an apiName.

Items are tagged by setting their taxonomies field, an array of:

{
"id": "<taxonomy id>",
"name": "<taxonomy name>",
"categories": [ { "id": "<category id>", "name": "<category name>" } ]
}

Assigned categories are indexed for search, which is what the filters query setting matches against: filter keys are taxonomy short names and values are lists of category names. The GraphQL API also exposes taxonomy lookups (taxonomies, getTaxonomy, getCategory) and category counts over a search (tagCloudSearch).

Folders organize items hierarchically. A folder is itself an item — its type is Folder and its ID starts with FOLDER_ — and an item’s parent field holds the ID of the folder that contains it (or null at the repository root).

Search queries ignore folder structure by default: results exclude items of type Folder, and items match regardless of where they live. To work with folders, use the query settings: folder restricts results to the direct children of one folder, and includeFolders: true adds folder items to the results.

Search-style queries — GraphQL items, get<Type>, and tagCloudSearch — take a single QuerySettings object:

Field Type Behavior
query string Full-text search string; most punctuation is stripped from the string before matching
start number Zero-based offset of the first result (paging)
limit number Maximum number of results to return
filters object Taxonomy filtering: keys are taxonomy short names, values are arrays of category names; an item matches if it is tagged with any listed category
types array of strings Restrict results to these content types; defaults to all of the repository’s types
status array of strings Restrict results by status; accepted values are published, notPublished, draft, inReview, approved, rejected
sort string Sort specification as field:direction, for example updatedDate:DESC; when no query is given, defaults to updatedDate:DESC
advancedQuery string Raw search-expression fragment appended to the generated query, for filters the other settings don’t cover
folder string Return only direct children of this folder ID
includeFolders boolean Include Folder items in results (excluded by default)
version string latest (default), latestPublished, or a specific version number — see the lifecycle
showArchive boolean Include archived items alongside normal results
showArchiveOnly boolean Return archived items exclusively
packageName string Query the named update package, layered over the main repository
packageOnly boolean With packageName, return only items in the package (no layering)