> ## 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.

# Creatives

> Content variants that define how an offer is presented to a customer on a specific channel.

<Note>
  **See also**: [Creatives REST API reference](/api-reference/creatives) for request/response shapes, status codes, and error semantics.
</Note>

## Overview

A **creative** is a content variant that defines how a specific offer is rendered on a specific channel. Creatives contain the actual messaging — subject lines, headlines, body copy, images, and calls-to-action — along with personalization variables and A/B test configuration.

Each creative links one **[offer](/studio/offers)** to one **[channel](/studio/channels)**, allowing the same offer to have different presentations across email, push, web, and other delivery mechanisms.

## Field Reference

| Field             | Type    | Required | Default        | Description                                                                   |
| ----------------- | ------- | -------- | -------------- | ----------------------------------------------------------------------------- |
| `name`            | string  | Yes      | —              | Internal name for the creative (1–255 chars)                                  |
| `offerId`         | string  | Yes      | —              | The offer this creative presents                                              |
| `channelId`       | string  | Yes      | —              | The channel this creative is delivered through                                |
| `placementId`     | string  | No       | `null`         | Optional placement slot within the channel                                    |
| `status`          | enum    | No       | `"draft"`      | Lifecycle status: `draft`, `active`, `paused`, `archived`                     |
| `templateType`    | string  | No       | `"email_html"` | Content format template (see Template Types below)                            |
| `content`         | object  | No       | `{}`           | The actual content payload (subject, headline, body, etc.)                    |
| `personalization` | array   | No       | `[]`           | Dynamic variable substitutions (up to 500 items)                              |
| `constraints`     | object  | No       | `{}`           | Frequency caps, cooldown periods, and delivery constraints                    |
| `abTestVariant`   | string  | No       | `null`         | A/B test variant assignment (e.g., `"control"`, `"variant_a"`, `"variant_b"`) |
| `weight`          | integer | No       | `100`          | Traffic allocation weight for the variant (0–100)                             |
| `metrics`         | object  | No       | `{}`           | Performance metrics (impressions, clicks, conversions)                        |

## Template Types

| Type                | Channel  | Description                               |
| ------------------- | -------- | ----------------------------------------- |
| `email_html`        | Email    | Full HTML email template                  |
| `email_text`        | Email    | Plain text email fallback                 |
| `push_notification` | Push     | Title + body + optional image             |
| `sms_text`          | SMS      | Plain text message (160 char recommended) |
| `in_app_banner`     | In-App   | Banner with image, headline, CTA          |
| `in_app_modal`      | In-App   | Full-screen modal overlay                 |
| `in_app_card`       | In-App   | Card-style recommendation                 |
| `web_banner`        | Web      | Website banner ad                         |
| `web_overlay`       | Web      | Popup/overlay                             |
| `webhook_payload`   | Webhook  | Custom JSON payload                       |
| `whatsapp_template` | WhatsApp | WhatsApp Business template                |

## Content Object

The `content` object varies by template type, but common fields include:

```json theme={null}
{
  "subject": "You're pre-approved for our Premium Card",
  "headline": "Upgrade to 3x Rewards",
  "body": "Hi {{first_name}}, based on your spending patterns...",
  "imageUrl": "https://cdn.example.com/premium-card.png",
  "ctaText": "Apply Now",
  "ctaUrl": "https://example.com/apply?offer={{offer_id}}",
  "deepLink": "myapp://offers/premium-card"
}
```

| Field      | Description                                              |
| ---------- | -------------------------------------------------------- |
| `subject`  | Email subject line or notification title                 |
| `headline` | Primary heading text                                     |
| `body`     | Main message body (supports `{{variable}}` placeholders) |
| `imageUrl` | URL to hero image or thumbnail                           |
| `ctaText`  | Call-to-action button text                               |
| `ctaUrl`   | Click-through destination URL                            |
| `deepLink` | Mobile app deep link URI                                 |

## Personalization Variables

Personalization variables inject dynamic values into the content at delivery time:

```json theme={null}
{
  "personalization": [
    {
      "variable": "first_name",
      "source": "customer.first_name",
      "fallback": "Valued Customer"
    },
    {
      "variable": "offer_rate",
      "source": "computed.personalized_rate",
      "fallback": "competitive"
    },
    {
      "variable": "offer_id",
      "source": "offer.id",
      "fallback": ""
    }
  ]
}
```

| Field      | Description                                                                 |
| ---------- | --------------------------------------------------------------------------- |
| `variable` | Placeholder name used in content (referenced as `{{variable}}`)             |
| `source`   | Data source path — `customer.*`, `computed.*`, `offer.*`, or `attributes.*` |
| `fallback` | Default value if the source is null or unavailable                          |

<Tip>
  Use `computed.*` sources to inject [dynamic computed values](/tutorials/computed-values) like personalized rates or custom pricing into creative content.
</Tip>

## A/B Test Variants

Creatives support A/B testing by assigning each creative a variant label and traffic weight:

| Variant     | Description                                         |
| ----------- | --------------------------------------------------- |
| `control`   | The baseline creative (existing or default content) |
| `variant_a` | First test variant                                  |
| `variant_b` | Second test variant                                 |

Traffic is split according to the `weight` field on each creative. Weights are relative — if control has weight 50 and variant\_a has weight 50, traffic is split 50/50.

```json theme={null}
[
  { "name": "Email v1 - Control", "abTestVariant": "control", "weight": 50 },
  { "name": "Email v1 - New CTA", "abTestVariant": "variant_a", "weight": 30 },
  { "name": "Email v1 - Short Copy", "abTestVariant": "variant_b", "weight": 20 }
]
```

