diff --git a/ai-agents/ag-ui-card-messages.mdx b/ai-agents/ag-ui-card-messages.mdx
new file mode 100644
index 000000000..ffc3a5a46
--- /dev/null
+++ b/ai-agents/ag-ui-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your AG-UI BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/ai-agents/ag2-card-messages.mdx b/ai-agents/ag2-card-messages.mdx
new file mode 100644
index 000000000..39c4d0aa0
--- /dev/null
+++ b/ai-agents/ag2-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your AG2 BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/ai-agents/agent-builder/card-messages.mdx b/ai-agents/agent-builder/card-messages.mdx
new file mode 100644
index 000000000..3bc7e8ed2
--- /dev/null
+++ b/ai-agents/agent-builder/card-messages.mdx
@@ -0,0 +1,59 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your agent reply with rich, interactive cards — designed in Card Builder — instead of plain text."
+---
+
+The **Card Messages** tool lets your agent reply with flexible, interactive cards — buttons, images, progress bars, layouts — instead of plain text. You design each card once in [Card Builder](/card-builder/overview) so it always renders uniformly, then tell the agent when to send it.
+
+## Enable the Card Messages tool
+
+1. Open your agent and go to **Tools**.
+2. Find **Card Messages** (a built-in system tool) and toggle it **on**.
+3. A **Design interactive cards with Card Builder** prompt appears — click **Open Card Builder** to start designing.
+
+## How it works
+
+Card Messages is a built-in **system tool**. When you enable it, the agent can call the tool to fetch a **card reference — working examples plus a field reference** (describing the structure documented in the [Card JSON Schema](/card-builder/schema)) — and then generate a conforming card in its reply.
+
+That means the agent *can* compose cards freely — but free-form generation drifts in layout and styling from one reply to the next. To keep every card consistent, **design it once in Card Builder and give the agent the exported JSON** to reuse, as shown below.
+
+
+You supply **what** card to send — the **how** is automatic. Enabling the tool also teaches the agent the format CometChat uses to recognize a card in its reply, so cards render with no extra work. This holds even when you paste a predefined card into the Instructions: keep the tool **on** — that's what supplies the format. With the tool off, pasted card JSON won't render as a card.
+
+
+
+A reply is delivered as an ordered sequence of **elements** — plain-text segments and at most **one card**. So an agent can send a card on its own, or with text before and/or after it, in a single reply. To present multiple sections *inside* the card, use layout elements (`row`, `column`, `grid`, `tabs`, `accordion`) rather than sending a second card.
+
+
+## Design a card and add it to your agent
+
+Once the tool is on, the workflow is:
+
+1. **Design your card** visually in [Card Builder](/card-builder/overview) — see [Building an Order Status Card](/card-builder/example-order-status) for a full walkthrough.
+2. Use **Export → Copy Card JSON** to copy the finished card.
+3. Add the JSON to the agent's **[Instructions](/ai-agents/agent-builder/instructions)** and specify **when** to send it.
+
+
+A fixed card renders exactly as designed. If it includes `{{placeholder}}` variables, instruct the agent to fill them in before sending.
+
+
+
+With several card types, you can return the card JSON from a **[Custom API Tool](/ai-agents/agent-builder/tools/overview)** instead of pasting it into the instructions — keeping the agent's instructions concise and focused.
+
+
+## Design cards in Card Builder
+
+Card Builder is the visual editor where you compose and save your cards.
+
+
+
+ Learn the editor — palette, canvas, elements, actions, and variables.
+
+
+ Build an interactive Order Status card from scratch, step by step.
+
+
+ The complete schema a card's JSON must conform to.
+
+
diff --git a/ai-agents/agno-card-messages.mdx b/ai-agents/agno-card-messages.mdx
new file mode 100644
index 000000000..174a4e8ab
--- /dev/null
+++ b/ai-agents/agno-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your Agno BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/ai-agents/crew-ai-card-messages.mdx b/ai-agents/crew-ai-card-messages.mdx
new file mode 100644
index 000000000..bfa319ba6
--- /dev/null
+++ b/ai-agents/crew-ai-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your CrewAI BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/ai-agents/langgraph-card-messages.mdx b/ai-agents/langgraph-card-messages.mdx
new file mode 100644
index 000000000..58df16be1
--- /dev/null
+++ b/ai-agents/langgraph-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your LangGraph BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/ai-agents/mastra-card-messages.mdx b/ai-agents/mastra-card-messages.mdx
new file mode 100644
index 000000000..56122286e
--- /dev/null
+++ b/ai-agents/mastra-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your Mastra BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/ai-agents/vercel-card-messages.mdx b/ai-agents/vercel-card-messages.mdx
new file mode 100644
index 000000000..13fcca422
--- /dev/null
+++ b/ai-agents/vercel-card-messages.mdx
@@ -0,0 +1,9 @@
+---
+title: "Card Messages"
+sidebarTitle: "Card Messages"
+description: "Let your Vercel AI BYOA agent reply with rich, interactive cards designed in Card Builder."
+---
+
+import CardMessages from '/snippets/ai-agents/card-messages.mdx';
+
+
diff --git a/card-builder/building-cards.mdx b/card-builder/building-cards.mdx
new file mode 100644
index 000000000..175f69288
--- /dev/null
+++ b/card-builder/building-cards.mdx
@@ -0,0 +1,92 @@
+---
+title: "Building Cards"
+sidebarTitle: "Building Cards"
+description: "Walk through the Card Builder editor — the canvas, the element palette, and the properties panel — to design, style, and save a card in the CometChat Dashboard."
+---
+
+This guide walks through designing a card in Card Builder, from a blank canvas to a saved template.
+
+
+
+
+
+## The Editor
+
+Card Builder is organized into three areas:
+
+| Area | What it does |
+| --- | --- |
+| **Palette** (left) | The elements and ready-made components you can add to a card. |
+| **Canvas** (center) | A live preview of your card as you build it. Select an element here to edit it. |
+| **Properties** (right) | Settings for the selected element, the card structure (tree), and overall card style. |
+
+The top bar holds the card name, import and export, undo/redo, and **Save**.
+
+
+
+
+
+## 1. Start a Card
+
+When you open Card Builder, choose a starting point:
+
+- **Template library** — pick a ready-made template (Product Card, Order Confirmation, and more) and customize it.
+- **Blank card** — start from scratch.
+
+
+
+
+
+## 2. Add Elements
+
+Click an element in the palette to add it to your card. New elements are placed relative to your current selection — inside a selected layout element, or after the selected element. You can add content such as text, images, and buttons, and arrange them using layout elements like rows, columns, and grids. For the full list, see [Elements & Actions](/card-builder/elements).
+
+You can also add a **component** — a pre-built group of elements (for example a product card or an order timeline) — and then edit its pieces.
+
+## 3. Arrange the Layout
+
+By default, elements stack vertically. To change the layout:
+
+- **Row** — place elements side by side.
+- **Column** — group elements vertically inside a row.
+- **Grid** — arrange elements in a grid.
+- **Carousel** — let users scroll horizontally through items.
+
+Use the structure tree in the properties panel to drag elements into a new order, nest them inside layouts, or remove them.
+
+## 4. Style the Card
+
+Select an element to edit its properties, or click an empty area of the card to edit the overall **card style**:
+
+- **Background** — set a fill color, or make it transparent.
+- **Corner radius** — round the card's corners.
+- **Border** — add a border color and width.
+- **Padding** — control the spacing inside the card.
+
+### Light and Dark Mode
+
+Colors are set separately for **light** and **dark** mode, so your card looks right in both. You can set a color for one mode and leave the other transparent.
+
+## 5. Make It Interactive
+
+Add an **action** to a button, icon button, link, or chip so it does something when tapped — open a URL, start a chat, send a message, make a call, and more. See [Elements & Actions](/card-builder/elements#actions) for the full list.
+
+## 6. Use Variables
+
+Insert [variables](/card-builder/elements#variables) — placeholders such as `{{user.name}}` or `{{order.id}}` — from the variable picker wherever you enter text or a URL. They're filled with real values when the card is sent, so a single card personalizes for every recipient. Available variables depend on where the card is used.
+
+## 7. Notifications (Push)
+
+A card is a message in CometChat. When that message triggers a push notification, the push can't show the full rich card — so the **Notification** tab is where you define the **notification text** for the message: the title and body shown in the push. A device preview shows how it will appear, and you can insert [variables](#6-use-variables) into the title and body so the notification is personalized per recipient.
+
+
+
+
+
+## 8. Save
+
+Give the card a name in the top bar and click **Save**. Saved cards are stored as templates so you can open them again from the template library, edit them, and reuse them.
+
+---
+
+Next: [Elements & Actions](/card-builder/elements) — a reference of everything you can add to a card.
diff --git a/card-builder/elements.mdx b/card-builder/elements.mdx
new file mode 100644
index 000000000..678c0b3ce
--- /dev/null
+++ b/card-builder/elements.mdx
@@ -0,0 +1,91 @@
+---
+title: "Elements & Actions"
+sidebarTitle: "Elements & Actions"
+description: "A reference of everything a card can contain — content, layout, and interactive elements, the actions a card can trigger, and the ready-made components you can add to a card."
+---
+
+A card is made up of **elements** arranged on the canvas. Interactive elements can trigger **actions**, and **components** give you ready-made groups of elements to start from. This page lists what's available.
+
+## Elements
+
+### Content
+
+| Element | Description |
+| --- | --- |
+| **Text** | A line or paragraph of text, with heading and body styles. |
+| **Markdown** | Rich text written in Markdown. |
+| **Image** | An image from a URL. |
+| **Icon** | An icon from the built-in library or a custom image. |
+| **Avatar** | A circular user or entity image. |
+| **Badge** | A small label, often for status or counts. |
+| **Chip** | A compact, tappable tag. |
+| **Code block** | Pre-formatted, monospaced text. |
+
+### Layout
+
+| Element | Description |
+| --- | --- |
+| **Row** | Arranges elements side by side. |
+| **Column** | Groups elements vertically, usually inside a row. |
+| **Grid** | Arranges elements in a grid. |
+| **Accordion** | Collapsible sections that expand on tap. |
+| **Tabs** | Switch between sections of content. |
+| **Divider** | A horizontal line to separate content. |
+| **Spacer** | Empty space to control vertical rhythm. |
+
+Rows, columns, and grids can also have their own background color, corner radius, and border.
+
+### Interactive
+
+| Element | Description |
+| --- | --- |
+| **Button** | A labeled button that triggers an action. |
+| **Icon button** | An icon-only button that triggers an action. |
+| **Link** | Tappable text that triggers an action. |
+
+### Data
+
+| Element | Description |
+| --- | --- |
+| **Table** | Rows and columns of structured data. |
+| **Progress bar** | A visual indicator of progress. |
+
+## Actions
+
+Add an action to a button, icon button, link, or chip to make it interactive. When a user taps the element, the action runs.
+
+| Action | What it does |
+| --- | --- |
+| **Open URL** | Opens a web address. |
+| **Chat with user** | Starts a one-to-one conversation with a user. |
+| **Chat with group** | Opens a group conversation. |
+| **Send message** | Sends a message on the user's behalf. |
+| **Copy to clipboard** | Copies text to the clipboard. |
+| **Download file** | Downloads a file. |
+| **Initiate call** | Starts a voice or video call. |
+| **API call** | Makes a request to a configured endpoint. |
+| **Custom callback** | Triggers custom handling in your app. |
+
+## Variables
+
+Variables are placeholders you insert into text and URL fields, written as `{{name}}` (for example `{{user.name}}`). They're replaced with real values when the card is sent, letting one card adapt to each recipient. Insert them from the variable picker wherever you enter text.
+
+## Components
+
+Components are pre-built groups of elements you can add to a card and then edit. They're a fast way to start a common card:
+
+| Component | Use case |
+| --- | --- |
+| **Product Card** | A product with image, details, and a call to action. |
+| **Order Confirmation** | Order summary with status. |
+| **Order Tracking** | A delivery timeline. |
+| **Event Card** | Event details with date and location. |
+| **Announcement** | News or an update. |
+| **Quick Reply Buttons** | Tappable response options. |
+| **Feedback** | A quick rating or response prompt. |
+| **Data Table** | Structured rows of data. |
+| **Carousel** | A horizontally scrollable set of cards. |
+
+## Fallback Text
+
+Every card includes **fallback text** — what a CometChat UI Kit renders if it can't display the card itself (for example, if the card JSON is malformed or the client doesn't support cards). Always set it so the message still conveys its meaning.
diff --git a/card-builder/example-order-status.mdx b/card-builder/example-order-status.mdx
new file mode 100644
index 000000000..007e9728c
--- /dev/null
+++ b/card-builder/example-order-status.mdx
@@ -0,0 +1,98 @@
+---
+title: "Building an Order Status Card"
+sidebarTitle: "Building an Order Status Card"
+description: "Step-by-step guide to building an interactive Order Status card from scratch in Card Builder — a heading, a progress bar, status rows with variables, a divider, and two action buttons in a row."
+---
+
+This guide builds an **Order Status** card from a blank canvas — the kind of card you might send when a customer's order ships. You'll add each element yourself: a heading, a progress bar, three status rows driven by variables, a divider, and two action buttons side by side.
+
+## What You'll Build
+
+A single card that shows order status at a glance and lets the customer act on it:
+
+- An **Order Status** heading (heading style)
+- A **progress bar** labelled **In Transit**, filled to the current stage
+- Three rows — **Status**, **ETA**, and **Tracking #** — filled from `{{order.*}}` variables
+- A **divider**
+- Two buttons in a **row** — **Track** and **Contact Support**
+
+## Prerequisites
+
+- Access to **Card Builder** in your app — see [Overview](/card-builder/overview) for how to open it.
+- Familiarity with the editor layout — see [Building Cards](/card-builder/building-cards).
+
+## Steps
+
+### Step 1 — Start a blank card
+
+In the template library, click **+ New Card**. The editor opens with an empty canvas ("Click an element or component to add it here"). Switch the left palette to the **Elements** tab — elements are grouped under **Layout**, **Content**, **Data Display**, and **Actions**.
+
+### Step 2 — Add the heading
+
+From **Content**, click **Text** to add it, then in the **Element** tab set its content to `Order Status` and change its **Variant** to **heading2**.
+
+
+
+
+
+### Step 3 — Add the progress bar and status rows
+
+From **Data Display**, add a **Progress Bar**. In the Element tab set its **Value** to `60` and its **Label** to `In Transit` (the label renders just below the heading).
+
+Then add three more **Text** elements and, in each, type the label and insert a [variable](/card-builder/building-cards#6-use-variables) from the variable picker:
+
+| Text element | Content |
+| --- | --- |
+| Status | `Status: {{order.status}}` |
+| ETA | `ETA: {{order.eta}}` |
+| Tracking # | `Tracking #: {{order.trackingNumber}}` |
+
+Variables are resolved to real values when the card is sent, so one card personalizes for every order.
+
+
+
+
+
+### Step 4 — Add a divider and the buttons
+
+From **Layout**, add a **Divider**. Then add a **Row** so the buttons sit side by side — with the row selected, add a **Button** (it nests inside the row) and set its label to `Track`. Select the row again, add a second **Button**, and label it `Contact Support`.
+
+
+
+
+
+### Step 5 — Give the buttons their actions
+
+Select a button, scroll to the **Action** section, and choose an [action](/card-builder/elements#actions):
+
+- **Track** → **Open URL**, with the URL `https://example.com/track/{{order.trackingNumber}}` (variables work in URLs too).
+- **Contact Support** → **Chat with user**, with the support agent's user ID.
+
+
+
+
+
+### Step 6 — Set the message type and fallback text
+
+Open the **Card** tab. Set the message **Type** to `order_status` — a meaningful identifier your app can use to recognize this kind of card (it defaults to `custom_type`).
+
+Then fill in **Fallback Text**. This is what a CometChat UI Kit renders if it ever **can't display the card itself** — for example if the card JSON is malformed or the client doesn't support cards — so the message still conveys its meaning. Because the card (and its buttons) won't be shown in that case, write plain copy that **stands on its own** and doesn't reference interactive elements like "tap Track". For this card:
+
+> Your order is in transit. We'll notify you when it's out for delivery.
+
+
+
+
+
+### Step 7 — Save
+
+Give the card a name (for example, **Order Status**) in the top bar and click **Save**. It now appears under **Saved Templates** and can be reused or edited any time.
+
+
+
+
+
+## Next steps
+
+- Browse what else a card can hold in [Elements & Actions](/card-builder/elements).
+- Reuse this card as a [saved template](/card-builder/building-cards#8-save) for future orders.
diff --git a/card-builder/overview.mdx b/card-builder/overview.mdx
new file mode 100644
index 000000000..a6188baa3
--- /dev/null
+++ b/card-builder/overview.mdx
@@ -0,0 +1,50 @@
+---
+title: "CometChat Card Builder"
+sidebarTitle: "Overview"
+description: "Card Builder is a visual tool in the CometChat Dashboard for designing rich, interactive card messages — product cards, order confirmations, quick replies, and more — that your CometChat UI Kits render natively."
+---
+
+Card Builder is a visual tool in the [CometChat Dashboard](https://app.cometchat.com) for designing **card messages** — structured, interactive messages such as product cards, order confirmations, event invites, and quick-reply prompts.
+
+Instead of sending plain text, you compose a card visually and CometChat UI Kits render it natively in your chat — with images, buttons, layouts, and actions that respond when a user taps them.
+
+
+
+
+
+With Card Builder, you can:
+
+- **Design cards visually** — add text, images, buttons, and layouts and see them on a live canvas.
+- **Add interactivity** — wire buttons and links to actions like opening a URL, starting a chat, or making a call.
+- **Use variables** — insert placeholders such as `{{user.name}}` that are filled in when the card is sent.
+- **Preview in light and dark mode** — set colors for each mode and see the result instantly.
+- **Save and reuse templates** — store finished cards and load them again whenever you need them.
+
+## What You Can Build
+
+Start from a blank card, or from a ready-made template — Product Card, Order Confirmation, Order Tracking, Event Card, Announcement, Quick Reply Buttons, and more. See the full set in [Components](/card-builder/elements#components).
+
+## How to Open Card Builder
+
+Card Builder opens in a new browser tab from the dashboard:
+
+- **For chat** — open your app in the [CometChat Dashboard](https://app.cometchat.com), expand **Chat & Messaging** in the sidebar, and select **Card Builder**.
+- **For an AI Agent** — open your agent and select **Card Builder** from the agent configuration menu.
+
+
+
+
+
+
+Card Builder is available to app owners, admins, and developers.
+
+
+## The Design Workflow
+
+1. **Choose a starting point** — open a blank card or a template from the library.
+2. **Build the card** — add elements from the palette and arrange them with rows, columns, and grids.
+3. **Style and preview** — set colors, spacing, and corner radius, and preview in light and dark mode.
+4. **Add actions and variables** — make buttons interactive and insert `{{placeholder}}` values.
+5. **Save** — save the card as a template to reuse it later.
+
+Continue to [Building Cards](/card-builder/building-cards) for a walkthrough of the editor, or see [Elements & Actions](/card-builder/elements) for everything a card can contain.
diff --git a/card-builder/schema.mdx b/card-builder/schema.mdx
new file mode 100644
index 000000000..a2b91064d
--- /dev/null
+++ b/card-builder/schema.mdx
@@ -0,0 +1,1666 @@
+---
+title: "Card JSON Schema"
+sidebarTitle: "JSON Schema"
+description: "The complete JSON schema a card must conform to — for developers generating cards programmatically, such as from a BYOA agent or a Custom API Tool."
+---
+
+Every card is a JSON document that conforms to the **CometChat Card Message Schema**. [Card Builder](/card-builder/overview) produces conforming JSON automatically, so you only need this page if you generate cards **programmatically** — for example, from a [BYOA agent](/ai-agents/cometchat-ag-ui-byoa) or a [Custom API Tool](/ai-agents/agent-builder/tools/overview).
+
+The schema is **Draft-07**.
+
+
+Data placeholders (`{{variable}}`) must be **resolved before the card is sent** — the backend passes the JSON through as-is and does not substitute them.
+
+
+## Root structure
+
+| Field | Required | Type | Notes |
+| --- | --- | --- | --- |
+| `version` | Yes | string | Always `"1.0"` (the string, not a number). |
+| `body` | Yes | array | The card's elements, rendered top to bottom. Must be non-empty. |
+| `style` | Yes | object | Card-level style. Its `background` is required; `borderRadius`, `borderColor`, `borderWidth`, `padding` are optional. |
+| `fallbackText` | Yes | string | Plain text shown when a client can't render the card. Always set it. |
+
+```jsonc
+{
+ "version": "1.0",
+ "style": { "background": { "light": "#FFFFFF", "dark": "#1C1C1E" } },
+ "body": [ /* one or more elements */ ],
+ "fallbackText": "Your order #1234 has shipped"
+}
+```
+
+
+**Push notifications are not part of the card.** When a card is sent, the *message's* `data.text` carries the push/preview text — set from the **Notification** tab in Card Builder, falling back to `fallbackText`. The card JSON itself has no notification field.
+
+
+## Colors
+
+Color fields are **objects with explicit light- and dark-mode values**, so a card looks right in both themes. Each side is a 6-digit hex string or `"transparent"`:
+
+```jsonc
+"background": { "light": "#FFFFFF", "dark": "#1C1C1E" }
+```
+
+Use `"transparent"` to apply no color for one mode while setting the other, and **omit the property entirely** if you don't need a color override (where allowed — note `style.background` is required).
+
+## Elements
+
+Every element needs a unique `id` and a `type`. The `type` determines its other required fields. No element may include properties not defined for its type (`additionalProperties: false`).
+
+| Element `type` | Required fields (besides `id`/`type`) |
+| --- | --- |
+| `text` | `content` |
+| `markdown` | `content` |
+| `image` | `url` |
+| `icon` | `name` or `url` (at least one) |
+| `avatar` | — |
+| `badge` | `text` |
+| `chip` | `text` |
+| `codeBlock` | `content` |
+| `divider` | — |
+| `spacer` | `height` |
+| `row` | `items` (non-empty) |
+| `column` | `items` (non-empty) |
+| `grid` | `items` (non-empty) |
+| `accordion` | `header`, `body` (non-empty) |
+| `tabs` | `tabs` (non-empty, each `{ label, content }`) |
+| `button` | `label`, `action` |
+| `iconButton` | `icon`, `action` |
+| `link` | `text`, `action` |
+| `table` | `columns` (non-empty), `rows` |
+| `progressBar` | `value` (0–100) |
+
+For a description of each element, see [Elements & Actions](/card-builder/elements).
+
+## Actions
+
+Add an `action` to a `button`, `iconButton`, `link`, or `chip`. Every action needs a `type` plus its required fields.
+
+| Action `type` | Required fields |
+| --- | --- |
+| `openUrl` | `url` (optional `openIn`: `browser` \| `webview`) |
+| `chatWithUser` | `uid` |
+| `chatWithGroup` | `guid` |
+| `sendMessage` | `text` |
+| `copyToClipboard` | `value` |
+| `downloadFile` | `url` |
+| `initiateCall` | `callType` (`audio` \| `video`) **and** `uid` or `guid` |
+| `apiCall` | `url` (optional `method`, `headers`, `body`) |
+| `customCallback` | — (just `type`) |
+
+## Variables
+
+Insert variables as `{{name}}` (for example `{{user.name}}`, `{{order.id}}`) into text and URL fields. They personalize a single card per recipient, but **must be resolved before sending** — when an agent sends a card, instruct it to fill them in first.
+
+## Full JSON Schema
+
+This is the complete schema. Validate generated cards against it (any Draft-07 validator, e.g. Ajv) before sending.
+
+
+```json
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://schema.cometchat.com/card/v1.0",
+ "title": "CometChat Card Message Schema",
+ "description": "Schema for rich, interactive message cards rendered natively by CometChat UI Kits. Used by the Dashboard Card Builder, external developers via API, and AI Agents for structured message generation. Data placeholders ({{variable}}) must be resolved before sending — the backend passes JSON through as-is.",
+ "type": "object",
+ "required": [
+ "version",
+ "body",
+ "style",
+ "fallbackText"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "type": "string",
+ "const": "1.0",
+ "description": "Schema version. Always '1.0' for this release."
+ },
+ "body": {
+ "type": "array",
+ "description": "Ordered list of elements rendered top-to-bottom (vertical stack). This is always vertical. Use 'row' for horizontal, 'grid' for grid, or 'carousel' for scrollable horizontal layout.",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/definitions/element"
+ }
+ },
+ "style": {
+ "$ref": "#/definitions/cardStyle"
+ },
+ "fallbackText": {
+ "type": "string",
+ "description": "Plain text shown on older UI Kit versions that cannot render cards. Required for graceful degradation."
+ }
+ },
+ "definitions": {
+ "padding": {
+ "description": "Padding. Single number applies to all sides, or specify per-side.",
+ "oneOf": [
+ {
+ "type": "number",
+ "minimum": 0
+ },
+ {
+ "type": "object",
+ "properties": {
+ "top": {
+ "type": "number",
+ "minimum": 0
+ },
+ "right": {
+ "type": "number",
+ "minimum": 0
+ },
+ "bottom": {
+ "type": "number",
+ "minimum": 0
+ },
+ "left": {
+ "type": "number",
+ "minimum": 0
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ },
+ "sizeOrPercentage": {
+ "description": "Size in pixels (number) or percentage string (e.g. '50%').",
+ "oneOf": [
+ {
+ "type": "number",
+ "minimum": 0
+ },
+ {
+ "type": "string",
+ "pattern": "^\\d+(\\.\\d+)?%$"
+ }
+ ]
+ },
+ "colorSide": {
+ "description": "A single color side value — either a 6-digit hex or 'transparent' for transparent/default.",
+ "oneOf": [
+ {
+ "type": "string",
+ "pattern": "^#[0-9A-Fa-f]{6}$",
+ "description": "6-digit hex color for this mode."
+ },
+ {
+ "type": "string",
+ "const": "transparent",
+ "description": "Transparent/default — no color override for this mode."
+ }
+ ]
+ },
+ "colorValue": {
+ "type": "object",
+ "description": "Color value with explicit light and dark mode values. Each side is either a 6-digit hex or 'transparent'. Use 'transparent' to apply no color for a specific mode while setting a color for the other. Omit the property entirely if no color override is needed for either mode.",
+ "required": [
+ "light",
+ "dark"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "light": {
+ "$ref": "#/definitions/colorSide",
+ "description": "Color for light mode."
+ },
+ "dark": {
+ "$ref": "#/definitions/colorSide",
+ "description": "Color for dark mode."
+ }
+ }
+ },
+ "iconRef": {
+ "type": "object",
+ "description": "Reference to an icon. Use 'name' for built-in icons from the icon library, or 'url' for custom icon URLs. At least one must be provided. If both are present, 'url' takes precedence for rendering while 'name' serves as a fallback identifier.",
+ "anyOf": [
+ {
+ "required": [
+ "name"
+ ]
+ },
+ {
+ "required": [
+ "url"
+ ]
+ }
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Icon name from the built-in icon library (e.g. 'check', 'star', 'calendar_today')."
+ },
+ "url": {
+ "type": "string",
+ "description": "Direct URL to the icon image asset. Takes precedence over 'name' for rendering."
+ }
+ }
+ },
+ "action": {
+ "description": "An action triggered by user interaction (button tap, link click, toggle change).",
+ "oneOf": [
+ {
+ "type": "object",
+ "title": "openUrl",
+ "required": [
+ "type",
+ "url"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "openUrl"
+ },
+ "url": {
+ "type": "string",
+ "description": "URL to open. Supports {{placeholder}}."
+ },
+ "openIn": {
+ "type": "string",
+ "enum": [
+ "browser",
+ "webview"
+ ],
+ "default": "browser"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "chatWithUser",
+ "required": [
+ "type",
+ "uid"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "chatWithUser"
+ },
+ "uid": {
+ "type": "string",
+ "description": "CometChat user uid."
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "chatWithGroup",
+ "required": [
+ "type",
+ "guid"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "chatWithGroup"
+ },
+ "guid": {
+ "type": "string",
+ "description": "CometChat group guid."
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "sendMessage",
+ "required": [
+ "type",
+ "text"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "sendMessage"
+ },
+ "text": {
+ "type": "string"
+ },
+ "receiverUid": {
+ "type": "string",
+ "description": "Send to a specific user. If omitted along with receiverGuid, sends in the current conversation."
+ },
+ "receiverGuid": {
+ "type": "string",
+ "description": "Send to a specific group. If omitted along with receiverUid, sends in the current conversation."
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "copyToClipboard",
+ "required": [
+ "type",
+ "value"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "copyToClipboard"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "downloadFile",
+ "required": [
+ "type",
+ "url"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "downloadFile"
+ },
+ "url": {
+ "type": "string"
+ },
+ "filename": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "initiateCall",
+ "required": [
+ "type",
+ "callType"
+ ],
+ "anyOf": [
+ {
+ "required": [
+ "uid"
+ ]
+ },
+ {
+ "required": [
+ "guid"
+ ]
+ }
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "initiateCall"
+ },
+ "uid": {
+ "type": "string",
+ "description": "User uid for 1:1 call."
+ },
+ "guid": {
+ "type": "string",
+ "description": "Group guid for group call."
+ },
+ "callType": {
+ "type": "string",
+ "enum": [
+ "audio",
+ "video"
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "apiCall",
+ "required": [
+ "type",
+ "url"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "apiCall"
+ },
+ "url": {
+ "type": "string"
+ },
+ "method": {
+ "type": "string",
+ "enum": [
+ "GET",
+ "POST",
+ "PUT",
+ "DELETE"
+ ],
+ "default": "POST"
+ },
+ "headers": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "body": {
+ "type": "object"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "title": "customCallback",
+ "required": [
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "customCallback"
+ }
+ }
+ }
+ ]
+ },
+ "element": {
+ "description": "A UI element inside a card. Discriminated by the 'type' field.",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/elements/text"
+ },
+ {
+ "$ref": "#/definitions/elements/image"
+ },
+ {
+ "$ref": "#/definitions/elements/icon"
+ },
+ {
+ "$ref": "#/definitions/elements/avatar"
+ },
+ {
+ "$ref": "#/definitions/elements/badge"
+ },
+ {
+ "$ref": "#/definitions/elements/divider"
+ },
+ {
+ "$ref": "#/definitions/elements/spacer"
+ },
+ {
+ "$ref": "#/definitions/elements/chip"
+ },
+ {
+ "$ref": "#/definitions/elements/progressBar"
+ },
+ {
+ "$ref": "#/definitions/elements/codeBlock"
+ },
+ {
+ "$ref": "#/definitions/elements/markdown"
+ },
+ {
+ "$ref": "#/definitions/elements/row"
+ },
+ {
+ "$ref": "#/definitions/elements/column"
+ },
+ {
+ "$ref": "#/definitions/elements/grid"
+ },
+ {
+ "$ref": "#/definitions/elements/accordion"
+ },
+ {
+ "$ref": "#/definitions/elements/tabs"
+ },
+ {
+ "$ref": "#/definitions/elements/button"
+ },
+ {
+ "$ref": "#/definitions/elements/iconButton"
+ },
+ {
+ "$ref": "#/definitions/elements/link"
+ },
+ {
+ "$ref": "#/definitions/elements/table"
+ }
+ ]
+ },
+ "elements": {
+ "text": {
+ "type": "object",
+ "title": "Text",
+ "description": "Renders text content. Supports data placeholders {{var}}.",
+ "required": [
+ "id",
+ "type",
+ "content"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "text"
+ },
+ "content": {
+ "type": "string",
+ "description": "Text content. Supports {{placeholder}} syntax."
+ },
+ "variant": {
+ "type": "string",
+ "enum": [
+ "title",
+ "heading1",
+ "heading2",
+ "heading3",
+ "heading4",
+ "body",
+ "caption1",
+ "caption2"
+ ],
+ "default": "body",
+ "description": "Typography level: title (32px), heading1 (24px), heading2 (20px), heading3 (18px), heading4 (16px), body (14px), caption1 (12px), caption2 (10px)."
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "align": {
+ "type": "string",
+ "enum": [
+ "left",
+ "center",
+ "right",
+ "justify"
+ ],
+ "default": "left"
+ },
+ "fontWeight": {
+ "type": "string",
+ "enum": [
+ "regular",
+ "medium",
+ "bold"
+ ],
+ "default": "regular",
+ "description": "Maps to UI Kit weights: regular (400), medium (500), bold (700)."
+ },
+ "maxLines": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ }
+ }
+ },
+ "image": {
+ "type": "object",
+ "title": "Image",
+ "description": "Renders an image. URL supports {{placeholder}}.",
+ "required": [
+ "id",
+ "type",
+ "url"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "image"
+ },
+ "url": {
+ "type": "string",
+ "description": "Image source URL. Supports {{placeholder}}."
+ },
+ "altText": {
+ "type": "string"
+ },
+ "fit": {
+ "type": "string",
+ "enum": [
+ "cover",
+ "contain",
+ "fill"
+ ],
+ "default": "cover"
+ },
+ "width": {
+ "$ref": "#/definitions/sizeOrPercentage"
+ },
+ "height": {
+ "$ref": "#/definitions/sizeOrPercentage"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ }
+ }
+ },
+ "icon": {
+ "type": "object",
+ "title": "Icon",
+ "description": "Renders an icon from the icon library or a custom URL. Use 'name' for built-in icons, or 'url' for custom icon URLs. At least one of 'name' or 'url' must be provided.",
+ "required": [
+ "id",
+ "type"
+ ],
+ "anyOf": [
+ {
+ "required": [
+ "name"
+ ]
+ },
+ {
+ "required": [
+ "url"
+ ]
+ }
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "icon"
+ },
+ "name": {
+ "type": "string",
+ "description": "Icon name from the built-in icon library (e.g. 'check', 'star', 'calendar_today')."
+ },
+ "url": {
+ "type": "string",
+ "description": "Direct URL to the icon image asset. Takes precedence over 'name' for rendering."
+ },
+ "size": {
+ "type": "number",
+ "minimum": 0
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Padding around the icon in px."
+ }
+ }
+ },
+ "avatar": {
+ "type": "object",
+ "title": "Avatar",
+ "description": "Renders a user avatar with image or fallback initials.",
+ "required": [
+ "id",
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "avatar"
+ },
+ "imageUrl": {
+ "type": "string",
+ "description": "Avatar image URL. Supports {{placeholder}}."
+ },
+ "fallbackInitials": {
+ "type": "string",
+ "maxLength": 2
+ },
+ "size": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Size in density-independent pixels. Suggested presets: 28 (small), 36 (medium), 48 (large)."
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Corner radius in px. Set to half of size for circle, ~size/4 for rounded."
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue",
+ "description": "Background color for the fallback initials circle."
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size for fallback initials in px."
+ },
+ "fontWeight": {
+ "type": "string",
+ "enum": [
+ "regular",
+ "medium",
+ "bold"
+ ],
+ "description": "Font weight for fallback initials."
+ }
+ }
+ },
+ "badge": {
+ "type": "object",
+ "title": "Badge",
+ "description": "Renders a small label badge (e.g. status, priority).",
+ "required": [
+ "id",
+ "type",
+ "text"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "badge"
+ },
+ "text": {
+ "type": "string"
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "size": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Badge height in px. Suggested presets: 20 (small), 24 (medium)."
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size in px."
+ }
+ }
+ },
+ "divider": {
+ "type": "object",
+ "title": "Divider",
+ "description": "Renders a horizontal line separator.",
+ "required": [
+ "id",
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "divider"
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "thickness": {
+ "type": "number",
+ "minimum": 0
+ },
+ "margin": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Top and bottom margin in px."
+ }
+ }
+ },
+ "spacer": {
+ "type": "object",
+ "title": "Spacer",
+ "description": "Adds vertical empty space.",
+ "required": [
+ "id",
+ "type",
+ "height"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "spacer"
+ },
+ "height": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "chip": {
+ "type": "object",
+ "title": "Chip",
+ "description": "Renders a compact label chip, optionally with an icon.",
+ "required": [
+ "id",
+ "type",
+ "text"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "chip"
+ },
+ "text": {
+ "type": "string"
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "icon": {
+ "$ref": "#/definitions/iconRef",
+ "description": "Optional icon displayed in the chip."
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size in px."
+ }
+ }
+ },
+ "progressBar": {
+ "type": "object",
+ "title": "Progress Bar",
+ "description": "Renders a horizontal progress bar.",
+ "required": [
+ "id",
+ "type",
+ "value"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "progressBar"
+ },
+ "value": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "trackColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "height": {
+ "type": "number",
+ "minimum": 0
+ },
+ "label": {
+ "type": "string"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "labelFontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size for the label text in px."
+ },
+ "labelColor": {
+ "$ref": "#/definitions/colorValue",
+ "description": "Color for the label text."
+ }
+ }
+ },
+ "codeBlock": {
+ "type": "object",
+ "title": "Code Block",
+ "description": "Renders a code snippet with optional syntax highlighting label.",
+ "required": [
+ "id",
+ "type",
+ "content"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "codeBlock"
+ },
+ "content": {
+ "type": "string"
+ },
+ "language": {
+ "type": "string"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "textColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size in px."
+ },
+ "languageLabelFontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size for the language label in px."
+ },
+ "languageLabelColor": {
+ "$ref": "#/definitions/colorValue",
+ "description": "Color for the language label text."
+ }
+ }
+ },
+ "markdown": {
+ "type": "object",
+ "title": "Markdown",
+ "description": "Renders markdown content.",
+ "required": [
+ "id",
+ "type",
+ "content"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "markdown"
+ },
+ "content": {
+ "type": "string"
+ },
+ "baseFontSize": {
+ "type": "number",
+ "minimum": 0
+ },
+ "linkColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "lineHeight": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Line height multiplier (e.g. 1.5)."
+ }
+ }
+ },
+ "row": {
+ "type": "object",
+ "title": "Row",
+ "description": "Horizontal layout container. Children are arranged left-to-right. Use 'scrollable' for horizontal scroll with optional snap and peek (carousel behavior).",
+ "required": [
+ "id",
+ "type",
+ "items"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "row"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/element"
+ },
+ "minItems": 1
+ },
+ "gap": {
+ "type": "number",
+ "minimum": 0
+ },
+ "align": {
+ "type": "string",
+ "enum": [
+ "start",
+ "center",
+ "end",
+ "spaceBetween",
+ "spaceAround"
+ ],
+ "default": "start"
+ },
+ "crossAlign": {
+ "type": "string",
+ "enum": [
+ "start",
+ "center",
+ "end"
+ ],
+ "default": "start",
+ "description": "Cross-axis (vertical) alignment of children within the row."
+ },
+ "wrap": {
+ "type": "boolean",
+ "default": false
+ },
+ "scrollable": {
+ "type": "boolean",
+ "default": false,
+ "description": "Enable horizontal scrolling when items overflow the card width."
+ },
+ "peek": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Pixels of the next item visible when scrollable. Only applies when scrollable is true."
+ },
+ "snap": {
+ "type": "string",
+ "enum": [
+ "item",
+ "free"
+ ],
+ "default": "item",
+ "description": "Snap behavior when scrolling. Only applies when scrollable is true."
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "column": {
+ "type": "object",
+ "title": "Column",
+ "description": "Vertical layout container. Children are arranged top-to-bottom.",
+ "required": [
+ "id",
+ "type",
+ "items"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "column"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/element"
+ },
+ "minItems": 1
+ },
+ "gap": {
+ "type": "number",
+ "minimum": 0
+ },
+ "align": {
+ "type": "string",
+ "enum": [
+ "start",
+ "center",
+ "end",
+ "stretch"
+ ],
+ "default": "start"
+ },
+ "crossAlign": {
+ "type": "string",
+ "enum": [
+ "start",
+ "center",
+ "end"
+ ],
+ "default": "start",
+ "description": "Cross-axis (horizontal) alignment of children within the column."
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "grid": {
+ "type": "object",
+ "title": "Grid",
+ "description": "Grid layout with 2-4 columns. Items fill left-to-right, top-to-bottom.",
+ "required": [
+ "id",
+ "type",
+ "items"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "grid"
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/element"
+ },
+ "minItems": 1
+ },
+ "columns": {
+ "type": "integer",
+ "enum": [
+ 2,
+ 3,
+ 4
+ ],
+ "default": 2
+ },
+ "gap": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "accordion": {
+ "type": "object",
+ "title": "Accordion",
+ "description": "Collapsible section with a header and expandable body.",
+ "required": [
+ "id",
+ "type",
+ "header",
+ "body"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "accordion"
+ },
+ "header": {
+ "type": "string"
+ },
+ "headerIcon": {
+ "$ref": "#/definitions/iconRef",
+ "description": "Optional icon displayed in the accordion header."
+ },
+ "body": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/element"
+ },
+ "minItems": 1
+ },
+ "expandedByDefault": {
+ "type": "boolean",
+ "default": false
+ },
+ "border": {
+ "type": "boolean"
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size for the header text in px."
+ },
+ "fontWeight": {
+ "type": "string",
+ "enum": [
+ "regular",
+ "medium",
+ "bold"
+ ],
+ "description": "Font weight for the header text."
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "tabs": {
+ "type": "object",
+ "title": "Tabs",
+ "description": "Tabbed container. Each tab has a label and content elements.",
+ "required": [
+ "id",
+ "type",
+ "tabs"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "tabs"
+ },
+ "tabs": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "required": [
+ "label",
+ "content"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "label": {
+ "type": "string"
+ },
+ "content": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/element"
+ },
+ "minItems": 1
+ }
+ }
+ }
+ },
+ "defaultActiveTab": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "tabAlign": {
+ "type": "string",
+ "enum": [
+ "start",
+ "center",
+ "stretch"
+ ],
+ "default": "start"
+ },
+ "tabPadding": {
+ "$ref": "#/definitions/padding",
+ "description": "Padding inside each tab label."
+ },
+ "contentPadding": {
+ "$ref": "#/definitions/padding",
+ "description": "Padding inside the tab content area."
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size for tab labels in px."
+ }
+ }
+ },
+ "button": {
+ "type": "object",
+ "title": "Button",
+ "description": "A clickable button that triggers an action.",
+ "required": [
+ "id",
+ "type",
+ "label",
+ "action"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "button"
+ },
+ "label": {
+ "type": "string"
+ },
+ "action": {
+ "$ref": "#/definitions/action"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "textColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "icon": {
+ "$ref": "#/definitions/iconRef",
+ "description": "Optional icon displayed in the button."
+ },
+ "iconPosition": {
+ "type": "string",
+ "enum": [
+ "left",
+ "right"
+ ],
+ "default": "left"
+ },
+ "size": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Button height in px. Suggested presets: 32 (small), 40 (medium), 48 (large)."
+ },
+ "fullWidth": {
+ "type": "boolean",
+ "default": false
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size in px."
+ }
+ }
+ },
+ "iconButton": {
+ "type": "object",
+ "title": "Icon Button",
+ "description": "A compact icon-only button.",
+ "required": [
+ "id",
+ "type",
+ "icon",
+ "action"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "iconButton"
+ },
+ "icon": {
+ "$ref": "#/definitions/iconRef",
+ "description": "Icon to display in the button."
+ },
+ "action": {
+ "$ref": "#/definitions/action"
+ },
+ "size": {
+ "type": "number",
+ "minimum": 0
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "backgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Corner radius in px. Set to half of size for circle, 0 for square."
+ }
+ }
+ },
+ "link": {
+ "type": "object",
+ "title": "Link",
+ "description": "An inline text link that triggers an action.",
+ "required": [
+ "id",
+ "type",
+ "text",
+ "action"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "link"
+ },
+ "text": {
+ "type": "string"
+ },
+ "action": {
+ "$ref": "#/definitions/action"
+ },
+ "color": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "underline": {
+ "type": "boolean",
+ "default": true
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size in px."
+ }
+ }
+ },
+ "table": {
+ "type": "object",
+ "title": "Table",
+ "description": "Renders a data table with headers and rows.",
+ "required": [
+ "id",
+ "type",
+ "columns",
+ "rows"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "Unique element identifier. Must be unique across all elements in the card."
+ },
+ "type": {
+ "const": "table"
+ },
+ "columns": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "minItems": 1,
+ "description": "Header labels."
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "description": "Row data. Cell values support {{placeholder}}."
+ },
+ "headerBackgroundColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "border": {
+ "type": "boolean"
+ },
+ "stripedRows": {
+ "type": "boolean"
+ },
+ "cellPadding": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Padding inside each cell in px."
+ },
+ "fontSize": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Font size for table content in px."
+ },
+ "stripedRowColor": {
+ "$ref": "#/definitions/colorValue",
+ "description": "Background color for striped rows."
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue",
+ "description": "Color for table borders."
+ }
+ }
+ }
+ },
+ "cardStyle": {
+ "type": "object",
+ "description": "Visual settings for the message card container.",
+ "required": [
+ "background"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "background": {
+ "$ref": "#/definitions/colorValue",
+ "description": "Background color for the card container. Required: UI Kits always expect a background key. Provide an explicit color per mode, or set 'transparent' per side when no fill is wanted. If this key is omitted, the card inherits a color from its surrounding context, which is incorrect."
+ },
+ "borderRadius": {
+ "type": "number",
+ "minimum": 0,
+ "description": "Corner radius in px."
+ },
+ "borderColor": {
+ "$ref": "#/definitions/colorValue"
+ },
+ "borderWidth": {
+ "type": "number",
+ "minimum": 0
+ },
+ "padding": {
+ "$ref": "#/definitions/padding"
+ }
+ }
+ }
+ }
+}
+```
+
diff --git a/docs.json b/docs.json
index 440b90bbc..e25fde43d 100644
--- a/docs.json
+++ b/docs.json
@@ -104,6 +104,27 @@
]
}
]
+ },
+ {
+ "tab": "Card Builder",
+ "hidden": true,
+ "pages": [
+ {
+ "group": "Card Builder",
+ "pages": [
+ "card-builder/overview",
+ "card-builder/building-cards",
+ "card-builder/elements",
+ "card-builder/schema"
+ ]
+ },
+ {
+ "group": "Guides",
+ "pages": [
+ "card-builder/example-order-status"
+ ]
+ }
+ ]
}
]
},
@@ -5972,6 +5993,7 @@
"/ai-agents/agent-builder/instructions",
"/ai-agents/agent-builder/knowledge-base/overview",
"/ai-agents/agent-builder/tools/overview",
+ "/ai-agents/agent-builder/card-messages",
"/ai-agents/agent-builder/mcp/overview",
"/ai-agents/agent-builder/frontend-actions/overview",
"/ai-agents/agent-builder/variables/overview"
@@ -5996,6 +6018,7 @@
"/ai-agents/mastra-actions",
"/ai-agents/mastra-tools",
"/ai-agents/mastra-runtime-context",
+ "/ai-agents/mastra-card-messages",
{
"group": "Guides",
"pages": [
@@ -6021,6 +6044,7 @@
"/ai-agents/crew-ai",
"/ai-agents/crew-ai-actions",
"/ai-agents/crew-ai-tools",
+ "/ai-agents/crew-ai-card-messages",
{
"group": "Guides",
"pages": [
@@ -6042,6 +6066,7 @@
"/ai-agents/agno",
"/ai-agents/agno-actions",
"/ai-agents/agno-tools",
+ "/ai-agents/agno-card-messages",
{
"group": "Guides",
"pages": [
@@ -6063,6 +6088,7 @@
"/ai-agents/vercel",
"/ai-agents/vercel-actions",
"/ai-agents/vercel-tools",
+ "/ai-agents/vercel-card-messages",
{
"group": "Guides",
"pages": [
@@ -6082,6 +6108,7 @@
"icon": "/images/icons/lang-graph.svg",
"pages": [
"/ai-agents/langgraph",
+ "/ai-agents/langgraph-card-messages",
{
"group": "Guides",
"pages": [
@@ -6103,6 +6130,7 @@
"/ai-agents/ag2",
"/ai-agents/ag2-actions",
"/ai-agents/ag2-tools",
+ "/ai-agents/ag2-card-messages",
{
"group": "Guides",
"pages": [
@@ -6124,6 +6152,7 @@
"/ai-agents/ag-ui",
"/ai-agents/ag-ui-actions",
"/ai-agents/ag-ui-tools",
+ "/ai-agents/ag-ui-card-messages",
{
"group": "Guides",
"pages": [
diff --git a/images/card-builder/build-1-heading.mp4 b/images/card-builder/build-1-heading.mp4
new file mode 100644
index 000000000..4cb4cff7c
Binary files /dev/null and b/images/card-builder/build-1-heading.mp4 differ
diff --git a/images/card-builder/build-2-details.mp4 b/images/card-builder/build-2-details.mp4
new file mode 100644
index 000000000..5c67f258b
Binary files /dev/null and b/images/card-builder/build-2-details.mp4 differ
diff --git a/images/card-builder/build-3-buttons.mp4 b/images/card-builder/build-3-buttons.mp4
new file mode 100644
index 000000000..b6dbde354
Binary files /dev/null and b/images/card-builder/build-3-buttons.mp4 differ
diff --git a/images/card-builder/build-4-actions.mp4 b/images/card-builder/build-4-actions.mp4
new file mode 100644
index 000000000..56b2223cd
Binary files /dev/null and b/images/card-builder/build-4-actions.mp4 differ
diff --git a/images/card-builder/build-5-fallback.mp4 b/images/card-builder/build-5-fallback.mp4
new file mode 100644
index 000000000..53e5750ee
Binary files /dev/null and b/images/card-builder/build-5-fallback.mp4 differ
diff --git a/images/card-builder/editor.png b/images/card-builder/editor.png
new file mode 100644
index 000000000..e793acc21
Binary files /dev/null and b/images/card-builder/editor.png differ
diff --git a/images/card-builder/nav-card-builder.png b/images/card-builder/nav-card-builder.png
new file mode 100644
index 000000000..95333a196
Binary files /dev/null and b/images/card-builder/nav-card-builder.png differ
diff --git a/images/card-builder/notification.png b/images/card-builder/notification.png
new file mode 100644
index 000000000..87e5c004f
Binary files /dev/null and b/images/card-builder/notification.png differ
diff --git a/images/card-builder/template-library.png b/images/card-builder/template-library.png
new file mode 100644
index 000000000..a903c4455
Binary files /dev/null and b/images/card-builder/template-library.png differ
diff --git a/sdk/flutter/campaigns.mdx b/sdk/flutter/campaigns.mdx
index 5a53f1a00..47501606b 100644
--- a/sdk/flutter/campaigns.mdx
+++ b/sdk/flutter/campaigns.mdx
@@ -17,6 +17,10 @@ Before using the SDK, set up your channels, categories, templates, and campaigns
A **Card Message** is a structured, interactive message rendered as a card bubble inside a conversation. Cards are **receive-only** on the SDK: they are created through the **Platform REST API** or the **Dashboard Bubble Builder** and delivered to clients like any other message — the SDK does not send them.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
- **Type:** `CardMessage` (cometchat_sdk)
- **Category:** `"card"` (`CometChatMessageCategory.card`)
diff --git a/sdk/flutter/send-message.mdx b/sdk/flutter/send-message.mdx
index b409a425a..87749b741 100644
--- a/sdk/flutter/send-message.mdx
+++ b/sdk/flutter/send-message.mdx
@@ -649,6 +649,10 @@ CometChat.sendCustomMessage(customMessage, onSuccess: (CustomMessage message) {
A `CardMessage` is a structured, interactive message rendered as a card bubble. It belongs to the `card` category and carries a block of card schema JSON that the CometChat Cards library draws.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
**Card Messages cannot be sent through the SDK.** The `CardMessage` class is **receive-only** — it has no public constructor and the SDK exposes no `sendCardMessage()` method. Card Messages are created server-side via the **Platform REST API** or the **Dashboard Bubble Builder**, and delivered to clients like any other message.
diff --git a/sdk/javascript/campaigns.mdx b/sdk/javascript/campaigns.mdx
index a2394204c..20253d779 100644
--- a/sdk/javascript/campaigns.mdx
+++ b/sdk/javascript/campaigns.mdx
@@ -581,3 +581,63 @@ When a user taps a button or link inside a card, the action callback receives on
| `initiateCall` | callType (audio/video), uid, guid | Start a call |
| `apiCall` | url, method, headers, body | Make an HTTP request |
| `customCallback` | callbackId, payload | App-specific logic |
+
+---
+
+## Card Messages
+
+Besides the notification feed, the **same Card Schema JSON** can arrive as a chat message. A `CardMessage` is a message with `category: "card"` — created and sent via the Platform (REST) API or the Dashboard Bubble Builder. The SDK only **receives** card messages; it does not send them.
+
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
+Card messages are delivered through the `onCardMessageReceived` callback of the [`MessageListener`](/sdk/javascript/all-real-time-listeners#message-listener), not through the notification feed listener. The payload from `getCard()` is the same Card Schema JSON described above, so you render it with the same [`CometChatCardView`](#rendering-cards) and handle the same [card actions](#supported-card-actions). For the complete receive-and-render flow, see the [Card Messages guide](/sdk/javascript/card-messages).
+
+### CardMessage Fields
+
+| Method | Return Type | Description |
+| --- | --- | --- |
+| `getCard()` | object | The raw Card Schema JSON payload. Pass directly to the Cards renderer. |
+| `getText()` | string | Preview text for push notifications and the conversation list. |
+| `getFallbackText()` | string | Fallback text from inside the card (`card.fallbackText`), used for accessibility or when the renderer fails. |
+| `getTags()` | `Array` | Tags associated with this message. |
+
+
+
+```typescript
+CometChat.addMessageListener(
+ "UNIQUE_LISTENER_ID",
+ new CometChat.MessageListener({
+ onCardMessageReceived: (cardMessage: CometChat.CardMessage) => {
+ console.log("Card message received:", cardMessage.getId());
+ const cardJson: string = JSON.stringify(cardMessage.getCard()); // same schema as feed cards
+ const fallback: string = cardMessage.getFallbackText();
+ const previewText: string = cardMessage.getText();
+ // Pass cardJson to CometChatCardView
+ },
+ })
+);
+```
+
+
+```javascript
+CometChat.addMessageListener(
+ "UNIQUE_LISTENER_ID",
+ new CometChat.MessageListener({
+ onCardMessageReceived: (cardMessage) => {
+ console.log("Card message received:", cardMessage.getId());
+ const cardJson = JSON.stringify(cardMessage.getCard()); // same schema as feed cards
+ const fallback = cardMessage.getFallbackText();
+ const previewText = cardMessage.getText();
+ // Pass cardJson to CometChatCardView
+ },
+ })
+);
+```
+
+
+
+
+Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the raw payload via `getCard()` — the CometChat Cards library is responsible for drawing the card UI.
+
diff --git a/sdk/javascript/card-messages.mdx b/sdk/javascript/card-messages.mdx
index 9faa962c4..91d4ccc2b 100644
--- a/sdk/javascript/card-messages.mdx
+++ b/sdk/javascript/card-messages.mdx
@@ -7,6 +7,10 @@ Card messages let your app display rich, structured content — such as product
The body of a card is **Card Schema JSON** — the same structured layout used by [Campaigns notification feeds](/sdk/javascript/campaigns). Cards are authored server-side (they cannot be composed or sent from the SDK) via the [Platform (REST) API](/rest-api/messages/send-message) or the **Dashboard Bubble Builder**, and delivered to clients like any other message.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — then send it through the [Platform (REST) API](/rest-api/messages/send-message) instead of writing the schema by hand.
+
+
The SDK never interprets the body of a card — every accessor returns the raw
Card Schema JSON exactly as it was sent. Drawing it is your app's
diff --git a/sdk/javascript/send-message.mdx b/sdk/javascript/send-message.mdx
index 563e87d24..b8d6745db 100644
--- a/sdk/javascript/send-message.mdx
+++ b/sdk/javascript/send-message.mdx
@@ -936,6 +936,10 @@ The `sendCustomMessage()` method returns a [`CustomMessage`](/sdk/reference/mess
A [`CardMessage`](/sdk/reference/messages#cardmessage) (category `card`) is a rich, structured card rendered from Card Schema JSON.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
**Card messages cannot be sent through the SDK.** `CardMessage` is
**receive-only** — there is no `sendCardMessage()` method. Cards are created
diff --git a/sdk/react-native/campaigns.mdx b/sdk/react-native/campaigns.mdx
index 683654d63..d31eb9bca 100644
--- a/sdk/react-native/campaigns.mdx
+++ b/sdk/react-native/campaigns.mdx
@@ -525,6 +525,10 @@ When a user taps a button or link inside a card, the action callback receives on
Besides the notification feed, the **same Card Schema JSON** can arrive as a chat message. A `CardMessage` is a message with `category: "card"` — created and sent via the Platform (REST) API or the Dashboard Bubble Builder. The SDK only **receives** card messages; it does not send them.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
Card messages are delivered through the `onCardMessageReceived` callback of the [`MessageListener`](/sdk/react-native/real-time-listeners#message-listener), not through the notification feed listener. The payload from `getCard()` is the same Card Schema JSON described above, so you render it with the same [`CometChatCardView`](#rendering-cards) and handle the same [card actions](#supported-card-actions).
### CardMessage Fields
diff --git a/sdk/react-native/send-message.mdx b/sdk/react-native/send-message.mdx
index 05f5518dd..3ede81fc3 100644
--- a/sdk/react-native/send-message.mdx
+++ b/sdk/react-native/send-message.mdx
@@ -878,6 +878,10 @@ customMessage.setConversationText("Shared a location");
A `CardMessage` is a structured, interactive message rendered as a card bubble. It belongs to the `card` category and carries a block of Card Schema JSON that the CometChat Cards library draws.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
**Card Messages cannot be sent through the SDK.** The `CardMessage` class is **receive-only** — it has no public constructor and the SDK exposes no `sendCardMessage()` method. Card Messages are created server-side via the **Platform (REST) API** or the **Dashboard Bubble Builder**, and delivered to clients like any other message, through the `onCardMessageReceived` callback of the `MessageListener`.
diff --git a/snippets/ai-agents/card-messages.mdx b/snippets/ai-agents/card-messages.mdx
new file mode 100644
index 000000000..756098696
--- /dev/null
+++ b/snippets/ai-agents/card-messages.mdx
@@ -0,0 +1,44 @@
+Your [Bring Your Own Agent (BYOA)](/ai-agents/cometchat-ag-ui-byoa) can reply with flexible, interactive cards — buttons, images, progress bars, layouts — instead of plain text. You design each card in [Card Builder](/card-builder/overview) so it renders uniformly, and your agent returns the card as JSON.
+
+## Enable card messages
+
+1. Open your BYOA agent in the dashboard.
+2. Turn on **Enable card messages**.
+
+Card messages are **opt-in** and off by default.
+
+## How it works
+
+When card messages are enabled, CometChat gives your agent a **card reference — working examples plus a field reference** — describing the same structure documented in the [Card JSON Schema](/card-builder/schema). Your agent returns a card simply by responding with **JSON that follows that reference**, and CometChat renders it as a native card in the chat.
+
+You only supply **what** card to send — the **how** is automatic. The format CometChat uses to recognize a card in your agent's response is part of the injected reference and is handled for you, **as long as card messages stays enabled**. This holds even if you use your own instructions or a predefined card: keep the feature on and just provide the card content. Don't disable it and try to emit cards from the raw schema alone — your agent won't have the format, and the card won't render.
+
+
+A reply is delivered as an ordered sequence of **elements** — plain-text segments and at most **one card**. So an agent can send a card on its own, or with text before and/or after it, in a single reply. To present multiple sections *inside* the card, use layout elements (`row`, `column`, `grid`, `tabs`, `accordion`) rather than sending a second card.
+
+
+## Keep cards uniform
+
+Because the agent has the card reference, it *can* generate cards freely — but free-form generation drifts in layout and styling. To keep every card consistent, design it once and reuse it:
+
+1. **Design your card** visually in [Card Builder](/card-builder/overview) — see [Building an Order Status Card](/card-builder/example-order-status) for a full walkthrough.
+2. Use **Export → Copy Card JSON** to copy the finished card.
+3. Have your agent **return that exact JSON** for the relevant reply, rather than composing a card from scratch.
+
+
+A fixed card renders exactly as designed. If it includes `{{placeholder}}` variables, your agent must fill them in with real values **before** returning the JSON — CometChat passes the JSON through as-is and does not resolve placeholders.
+
+
+## Reference
+
+
+
+ The complete schema your agent's card JSON must conform to.
+
+
+ Design and export cards visually — palette, canvas, elements, actions, and variables.
+
+
+ Build an interactive Order Status card from scratch, step by step.
+
+
diff --git a/ui-kit/angular/campaigns.mdx b/ui-kit/angular/campaigns.mdx
index 9621f8f1f..88cbc529d 100644
--- a/ui-kit/angular/campaigns.mdx
+++ b/ui-kit/angular/campaigns.mdx
@@ -5,6 +5,10 @@ description: "Deliver targeted, rich notifications to users via an in-app notifi
CometChat Campaigns enables you to send rich, interactive notifications to users through an in-app notification feed. Each notification is rendered as a native card using the **CometChat Cards** library — supporting images, text, buttons, layouts, and interactive actions.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card layouts in the CometChat Dashboard and export the Card Schema JSON these notifications render — instead of writing it by hand.
+
+
Before proceeding, ensure you have completed the [UI Kit integration](/ui-kit/angular/integration) and the [Dashboard Setup](/campaigns#setup-flow) for Campaigns.
diff --git a/ui-kit/angular/components/cometchat-card-bubble.mdx b/ui-kit/angular/components/cometchat-card-bubble.mdx
index 81e757911..e59984deb 100644
--- a/ui-kit/angular/components/cometchat-card-bubble.mdx
+++ b/ui-kit/angular/components/cometchat-card-bubble.mdx
@@ -9,6 +9,10 @@ The `CometChatCardBubbleComponent` renders a **developer Card Message** (`messag
The UIKit is a **render-only** consumer of cards: it draws cards delivered by the SDK and forwards card actions to your app. It never parses or mutates the card body, and never sends or creates cards. When a card message arrives, the UIKit routes it to this bubble automatically.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
The component follows a strict **render-only contract**:
- **Render-only** — the raw card payload from `message.getCard()` is serialized verbatim and handed to the prebuilt `CometChatCardView` renderer (from [`@cometchat/cards-angular`](https://www.npmjs.com/package/@cometchat/cards-angular)) as a `cardJson` string. The UI Kit performs **zero transformation** of the payload.
diff --git a/ui-kit/angular/events.mdx b/ui-kit/angular/events.mdx
index 3582fbd08..2f93a73f7 100644
--- a/ui-kit/angular/events.mdx
+++ b/ui-kit/angular/events.mdx
@@ -52,7 +52,7 @@ Events provide decoupled communication between UIKit components using a publish/
| **ccMessageEdited** | Triggered when the user successfully edits a message. |
| **ccReplyToMessage** | Triggered when the user successfully replies to a message. |
| **ccMessageDeleted** | Triggered when the user successfully deletes a message. |
-| **ccMessageRead** | Triggered when the sent message is read by the receiver. | |
+| **ccMessageRead** | Triggered when the sent message is read by the receiver. |
| **ccCardActionClicked** | Triggered when a user taps an interactive element on a card (developer card or nested agent card). Carries an `ICardActionEvent` with the owning `message` (or `null` for a streaming card), the raw renderer `action`, and the originating `elementId`/`cardJson`. The UIKit forwards the action untouched and runs no behavior. See the [Card Messages guide](/ui-kit/angular/guides/card-messages#handling-card-actions). |
### SDK Listener Events
diff --git a/ui-kit/flutter/campaigns.mdx b/ui-kit/flutter/campaigns.mdx
index ab5f864c2..35a8e190b 100644
--- a/ui-kit/flutter/campaigns.mdx
+++ b/ui-kit/flutter/campaigns.mdx
@@ -5,6 +5,10 @@ description: "Deliver targeted, rich notifications to users via an in-app notifi
CometChat Campaigns enables you to send rich, interactive notifications to users through an in-app notification feed. Each notification is rendered as a native card using the **CometChat Cards** library — supporting images, text, buttons, layouts, and interactive actions.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card layouts in the CometChat Dashboard and export the Card Schema JSON these notifications render — instead of writing it by hand.
+
+
Before proceeding, ensure you have completed the [UI Kit integration](/ui-kit/flutter/getting-started) and the [Dashboard Setup](/campaigns#setup-flow) for Campaigns.
diff --git a/ui-kit/flutter/v5/getting-started.mdx b/ui-kit/flutter/v5/getting-started.mdx
index 2b9496dcf..d3df5a6b5 100644
--- a/ui-kit/flutter/v5/getting-started.mdx
+++ b/ui-kit/flutter/v5/getting-started.mdx
@@ -86,7 +86,7 @@ Add to your `pubspec.yaml`:
dependencies:
flutter:
sdk: flutter
- cometchat_chat_uikit: ^5.2.16
+ cometchat_chat_uikit: ^5.2.18
cometchat_calls_uikit: ^5.0.16 # Optional: for voice/video calling
```
diff --git a/ui-kit/react-native/campaigns.mdx b/ui-kit/react-native/campaigns.mdx
index 820f4ad06..00e703a1e 100644
--- a/ui-kit/react-native/campaigns.mdx
+++ b/ui-kit/react-native/campaigns.mdx
@@ -5,6 +5,10 @@ description: "Deliver targeted, rich notifications to users via an in-app notifi
CometChat Campaigns enables you to send rich, interactive notifications to users through an in-app notification feed. Each notification is rendered as a native card using the **CometChat Cards** library — supporting images, text, buttons, layouts, and interactive actions.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card layouts in the CometChat Dashboard and export the Card Schema JSON these notifications render — instead of writing it by hand.
+
+
Before proceeding, ensure you have completed the [UI Kit integration](/ui-kit/react-native/overview) and the [Dashboard Setup](/campaigns#setup-flow) for Campaigns.
diff --git a/ui-kit/react/campaigns.mdx b/ui-kit/react/campaigns.mdx
index 71080b1ec..c8ac622c1 100644
--- a/ui-kit/react/campaigns.mdx
+++ b/ui-kit/react/campaigns.mdx
@@ -5,6 +5,10 @@ description: "Deliver targeted, rich notifications to users via an in-app notifi
CometChat Campaigns enables you to send rich, interactive notifications to users through an in-app notification feed. Each notification is rendered as a native card using the **CometChat Cards** library — supporting images, text, buttons, layouts, and interactive actions.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card layouts in the CometChat Dashboard and export the Card Schema JSON these notifications render — instead of writing it by hand.
+
+
Before proceeding, ensure you have completed the [UI Kit integration](/ui-kit/react/integration-react) and the [Dashboard Setup](/campaigns#setup-flow) for Campaigns.
diff --git a/ui-kit/react/components/card-bubble.mdx b/ui-kit/react/components/card-bubble.mdx
index dc52fc66f..e65e879cd 100644
--- a/ui-kit/react/components/card-bubble.mdx
+++ b/ui-kit/react/components/card-bubble.mdx
@@ -29,6 +29,10 @@ description: "A render-only bubble that draws developer-defined card messages (c
`CometChatCardBubble` renders a **card message** — a message with `category: "card"`. A card message carries a block of Card Schema JSON that is created and sent server-side (via the Platform (REST) API or the Dashboard Bubble Builder) and delivered to clients like any other message. Card messages are **receive-only**: the UI Kit renders them, it does not send them.
+
+ **Design cards visually with [Card Builder](/card-builder/overview).** Build your card messages in the CometChat Dashboard and export the Card Schema JSON — instead of writing it by hand.
+
+
The bubble is **render-only**, mirroring `CometChatTextBubble`: the kit performs zero transformation. It stringifies the raw payload from `message.getCard()` and hands it to the prebuilt [`CometChatCardView`](https://www.npmjs.com/package/@cometchat/cards-react) renderer (`@cometchat/cards-react`), then forwards user actions back to your app. It never parses or mutates the card body, and never performs an action itself — your app owns all action behavior (opening URLs, navigating to chats, API calls, etc.).
In the message list, card messages are routed to this bubble automatically by the built-in **Card plugin** — no configuration is required. See [Plugins → Built-in Plugins](/ui-kit/react/plugins/overview#built-in-plugins).