Content API
Internal Application API
These are internal SPA routes (cookie/session authenticated, used by the Studio app), not a versioned public contract — they may change between releases. To read published content externally, use the CDN Delivery API.
Content operations in Studio are performed through the chat agent (SSE endpoint) or through direct API calls for programmatic use. The direct API provides content save and status management.
All content endpoints are project-scoped:
/api/workspaces/:workspaceId/projects/:projectId/content/...Save Content
Save content entries to a model. Creates a cr/* branch, commits the changes, and optionally auto-merges based on workflow configuration.
POST /api/workspaces/:workspaceId/projects/:projectId/content/:modelIdRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
locale | string | No | Locale code (default: en) |
data | object | Yes | Content data (format depends on model kind) |
slug | string | Conditional | Document slug (required for document kind) |
body | string | No | Markdown body (document kind only) |
Data Format by Kind
Collection:
{
"data": {
"a1b2c3d4e5f6": {
"title": "My Blog Post",
"excerpt": "A brief summary"
}
}
}Singleton:
{
"data": {
"headline": "Welcome to Studio",
"tagline": "Conversation-first CMS"
}
}Dictionary:
{
"data": {
"auth.sign_in_title": "Sign in to your account",
"auth.sign_in_button": "Sign In"
}
}Response
The response is the engine's WriteResult ({ branch, commit, diff, validation }) spread with the merge outcome (merged, workflow, pullRequestUrl). There is no top-level commitSha, filesChanged, valid, or errors — the commit SHA lives under commit.sha, the changed files under diff, and validity under validation:
{
"branch": "cr/content/blog-post/en/1774800862-27c1",
"commit": {
"sha": "abc123def456",
"message": "contentrain: save blog-post [en]",
"author": { "name": "Contentrain Studio", "email": "[email protected]" },
"timestamp": "2026-01-15T12:00:00.000Z"
},
"diff": [
{ "path": ".contentrain/content/blog-post/en.json", "status": "modified" }
],
"validation": { "valid": true, "errors": [] },
"merged": true,
"workflow": "auto-merge",
"pullRequestUrl": null
}When validation fails, the endpoint returns the same WriteResult shape early with validation.valid: false and populated validation.errors (and an empty branch). pullRequestUrl is populated only when the merge opens a pull request instead of merging directly; otherwise it is null.
Auth
Requires editor, admin, or owner role.
Update Entry Status
Change the publish status of content entries.
PATCH /api/workspaces/:workspaceId/projects/:projectId/content/:modelId/statusRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
locale | string | No | Locale code (default: en) |
entryIds | string[] | Yes | Entry IDs to update |
status | 'draft' | 'published' | 'archived' | Yes | Target status |
Response
{
"merged": true,
"status": "published",
"entryIds": ["a1b2c3d4e5f6"]
}status and entryIds echo the request; merged reports whether the status-change branch was auto-merged.
Brain Sync
Refresh the project brain cache. Returns the full content snapshot used by the chat agent and context panel.
GET /api/workspaces/:workspaceId/projects/:projectId/brain/syncResponse
{
"models": [
{
"id": "blog-post",
"name": "Blog Post",
"kind": "collection",
"domain": "blog",
"i18n": true,
"fields": { ... }
}
],
"content": {
"blog-post:en": {
"a1b2c3d4e5f6": {
"title": "My Post",
"status": "published"
}
}
},
"meta": {
"blog-post:en": {
"a1b2c3d4e5f6": {
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-15T00:00:00Z",
"createdBy": "[email protected]"
}
}
},
"config": {
"stack": "nuxt",
"locales": { "default": "en", "supported": ["en", "tr"] },
"domains": ["marketing", "blog"],
"workflow": "auto-merge"
},
"schemaValidation": {
"healthScore": 95,
"modelCount": 5,
"validModels": 5,
"warnings": []
}
}Brain Cache
The brain cache is an in-memory representation of the project content, built from Git on first access and invalidated after any write operation. It is used by the chat agent for fast content reads.
Content Engine
Behind the scenes, all content operations go through the Content Engine (server/utils/content-engine/). The engine orchestrates:
- Validation -- schema-based content validation using model field definitions
- Serialization -- canonical JSON output (sorted keys, 2-space indent, trailing newline)
- Branching -- creates a
cr/*feature branch from thecontentrainSSOT branch - Commit -- commits file changes via the GitProvider
- Auto-merge -- merges the branch back if workflow and permissions allow
See Content Engine for full internals.
Related Pages
- Chat API -- content operations via AI agent
- Branches API -- managing content branches
- Field Types -- supported field type reference
- Content Engine -- write path internals