Skip to content

Conversation API

The Conversation API lets you interact with Contentrain Studio's AI agent programmatically. Instead of using the web interface, you can send messages and receive structured responses through a REST API — enabling chatbots, CI/CD pipelines, and custom integrations.

What the Conversation API Is

The Conversation API exposes the same AI agent that powers the Studio chat panel, but through a programmatic interface:

  • Same tool set (create/update/delete content, manage models, etc.)
  • Same permission model (scoped by API key role)
  • Same branch workflow (changes go to review branches)
  • Same conversation context (maintains history within a session)

API Key Management

Conversation API access requires an API key, managed in the project settings.

Creating an API Key

  1. Open the project sidebar
  2. Navigate to Conversation Keys settings
  3. Click Create key
  4. Configure the key:
SettingDescription
NameDescriptive label for the key
Roleviewer, editor, or admin — determines what the agent can do
Specific modelsRestrict access to certain models (Enterprise)
Allowed modelsList of model IDs the key can access
Allowed toolsWhich agent tools the key can invoke
Allowed localesWhich locales the key can read/write
Custom instructionsAdditional system prompt text for this key
AI modelWhich Claude model to use — Haiku or Sonnet (defaults to Sonnet)
  1. The key is generated and shown once — copy it immediately

Key Format

Conversation API keys follow the format:

crn_conv_{random-base62-string}

WARNING

API keys are shown only once at creation time. Studio stores only the SHA-256 hash. If you lose the key, create a new one and delete the old one.

Editing and Deleting Keys

You can update a key's name, role, and restrictions at any time. Deleting a key immediately revokes access.

Sending Messages

Endpoint

POST /api/conversation/v1/{projectId}/message
Authorization: Bearer crn_conv_...
Content-Type: application/json

Request Body

json
{
  "message": "Create a blog post titled 'API-Created Post' with status published",
  "conversationId": null,
  "context": { "activeLocale": "en" }
}
FieldRequiredDescription
messageYesThe user message to send to the agent
conversationIdNoContinue an existing conversation (null for new)
contextNoUI context hints — activeLocale, activeModelId, activeEntryId, activeBranch — that ground the agent's operations

There is no per-request model override. The Claude model is fixed per key: it is the AI model chosen when the key was created (see Creating an API Key).

Response

The endpoint returns a single JSON object once the agent's turn completes — it does not stream:

json
{
  "conversationId": "conv-uuid",
  "message": "Done! The blog post has been created on branch cr/content/blog-posts/en/...",
  "toolResults": [
    {
      "id": "tool-1",
      "name": "save_content",
      "result": { "branch": "cr/content/blog-posts/en/..." }
    }
  ],
  "usage": {
    "inputTokens": 1234,
    "outputTokens": 567,
    "cacheCreationInputTokens": 0,
    "cacheReadInputTokens": 0
  }
}
FieldDescription
conversationIdThe conversation ID — pass it back as conversationId on the next request to continue the thread
messageThe agent's final response text
toolResultsResults of any tools the agent invoked this turn (omitted when no tools ran)
usageToken usage for the turn — input, output, and prompt-cache tokens

Conversation History

Fetching a Conversation

GET /api/conversation/v1/{projectId}/history?conversationId=conv-uuid
Authorization: Bearer crn_conv_...

The conversationId query parameter is required — the endpoint returns the messages for that one conversation, not a list of conversations. An optional limit (default 50, max 100) caps how many messages come back.

json
{
  "conversationId": "conv-uuid",
  "messages": [
    {
      "id": "msg-uuid-1",
      "role": "user",
      "content": "Create a blog post titled 'API-Created Post'",
      "createdAt": "2026-04-02T10:00:00Z"
    },
    {
      "id": "msg-uuid-2",
      "role": "assistant",
      "content": "Done! The blog post has been created...",
      "model": "claude-sonnet-4-6",
      "usage": { "inputTokens": 1234, "outputTokens": 567 },
      "createdAt": "2026-04-02T10:00:05Z"
    }
  ]
}

Continuing a Conversation

Pass the conversationId in subsequent requests to maintain context:

json
{
  "message": "Now update the title to 'Updated Post'",
  "conversationId": "conv-uuid"
}

The agent will remember the previous context and can reference earlier operations.

Custom Instructions

Each API key can have custom instructions — additional text injected into the agent's system prompt. Use this to:

  • Set content guidelines ("Always use formal English")
  • Define default behaviors ("Set status to draft unless I say published")
  • Restrict scope ("Only work with the blog-posts model")
  • Add domain knowledge ("Our brand voice is friendly and professional")

Custom instructions are configured when creating or editing the API key.

Use Cases

Chatbot on Your Website

Embed a chat widget on your website that uses the Conversation API to let visitors ask questions about your content or submit feedback:

javascript
const response = await fetch('/api/conversation/v1/{projectId}/message', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer crn_conv_...',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: userInput,
    conversationId: sessionId,
  }),
})

const { conversationId, message } = await response.json()
// Show `message` to the visitor; reuse `conversationId` on the next turn.

CI/CD Content Updates

Automate content updates from your deployment pipeline:

bash
curl -X POST \
  -H "Authorization: Bearer crn_conv_..." \
  -H "Content-Type: application/json" \
  -d '{"message": "Set the site-settings version field to 2.1.0"}' \
  https://your-studio.com/api/conversation/v1/{projectId}/message

Bulk Content Operations

Use the API to perform bulk operations that would be tedious in the UI:

javascript
const operations = [
  'Set all blog posts with status draft to published',
  'Add the tag "featured" to entries with rating above 4',
  'Copy all English FAQ entries to Spanish',
]

for (const op of operations) {
  await sendMessage(op, conversationId)
}

Content Migration

Migrate content from external sources by instructing the agent:

"Create a team member entry with name 'Jane Smith', role 'CTO',
bio 'Leading technology strategy...', and email '[email protected]'"

Role-Based Access

Each Conversation API key has exactly one of three roles, and that role determines what the agent can do:

RoleCan ReadCan WriteCan DeleteCan Manage Models
ViewerYesNoNoNo
EditorYesYesYesNo
AdminYesYesYesYes

INFO

These three roles (viewer / editor / admin) are specific to Conversation API keys. They are not the same as the workspace and project roles used by the in-app AI Chat agent (workspace owner / admin / member combined with project editor / reviewer / viewer).

Model Restrictions

With specificModels enabled, the API key can only access the models listed in allowedModels. This is useful for creating scoped keys that can only manage specific content areas.

Tool Restrictions

The allowedTools setting lets you restrict which agent tools a key can invoke. For example, a viewer key might only allow brain_query and brain_search, while an editor key allows save_content and delete_content.

Locale Restrictions

The allowedLocales setting restricts which locales the key can read from and write to.

Plan Limits

FeatureFreeStarterProEnterprise
Conversation keys0015Unlimited
API messages/month01003,000Unlimited
Custom instructions (roadmap)NoNoYesYes

INFO

The Conversation API is an Enterprise-Edition feature available on Pro and above — Starter workspaces cannot create conversation keys.

Next Steps

  • AI Chat — Understand the agent's capabilities
  • Content Models — Define models for API-driven content
  • Webhooks — Get notified when content changes via API

Released under the AGPL-3.0 License.