Message Cards

Message Cards AI Tools

Open in ChatGPT

Open in ChatGPT to ask questions about this page

Open in Claude

Open in Claude to ask questions about this page

Copy as Markdown

Copy this page as markdown to use with AI assistants

View as Markdown

Open this page as markdown in a new tab

Message Cards are structured, interactive message formats in Zoho Cliq that go beyond plain text to deliver rich, engaging content inside conversations. They are used to present polls, inline data displays, and interactive prompts directly within a chat or channel - enabling bots and integrations to collect input, display structured information, and drive actions from users without leaving the conversation.

Message Cards are sent as part of the standard Post Message payload by setting the card object inside the message body. The theme field inside card determines which card type is rendered.

For more information, refer to the Message Cards Documentation.

Available Themes

Theme Description Required fields Optional fields
poll Renders a poll card that lets users vote on one or more options. Tracks and displays live vote counts and percentages. theme, title, options -
modern-inline Renders a rich inline card with a header, sections of labeled fields, and optional action buttons. Pair with slides for supporting data. theme, title thumbnail, sections, buttons
prompt Renders a focused prompt card with a question and a set of quick-reply or action buttons for the user to respond to. theme, title, buttons -

How Message Cards work

  • Cards are embedded in the message payload using the card object.
  • The theme field selects the rendering template.
  • Interactive elements (buttons, poll choices) trigger bot handlers or function calls when actioned by a user.
  • Cards can be sent to channels, chats, or individual users using the standard Post Message endpoints.

Download Message Cards OpenAPI Document
End Points
Post a Message Card to a Channel

Post a Message Card to a Channel AI Tools

Open in ChatGPT

Open in ChatGPT to ask questions about this page

Open in Claude

Open in Claude to ask questions about this page

Copy as Markdown

Copy this page as markdown to use with AI assistants

View as Markdown

Open this page as markdown in a new tab

Send a structured Message Card to a specific channel. Depending on the type of card you want to send, the card object in the request body will differ (i.e., poll, modern-inline, or prompt).

Threshold limit: 20 requests per min per user
Number of API calls allowed within a minute.

Lock period: 10 minutes
Wait time before consecutive API requests.


OAuth Scope : ZohoCliq.Channels.CREATE

Arguments

text
string
Fallback plain-text label displayed above the card or in notification previews where cards are not rendered.
Used in: Poll, Modern Inline, and Prompt cards.
card
object
(Required)
Defines the interactive card to be rendered inside the message. The theme field selects the card type and determines which fields are required. For a quick reference of required and optional fields per theme, see the Available Themes table in the overview above.

Poll card fields
  • theme string - Must be poll.
  • title string - The poll question displayed at the top of the card. Maximum 200 characters.
  • options array - List of voting choices. Minimum 2, maximum 10 items.
    • options[].text string - Display label for the poll option. Maximum 100 characters.
Modern Inline card fields
  • theme string - Must be modern-inline.
  • title string - Card header text displayed at the top of the card. Maximum 200 characters.
  • thumbnail string - Optional. Publicly accessible HTTPS URL of a thumbnail image shown in the card header.
  • sections array - Optional. One or more labeled field sections displayed in the card body. Each section groups related key-value pairs under an optional heading.
    • sections[].title string - Optional section heading displayed above the fields.
    • sections[].fields array - List of key-value field pairs.
      • fields[].title string - Field label (key).
      • fields[].value string - Field value.
  • buttons array - Optional. Action buttons rendered at the bottom of the card. Maximum 5. See Button fields below.
Prompt card fields
  • theme string - Must be prompt.
  • title string - The prompt question or alert text presented to the user. Maximum 200 characters.
  • buttons array - Action buttons for the user to respond with. Minimum 1, maximum 5. See Button fields below.
