> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Content Management

> Manage content items with approval workflows, version history, and CMS integration for multi-channel delivery.

## Overview

The Content module is your centralized content library for every piece of customer-facing content that KaireonAI delivers. Author, review, approve, version, and publish content across eight channel types — from email templates and push notifications to WhatsApp messages and webhook payloads.

Content items go through a structured approval workflow before they reach customers, and every edit is tracked with full version history so you can audit changes or revert at any time.

## Content Items vs. Creatives

<Info>
  **Content items** are standalone, reusable pieces of content managed in your content library. They can be shared across multiple offers and campaigns — think shared disclaimers, standard footers, or frequently updated promotional blocks.

  **Creatives** are tied to a specific offer-channel combination. A creative defines *what content to show when recommending Offer X on Channel Y*.

  Use content items when you need content that lives independently and updates everywhere at once. Use creatives when content is specific to a single offer and channel pairing.
</Info>

## Content Types

Every content item has a channel type that determines its editor, validation rules, and delivery format.

| Type              | Key                 | Description                                                       | Use Case                                                   |
| ----------------- | ------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- |
| Email HTML        | `email_html`        | Rich HTML email with images, buttons, and layout blocks           | Marketing campaigns, transactional emails, newsletters     |
| Push Notification | `push_notification` | Mobile push title and body text with character limits             | Time-sensitive alerts, re-engagement nudges                |
| SMS Text          | `sms_text`          | Short message content with segment counting                       | Appointment reminders, verification codes, flash offers    |
| In-App Modal      | `in_app_modal`      | Dialog overlay with CTA buttons and rich content                  | Feature announcements, upgrade prompts, surveys            |
| Banner            | `banner`            | Display content with images for web or app surfaces               | Promotional banners, seasonal campaigns                    |
| Content Card      | `content_card`      | Card-style content for feeds, lists, or carousels                 | Activity feeds, recommendation cards, news updates         |
| WhatsApp Template | `whatsapp_template` | WhatsApp Business API message template with variable placeholders | Customer support, order updates, appointment confirmations |
| Webhook JSON      | `webhook_json`      | Custom JSON payload for API-driven integrations                   | Third-party system triggers, custom channel adapters       |

## Status Lifecycle

Every content item moves through a five-stage lifecycle. The API enforces valid transitions — you cannot skip stages.

```mermaid theme={null}
stateDiagram-v2
    [*] --> draft
    draft --> in_review: Submit for review
    in_review --> approved: Approve
    in_review --> draft: Reject (with feedback)
    approved --> published: Publish
    published --> archived: Archive
    archived --> draft: Unarchive
```

| Status      | Trigger                        | Who Can Trigger                   | What Happens                                                                                            |
| ----------- | ------------------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `draft`     | Content is created or rejected | Editor, Admin                     | Content is editable. Not visible to customers.                                                          |
| `in_review` | Author submits for review      | Editor, Admin                     | Content is locked for editing. Awaiting approval.                                                       |
| `approved`  | Reviewer approves the item     | Editor, Admin (not the submitter) | Content is approved but not yet live.                                                                   |
| `published` | Publisher pushes content live  | Editor, Admin                     | Content becomes available for delivery. `publishedAt` timestamp is set. A version snapshot is recorded. |
| `archived`  | Content is retired             | Editor, Admin                     | Content is no longer delivered but remains in history.                                                  |

## Approval Workflow

KaireonAI enforces a review gate before content reaches customers. This prevents unreviewed content from going live.

### How It Works

1. **Author creates content** — The item starts in `draft` status.
2. **Submit for review** — The author moves the item to `in_review`. The content is locked.
3. **Reviewer approves or rejects:**
   * **Approve** — Moves to `approved`. The item is ready to publish.
   * **Reject** — Moves back to `draft` with required feedback explaining what needs to change.
4. **Publish** — An editor or admin publishes the approved item, making it live.

### Self-Approval Prevention

The API prevents self-approval: the user who submitted content for review cannot be the one to approve it. This enforces a four-eyes principle where at least two people are involved before content goes live.

### Rejection Feedback

When rejecting content, the reviewer must provide feedback (1-2000 characters). This is required by the API and ensures the author knows exactly what to fix.

```json POST /api/v1/content/{id}/reject theme={null}
{
  "feedback": "The disclaimer text is outdated — please use the Q2 2026 version from Legal."
}
```

