Skip to content

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/:modelId

Request Body

FieldTypeRequiredDescription
localestringNoLocale code (default: en)
dataobjectYesContent data (format depends on model kind)
slugstringConditionalDocument slug (required for document kind)
bodystringNoMarkdown body (document kind only)

Data Format by Kind

Collection:

json
{
  "data": {
    "a1b2c3d4e5f6": {
      "title": "My Blog Post",
      "excerpt": "A brief summary"
    }
  }
}

Singleton:

json
{
  "data": {
    "headline": "Welcome to Studio",
    "tagline": "Conversation-first CMS"
  }
}

Dictionary:

json
{
  "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:

json
{
  "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/status

Request Body

FieldTypeRequiredDescription
localestringNoLocale code (default: en)
entryIdsstring[]YesEntry IDs to update
status'draft' | 'published' | 'archived'YesTarget status

Response

json
{
  "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/sync

Response

json
{
  "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:

  1. Validation -- schema-based content validation using model field definitions
  2. Serialization -- canonical JSON output (sorted keys, 2-space indent, trailing newline)
  3. Branching -- creates a cr/* feature branch from the contentrain SSOT branch
  4. Commit -- commits file changes via the GitProvider
  5. Auto-merge -- merges the branch back if workflow and permissions allow

See Content Engine for full internals.

Released under the AGPL-3.0 License.