Button fields (applicable to modern-inline and prompt themes)
  • buttons[].label string - Text displayed on the button. Maximum 30 characters.
  • buttons[].action.type string - Determines how Cliq handles the button click. Allowed values:
    • open.url - Opens a URL in the user's default browser. Requires action.data.web (string).
    • invoke.function - Triggers a Cliq Function by name. Requires action.data.name (string).
    • system.api - Calls a Cliq internal system API. Requires action.data.api (string).
    • invoke.bot - Sends a message to a bot. Requires action.data.bot_name and action.data.message.
    • preview.url - Opens a URL inside a Cliq preview panel without leaving the conversation. Requires action.data.web (string).
  • buttons[].action.data object - The payload passed to the action handler. Expected fields depend on action.type as listed above.
Note: To render supporting structured content (such as tables, lists, or labelled records) alongside a card, use the top-level slides array in the message payload. slides is independent of the card object and can be combined with any card theme. For details on supported slide formats, see Message Content.
Show Sub-Attributes arrow
theme
string
(Required)
Card theme identifier. Determines the card type to render.
Allowed values: poll | modern-inline | prompt
title
string
(Required)
The card header or question text displayed at the top of the card.
Maximum length: 200 characters.
options
array
Applicable for poll theme only.
List of voting options. Each option is rendered as a selectable row with a live vote count and percentage bar.
Minimum: 2 options. Maximum: 10 options.
Show Sub-Attributes arrow
text
string
(Required)
Display label for the poll option.
thumbnail
string
Applicable for modern-inline theme only.
URL of an image to display as a thumbnail in the card header. Must be a publicly accessible HTTPS URL.
sections
array
Applicable for modern-inline theme only.
List of field sections. Each section groups related labeled key-value fields under an optional section title.
Show Sub-Attributes arrow
title
string
(Required)
Optional section heading displayed above the fields.
fields
array
List of key-value field pairs displayed in this section.
Show Sub-Attributes arrow
title
string
(Required)
Field label (key).
value
string
(Required)
Field value.
buttons
array
Applicable for modern-inline and prompt themes.
List of action buttons rendered inside the card. Each button executes an action when clicked by the user.
Maximum: 5 buttons. Minimum 1 for prompt.
Show Sub-Attributes arrow
label
string
(Required)
Display text shown on the button.
Maximum length: 30 characters.
action
object
(Required)
Defines the action executed when the button is clicked. The type field determines the action category and the expected structure of the data payload.
Show Sub-Attributes arrow
type
string
(Required)
The action type. Determines how Cliq handles the button click.
Allowed values:
  • open.url: Opens a URL in the user's browser.
  • invoke.function: Calls a Cliq Function by name.
  • system.api: Calls a Cliq internal system API.
  • invoke.bot: Sends a message to a bot.
  • preview.url: Opens a URL in a preview panel inside Cliq.
data
object
(Required)
Payload passed to the action handler. The expected fields depend on the type:
  • open.url: Requires web (string - the URL to open).
  • invoke.function: Requires name (string - Cliq Function name).
  • system.api: Requires api (string - the internal API path).
  • invoke.bot: Requires bot_name and message.
  • preview.url: Requires web (string - the URL to preview).
slides
array
An array of structured content blocks rendered below the card inside the message. slides is a top-level field in the message payload - it sits alongside text and card, and is not nested inside card.

Multiple slide blocks can be included in a single message, and they are rendered in the order they appear in the array. slides is most commonly paired with the modern-inline card theme to display supporting data such as tables, lists, or labelled records alongside the card header, but it is compatible with all card themes.

Each slide block requires a type field that determines how the content is rendered, an optional title heading, and a data payload whose structure depends on the slide type.

Supported slide types
Type Renders data structure
table A data table with column headers and rows. Object with headers (array of strings) and rows (array of objects where each key maps to a header).
list A bulleted list of items. Array of strings, each representing one list item.
label Key-value pairs in a definition-list style. Array of objects, each with label (string) and value (string).
images One or more inline images. Array of publicly accessible HTTPS image URL strings.
text A plain or formatted text block. A string containing the text content to display.