## Version History

Every content item maintains a complete version history. Versions are created automatically at two points:

* **On creation** — Version 1 is recorded with the change note "Initial version" and the creating user's ID.
* **On publish** — A version snapshot is recorded each time the item is published.

### Viewing Versions

Retrieve the full version history for any content item:

```bash theme={null}
GET /api/v1/content/{id}/versions
```

Returns up to 100 versions ordered by most recent first. Each version includes:

* `version` — The version number
* `content` — The full content payload at that point in time
* `blocks` — Block structure (if applicable)
* `personalization` — Personalization config at that version
* `changedBy` — User ID of who made the change
* `changeNote` — Description of the change
* `createdAt` — Timestamp

## CMS Integration

For teams that manage content outside KaireonAI, connect an external CMS to sync content automatically. KaireonAI supports four CMS providers:

| Provider   | Key          | Description                                     |
| ---------- | ------------ | ----------------------------------------------- |
| WordPress  | `wordpress`  | REST API integration with WordPress sites       |
| Contentful | `contentful` | Headless CMS with structured content models     |
| Strapi     | `strapi`     | Open-source headless CMS with customizable APIs |
| Sanity     | `sanity`     | Real-time collaborative content platform        |

### Sync Modes

Each content source can sync in one of two modes:

| Mode    | Key       | Description                                                                        |
| ------- | --------- | ---------------------------------------------------------------------------------- |
| Webhook | `webhook` | CMS pushes updates to KaireonAI in real time. Recommended for most setups.         |
| Polling | `polling` | KaireonAI pulls updates on a schedule. Set `syncIntervalMinutes` (1-1440 minutes). |

### Configuration

When creating a content source, provide:

* **`name`** — A label for this connection (must be unique per tenant)
* **`provider`** — One of `wordpress`, `contentful`, `strapi`, `sanity`
* **`config`** — Provider-specific connection details (API URL, credentials, space ID, etc.)
* **`syncMode`** — `webhook` (default) or `polling`
* **`syncIntervalMinutes`** — Polling interval in minutes (1-1440). Only used when `syncMode` is `polling`.
* **`autoPublish`** — When `true`, synced content skips the approval workflow and publishes immediately. Defaults to `false`.
* **`mappings`** — Field mapping from CMS fields to KaireonAI content item fields

### Auto-Publish

When `autoPublish` is enabled on a content source, incoming content from the CMS bypasses the approval workflow and goes directly to `published` status. Use this for trusted sources like your corporate CMS where content has already been reviewed externally.

<Warning>
  Enabling `autoPublish` skips the KaireonAI approval workflow entirely. Only enable this for content sources that have their own review process.
</Warning>

### Creating a Content Source

```json POST /api/v1/content-sources theme={null}
{
  "name": "Corporate Blog - Contentful",
  "provider": "contentful",
  "config": {
    "spaceId": "abc123",
    "accessToken": "••••••••",
    "environment": "master"
  },
  "syncMode": "webhook",
  "autoPublish": false,
  "mappings": {
    "title": "name",
    "body": "content.html",
    "heroImage": "content.imageUrl"
  }
}
```

<Note>
  Only **admin** users can create or modify content sources. Editors and viewers can list existing sources but cannot change them.
</Note>

## Personalization Variables

Content items support dynamic personalization using `{{variable}}` syntax. At delivery time, KaireonAI replaces variables with actual values from several sources.

| Source             | Syntax                      | Example                          | Description                                    |
| ------------------ | --------------------------- | -------------------------------- | ---------------------------------------------- |
| Customer fields    | `{{customer.field_name}}`   | `{{customer.first_name}}`        | Enriched data from schema tables               |
| Offer fields       | `{{offer.field_name}}`      | `{{offer.name}}`                 | Fields from the recommended offer              |
| Computed values    | `{{computed.field_name}}`   | `{{computed.personalized_rate}}` | Values calculated by the formula engine        |
| Request attributes | `{{attributes.field_name}}` | `{{attributes.tier}}`            | Attributes passed in the Recommend API request |

### Fallback Values

Define a default fallback value for each variable in case the source data is missing. For example, set `{{customer.first_name}}` with a fallback of `"Valued Customer"` so the message reads naturally when the customer's name is unavailable.

Fallback values are configured in the `personalization` array on the content item, where each entry specifies the variable name, source, and default value.

## Content Item Field Reference

