Skip to main content

REST Management API

Base: /api/v1/projects/{projectSlug}/.... Bearer-authed with a management key or a session JWT.

Resources

PathMethodsPurpose
/content-typesGET, POSTList + create content types
/content-types/{apiName}GET, PUT, DELETERead / update / delete a type
/content-types/{apiName}/delete-checkGETCheck whether a type can be safely deleted
/content-types/{apiName}/fieldsGET, POSTList + add fields
/content-types/{apiName}/fields/{fieldApiName}PUT, DELETEUpdate / delete a field
/entriesGET, POSTList + create entries
/entries/{id}GET, PUT, DELETERead / update / soft-delete
/entries/{id}/publishPOSTPublish a locale
/entries/{id}/unpublishPOSTUnpublish a locale
/entries/{id}/duplicatePOSTClone (with options)
/entries/{id}/copy-localePOSTSeed a translation from another locale
/entries/{id}/versionsGETList version snapshots
/entries/{id}/versions/{versionNum}GETRead one version snapshot
/entries/{id}/versions/{versionNum}/restorePOSTRestore a specific version
/entries/{id}/restorePOSTRestore a version (creates a new version)
/entries/{id}/referencesGET"Where used" — entries referencing this one
/entries/{id}/workflowGET, POSTCurrent state + transition
/entries/{id}/previewPOSTGenerate a signed preview URL
/entries/bulkPOSTUp to 100 entries: publish / unpublish / delete / move / workflowTransition / assign / duplicate
/tree/{siteSlug}GETTree for one site
/tree/globalGETGlobal tree
/tree/nodesPOSTCreate a node
/tree/nodes/{id}PUT, DELETEUpdate / delete a node
/tree/nodes/{id}/movePOSTReparent + reorder
/sitesGET, POSTList + create
/sites/{slug}GET, PUT, DELETERead / update / delete
/mediaGETList assets
/media/{id}GET, PUT, DELETERead / update / delete
/media/{id}/locales/{locale}PUTUpsert the per-locale overlay (altText, title, description, overrideStorageKey)
/media/uploadPOSTMultipart upload
/media/foldersGET, POSTList + create folders
/media/folders/{id}PUT, DELETEUpdate / delete a folder
/redirectsGET, POSTList + create
/redirects/{id}PUT, DELETEUpdate / delete
/redirects/importPOSTCSV import
/redirects/exportGETCSV export
/environmentsGET, POSTList + create
/environments/{slug}PUT, DELETEUpdate / delete
/environments/{slug}/promotePOSTPromote (full or cherry-pick)
/environments/selectPOSTSet the active environment
/workflowsGET, POSTList + create
/workflows/{slug}PUT, DELETEUpdate / delete
/translationsGETTranslation dashboard
/translations/statsGETTranslation coverage stats
/translations/{entryId}GETPer-entry translation status across locales
/translations/{entryId}/{locale}PUTUpdate status / assignee
/translations/{entryId}/{locale}/mark-stalePOSTMark a locale's translation stale
/viewsGET, POSTList + create saved views
/views/{id}PUT, DELETEUpdate / delete (creator only)
/api-keysGET, POSTList + create
/api-keys/{id}DELETERevoke
/webhooksGET, POSTList + create
/webhooks/{id}PUT, DELETEUpdate / delete
/webhooks/{id}/testPOSTFire a test payload
/rolesGET, POSTList + create
/roles/{id}PUT, DELETEUpdate / delete a role
/roles/{id}/permissionsGET, POSTList grants + add a grant
/roles/{id}/permissions/{grantId}DELETERemove a grant
/usersGETList members
/audit-logsGETNot yet implemented — currently a stub returning an empty list ({ data: [] }), no params or pagination
/searchGETFull-text + facet search
/search/reindexPOSTTrigger search reindex (no-op on the default Postgres provider; real reindex when SEARCH_PROVIDER=meilisearch)
/calendarGETScheduled + completed events
/calendar/reschedulePOSTMove a scheduled job
/reports/publishing-activityGETTime-series + table
/reports/content-healthGETHealth summary + per-entry issues
/reports/schema-usageGETPer-content-type stats
/reports/user-activityGETPer-user activity
/reports/agent-activityGETPer-API-key activity
/governance/analyzeGET, POSTRead last analysis (GET) / run governance analyzer (POST)
/governance/issuesGETCached issues
/governance/issues/{id}/resolvePOSTMark acknowledged
/custom-reportsGET, POSTList + create
/custom-reports/{id}PUT, DELETEUpdate / delete
/custom-field-typesGET, POSTList + register
/custom-field-types/{apiName}PUT, DELETEUpdate / delete
/ip-allowlistGET, POST, PUTList rules + add + toggle settings
/ip-allowlist/{id}PUT, DELETEEdit / delete a rule

Conventions

  • All inputs validated via Zod. 422 with details on shape mismatch.
  • Optimistic concurrency on entry updates: pass version in the body.
  • Audit logs record every mutation with before / after JSON snapshots.
  • Standard response envelope: { data } or { error, message, details? }.

Platform endpoints

For super-admins only — see Multi-tenant:

  • /api/v1/platform/tenants — list / create tenants
  • /api/v1/platform/tenants/{slug} — read / update / deactivate tenants

Examples

Create an entry

curl -X POST -H "Authorization: Bearer $MK" -H "Content-Type: application/json" \
https://cms.example.com/api/v1/projects/demo/entries \
-d '{
"contentTypeApiName": "blogPost",
"siteId": "site_main",
"locale": "en-US",
"treeParentId": "node_blog",
"slug": "hello-world",
"fields": { "title": "Hello World" }
}'

Bulk publish

curl -X POST -H "Authorization: Bearer $MK" -H "Content-Type: application/json" \
https://cms.example.com/api/v1/projects/demo/entries/bulk \
-d '{
"action": "publish",
"entryIds": ["ckl_a", "ckl_b", "ckl_c"],
"params": { "locale": "en-US" }
}'

Set localized alt text (and title / description) on a media asset

The locale overlay is an upsert — the row is created on first write, so you don't pre-create it. {locale} is a path segment (e.g. en-US) and must be a registered tenant locale (unknown → 404). Send only the fields you want to change; omitted fields are left untouched, and an explicit null clears one. Requires the update permission.

curl -X PUT -H "Authorization: Bearer $MK" -H "Content-Type: application/json" \
https://cms.example.com/api/v1/projects/demo/media/asset_123/locales/en-US \
-d '{ "altText": "Red bicycle leaning against a brick wall" }'

Returns { data: <MediaAssetLocale> }. Limits: altText ≤ 2000, title ≤ 500, description ≤ 5000 chars. An empty body returns 422 no_update_fields. This is the write side of the alt text that the delivery GraphQL MediaAsset.altText / REST ?locale= overlay reads back — see Media.