For full details on each slide type, including field-level descriptions and payload examples, refer to Message Content.
Show Sub-Attributes arrow
type
string
(Required)
The slide content type.
Allowed values: table | list | label | images | text
title
string
Optional heading displayed above the slide content.
data
Content payload for the slide. Structure depends on type:
  • table: Object with headers (array of strings) and rows (array of objects).
  • list: Array of strings.
  • label: Array of objects, each with label and value.
  • images: Array of image URL strings.
  • text: A string containing the text content to display.

Path Parameters

channelName
string
(Required)
The unique name of the channel to post the message card into.

Request Example

Click to copy
parameters_data='{"field1":"value1","field2":"value2"}'; headers_data = Map(); headers_data.put("Authorization", "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f"); response = invokeUrl [ url: "https://cliq.zoho.com/api/v3/channels/987000000654321/message" type: POST headers: headers_data content-type: application/json parameters: parameters_data connection: <connection_name> ]; info response;
OkHttpClient client = new OkHttpClient(); MediaType mediaType = MediaType.parse("application/json"); RequestBody body = RequestBody.create(mediaType, "{\"field1\":\"value1\",\"field2\":\"value2\"}"); Request request = new Request.Builder() .url("https://cliq.zoho.com/api/v3/channels/987000000654321/message") .post(body) .addHeader("Authorization", "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f") .addHeader("content-type", "application/json") .build(); Response response = client.newCall(request).execute();
const options = { method: 'POST', headers: { Authorization: 'Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f', 'content-type': 'application/json' }, body: '{"field1":"value1","field2":"value2"}' }; fetch('https://cliq.zoho.com/api/v3/channels/987000000654321/message', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err));
import http.client conn = http.client.HTTPSConnection("cliq.zoho.com") payload = "{\"field1\":\"value1\",\"field2\":\"value2\"}" headers = { 'Authorization': "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f", 'content-type': "application/json" } conn.request("POST", "/api/v3/channels/987000000654321/message", payload, headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8"))
const http = require("https"); const options = { "method": "POST", "hostname": "cliq.zoho.com", "port": null, "path": "/api/v3/channels/987000000654321/message", "headers": { "Authorization": "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f", "content-type": "application/json" } }; const req = http.request(options, function (res) { const chunks = []; res.on("data", function (chunk) { chunks.push(chunk); }); res.on("end", function () { const body = Buffer.concat(chunks); console.log(body.toString()); }); }); req.write(JSON.stringify({field1: 'value1', field2: 'value2'})); req.end();
var client = new RestClient("https://cliq.zoho.com/api/v3/channels/987000000654321/message"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f"); request.AddHeader("content-type", "application/json"); request.AddParameter("application/json", "{\"field1\":\"value1\",\"field2\":\"value2\"}", ParameterType.RequestBody); IRestResponse response = client.Execute(request);
var client = new HttpClient(); var request = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri("https://cliq.zoho.com/api/v3/channels/987000000654321/message"), Headers = { { "Authorization", "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f" }, }, Content = new StringContent("{\"field1\":\"value1\",\"field2\":\"value2\"}") { Headers = { ContentType = new MediaTypeHeaderValue("application/json") } } }; using (var response = await client.SendAsync(request)) { response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body); }
package main import ( "fmt" "strings" "net/http" "io/ioutil" ) func main() { url := "https://cliq.zoho.com/api/v3/channels/987000000654321/message" payload := strings.NewReader("{\"field1\":\"value1\",\"field2\":\"value2\"}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f") req.Header.Add("content-type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) }
const data = JSON.stringify({ "field1": "value1", "field2": "value2" }); const xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.addEventListener("readystatechange", function () { if (this.readyState === this.DONE) { console.log(this.responseText); } }); xhr.open("POST", "https://cliq.zoho.com/api/v3/channels/987000000654321/message"); xhr.setRequestHeader("Authorization", "Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f"); xhr.setRequestHeader("content-type", "application/json"); xhr.send(data);
curl --request POST \ --url https://cliq.zoho.com/api/v3/channels/987000000654321/message \ --header 'Authorization: Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f' \ --header 'content-type: application/json' \ --data '{"field1":"value1","field2":"value2"}'

Body Parameters

Click to copy
{ "text": "Sprint 42 - Please vote on which feature we prioritize this cycle.", "card": { "theme": "poll", "title": "Which feature should we prioritize in Sprint 42?", "options": [ { "text": "OAuth 2.0 support for third-party integrations" }, { "text": "Bulk export for audit logs" }, { "text": "Dark mode for the web app" }, { "text": "Push notifications for mobile" } ] } }
{ "text": "A critical support ticket has been escalated and requires immediate attention.", "card": { "theme": "modern-inline", "title": "Ticket Escalated - Payment Gateway Timeout" }, "slides": [ { "type": "table", "title": "Ticket Details", "data": { "headers": [ "Field", "Value" ], "rows": [ { "Field": "Ticket ID", "Value": "#TKT-00892" }, { "Field": "Priority", "Value": "Critical" }, { "Field": "Reported By", "Value": "olivia.palmer@zylker.com" }, { "Field": "Affected Module", "Value": "Payment Gateway" }, { "Field": "Open Since", "Value": "2026-04-16 09:14 AM" } ] } } ], "buttons": [ { "label": "Assign to Me", "action": { "type": "invoke.function", "data": { "name": "assign_ticket" } } }, { "label": "View Ticket", "action": { "type": "open.url", "data": { "web": "https://desk.zoho.com/tickets/TKT-00892" } } } ] }
{ "text": "Deployment approval required for release v3.6.1 to production.", "card": { "theme": "prompt", "title": "Approve deployment of v3.6.1 to production? This release includes 4 bug fixes and 1 migration script." }, "buttons": [ { "label": "Approve", "action": { "type": "invoke.function", "data": { "name": "approve_deployment" } } }, { "label": "Reject", "action": { "type": "invoke.function", "data": { "name": "reject_deployment" } } }, { "label": "View Diff", "action": { "type": "open.url", "data": { "web": "https://git.zylker.com/releases/v3.6.1/diff" } } } ] }

Response Example

{ "url": "/api/v3/channels/engineering/message", "type": "message", "data": { "id": "1701234567890_1234567890", "card": { "theme": "poll", "title": "Which feature should we prioritize in Sprint 42?", "options": [ { "text": "OAuth 2.0 support for third-party integrations", "votes": 0 }, { "text": "Bulk export for audit logs", "votes": 0 }, { "text": "Dark mode for the web app", "votes": 0 }, { "text": "Push notifications for mobile", "votes": 0 } ] } } }
{ "url": "/api/v3/channels/support/message", "type": "message", "data": { "id": "1701234567891_1234567891", "card": { "theme": "modern-inline", "title": "Ticket Escalated - Payment Gateway Timeout" }, "slides": [ { "type": "table", "title": "Ticket Details", "data": { "headers": [ "Field", "Value" ], "rows": [ { "Field": "Ticket ID", "Value": "#TKT-00892" }, { "Field": "Priority", "Value": "Critical" } ] } } ] } }
{ "url": "/api/v3/channels/devops/message", "type": "message", "data": { "id": "1701234567892_1234567892", "card": { "theme": "prompt", "title": "Approve deployment of v3.6.1 to production?" } } }
{ "message": "The request cannot be performed. Usually because of malformed parameter or missing parameter." }
{ "message": "Request was rejected because of invalid AuthToken." }
{ "message": "The user does not have enough permission or possibly not a user of the respective organization to access the resource." }
{ "message": "The URL you've sent is wrong. It's possible that the resource you've requested has been moved to another URL." }
{ "message": "The requested resource does not support the HTTP method used." }
{ "message": "Too many requests within a certain time frame." }
{ "message": "Cliq server encountered an error which prevents it from fulfilling the request." }