### A/B Variant Weight Resolution

At runtime, the decision engine normalizes variant weights to select which creative a customer sees:

1. **Collection** — All active creatives for the same offer + channel are grouped.
2. **Normalization** — Weights are summed and each creative's probability is calculated as `weight / totalWeight`. For the example above: control = 50/100 (50%), variant\_a = 30/100 (30%), variant\_b = 20/100 (20%).
3. **Selection** — A deterministic hash of the customer ID is used to pick a variant, ensuring the same customer always sees the same creative across requests.
4. **Fallback** — If no `abTestVariant` is set, the creative is treated as a standalone (no A/B split). If all weights are 0, each creative receives equal probability.

<Info>
  A/B test results are analyzed in the [Algorithms](/ai-ml/algorithms) module under Experiments. KaireonAI calculates statistical significance using z-tests on conversion rates.
</Info>

## Constraints

| Field           | Type   | Description                                                        |
| --------------- | ------ | ------------------------------------------------------------------ |
| `frequencyCap`  | number | Maximum total impressions of this creative per customer            |
| `cooldownHours` | number | Minimum hours between consecutive impressions to the same customer |

These creative-level constraints work alongside [contact policies](/decisioning/contact-policies) which apply broader rules across offers, channels, and categories.

Once your creatives are configured, set up decisioning gates to control which customers are eligible to see them.

## Creating a Creative

<Steps>
  <Step title="Navigate to Creatives">
    Go to **Studio > Creatives** in the sidebar.
  </Step>

  <Step title="Click Create Creative">
    Click the **+ New Creative** button.
  </Step>

  <Step title="Select offer and channel">
    Choose the [offer](/studio/offers) this creative presents and the [channel](/studio/channels) it will be delivered through. Optionally select a placement slot.
  </Step>

  <Step title="Choose template type">
    Select the appropriate template type for the channel (e.g., `email_html` for email, `push_notification` for push).
  </Step>

  <Step title="Write content">
    Fill in the content fields: subject, headline, body, image URL, CTA text, and CTA URL. Use `{{variable}}` placeholders for dynamic content.
  </Step>

  <Step title="Configure personalization">
    Add personalization variables that map placeholders to data sources with fallback values.
  </Step>

  <Step title="Set A/B variant (optional)">
    If running an experiment, assign a variant role (control, variant\_a, variant\_b) and traffic weight.
  </Step>

  <Step title="Set constraints (optional)">
    Configure frequency cap and cooldown hours for this creative.
  </Step>

  <Step title="Save">
    Save the creative. It is available for use in [Decision Flows](/decisioning/decision-flows) immediately.
  </Step>
</Steps>

## API Reference

### Create a Creative

```bash theme={null}
POST /api/v1/creatives
Content-Type: application/json
```

**Request body:**

```json theme={null}
{
  "name": "Premium Card - Email HTML",
  "offerId": "act_abc123",
  "channelId": "ch_mktg_email",
  "placementId": "pl_header",
  "status": "active",
  "templateType": "email_html",
  "content": {
    "subject": "You're pre-approved, {{first_name}}!",
    "headline": "Upgrade to 3x Rewards",
    "body": "Based on your spending of {{monthly_spend}}, you qualify for our Premium Card at {{offer_rate}}% APR.",
    "imageUrl": "https://cdn.example.com/premium-card.png",
    "ctaText": "Apply Now",
    "ctaUrl": "https://example.com/apply?offer={{offer_id}}"
  },
  "personalization": [
    { "variable": "first_name", "source": "customer.first_name", "fallback": "Valued Customer" },
    { "variable": "monthly_spend", "source": "customer.avg_monthly_spend", "fallback": "" },
    { "variable": "offer_rate", "source": "computed.personalized_rate", "fallback": "19.99" },
    { "variable": "offer_id", "source": "offer.id", "fallback": "" }
  ],
  "abTestVariant": "control",
  "weight": 60,
  "constraints": {
    "frequencyCap": 3,
    "cooldownHours": 72
  }
}
```

**Response (201 Created):**

```json theme={null}
{
  "id": "crv_xyz789",
  "name": "Premium Card - Email HTML",
  "offerId": "act_abc123",
  "channelId": "ch_mktg_email",
  "placementId": "pl_header",
  "status": "active",
  "templateType": "email_html",
  "abTestVariant": "control",
  "weight": 60,
  "constraints": {
    "frequencyCap": 3,
    "cooldownHours": 72
  },
  "createdAt": "2026-03-10T14:30:00Z",
  "updatedAt": "2026-03-10T14:30:00Z"
}
```

### List Creatives

```bash theme={null}
GET /api/v1/creatives
```

Filter by `offerId` or `channelId` using query parameters.

### Update a Creative

```bash theme={null}
PUT /api/v1/creatives
```

Pass the creative `id` in the JSON body alongside the fields to update.

### Delete a Creative

```bash theme={null}
DELETE /api/v1/creatives?id=<creativeId>
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Offers" icon="tag" href="/studio/offers">
    Define the offers that creatives present to customers.
  </Card>

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

  <Card title="Decisioning Gates" icon="filter" href="/decisioning/qualification-rules">
    Control who is eligible to receive each offer.
  </Card>

  <Card title="Decision Flows" icon="sitemap" href="/decisioning/decision-flows">
    Build pipelines that select and rank creatives for delivery.
  </Card>
</CardGroup>