| Field              | Type             | Description                                               |
| ------------------ | ---------------- | --------------------------------------------------------- |
| `id`               | string           | Unique identifier (auto-generated)                        |
| `tenantId`         | string           | Tenant this item belongs to                               |
| `name`             | string           | Display name (1-255 chars, unique per tenant)             |
| `description`      | string \| null   | Optional description (max 1000 chars)                     |
| `channelType`      | enum             | One of the eight content types listed above               |
| `status`           | enum             | `draft`, `in_review`, `approved`, `published`, `archived` |
| `content`          | object           | Channel-specific content payload (key-value pairs)        |
| `blocks`           | array \| null    | Structured content blocks for visual editors              |
| `personalization`  | array \| null    | Personalization variable definitions with fallbacks       |
| `parentTemplateId` | string \| null   | ID of the template this item was created from             |
| `isTemplate`       | boolean          | Whether this item is a reusable template                  |
| `sourceType`       | enum             | `internal`, `wordpress`, `contentful`, `strapi`, `sanity` |
| `externalId`       | string \| null   | ID in the external CMS (for synced content)               |
| `sourceId`         | string \| null   | Reference to the ContentSource record                     |
| `version`          | number           | Current version number                                    |
| `publishedAt`      | datetime \| null | When the item was last published                          |
| `createdAt`        | datetime         | Creation timestamp                                        |
| `updatedAt`        | datetime         | Last modification timestamp                               |

## API Quick Reference

### Create a Content Item

```json POST /api/v1/content theme={null}
{
  "name": "Spring Promo - Email Header",
  "channelType": "email_html",
  "content": {
    "subject": "Your exclusive spring offer, {{customer.first_name}}",
    "html": "<h1>Spring Sale</h1><p>Save {{computed.discount_pct}}% today.</p>"
  },
  "personalization": [
    { "variable": "customer.first_name", "fallback": "Valued Customer" },
    { "variable": "computed.discount_pct", "fallback": "20" }
  ],
  "isTemplate": false
}
```

**Response:** `201 Created` with the full content item. Status is automatically set to `draft`.

**Roles:** `admin`, `editor`

### Approve Content

```bash theme={null}
POST /api/v1/content/{id}/approve
```

Moves an `in_review` item to `approved`. The approver cannot be the same user who submitted the item.

**Response:** `200 OK` with the updated content item.

**Roles:** `admin`, `editor`

### Reject Content

```json POST /api/v1/content/{id}/reject theme={null}
{
  "feedback": "Please update the legal disclaimer to the latest version."
}
```

Moves an `in_review` item back to `draft`. Feedback is required (1-2000 characters).

**Response:** `200 OK` with the updated content item.

**Roles:** `admin`, `editor`

### Publish Content

```bash theme={null}
POST /api/v1/content/{id}/publish
```

Moves an `approved` item to `published`. Sets `publishedAt` and creates a version snapshot.

**Response:** `200 OK` with the updated content item.

**Roles:** `admin`, `editor`

### List Versions

```bash theme={null}
GET /api/v1/content/{id}/versions
```

Returns up to 100 versions of the content item, ordered by most recent first.

**Response:** `200 OK` with an array of version objects.

**Roles:** `viewer`, `editor`, `admin`

### List Content Items

```bash theme={null}
GET /api/v1/content?status=published&channelType=email_html&isTemplate=false
```

All query parameters are optional. Supports cursor-based pagination.

| Parameter     | Type    | Description                                                                  |
| ------------- | ------- | ---------------------------------------------------------------------------- |
| `status`      | string  | Filter by status (`draft`, `in_review`, `approved`, `published`, `archived`) |
| `channelType` | string  | Filter by channel type                                                       |
| `isTemplate`  | boolean | Filter templates vs. content items                                           |
| `sourceType`  | string  | Filter by source (`internal`, `wordpress`, etc.)                             |

**Roles:** `viewer`, `editor`, `admin`

## Related

<CardGroup cols={3}>
  <Card title="Creatives" icon="palette" href="/studio/creatives">
    Tie content to specific offer-channel combinations.
  </Card>

  <Card title="Channels" icon="paper-plane" href="/studio/channels">
    Configure delivery mechanisms for your content.
  </Card>

  <Card title="Compliance & Approvals" icon="shield-check" href="/governance-security/compliance">
    Governance workflows for production changes.
  </Card>
</CardGroup>
