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
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
cardobject. - The
themefield 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.
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
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
Used in: Poll, Modern Inline, and Prompt cards.
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 bepoll. - 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.
- options[].text
- theme
string- Must bemodern-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.
- fields[].title
- sections[].title
- buttons
array- Optional. Action buttons rendered at the bottom of the card. Maximum 5. See Button fields below.
- theme
string- Must beprompt. - 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.
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. Requiresaction.data.web(string).invoke.function- Triggers a Cliq Function by name. Requiresaction.data.name(string).system.api- Calls a Cliq internal system API. Requiresaction.data.api(string).invoke.bot- Sends a message to a bot. Requiresaction.data.bot_nameandaction.data.message.preview.url- Opens a URL inside a Cliq preview panel without leaving the conversation. Requiresaction.data.web(string).
- buttons[].action.data
object- The payload passed to the action handler. Expected fields depend onaction.typeas listed above.
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.
Allowed values:
poll | modern-inline | prompt
Maximum length: 200 characters.
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.
modern-inline theme only.URL of an image to display as a thumbnail in the card header. Must be a publicly accessible HTTPS URL.
modern-inline theme only.List of field sections. Each section groups related labeled key-value fields under an optional section title.
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.
Maximum length: 30 characters.
type field determines the action category and the expected structure of the data payload.
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.
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_nameandmessage. - preview.url: Requires
web(string - the URL to preview).
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. |
For full details on each slide type, including field-level descriptions and payload examples, refer to Message Content.
Allowed values:
table | list | label | images
type:
- table: Object with
headers(array of strings) androws(array of objects). - list: Array of strings.
- label: Array of objects, each with
labelandvalue. - images: Array of image URL strings.
Path Parameters
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/v2/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/v2/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/v2/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/v2/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/v2/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/v2/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/v2/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/v2/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/v2/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/v2/channels/987000000654321/message \
--header 'Authorization: Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f' \
--header 'content-type: application/json' \
--data '{"field1":"value1","field2":"value2"}'
Post a Message Card to a User
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
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 as a direct message to a specific user,
identified by their email address or user ID. 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.Messages.CREATE
Arguments
Used in: Poll, Modern Inline, and Prompt cards.
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 bepoll. - 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.
- options[].text
- theme
string- Must bemodern-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.
- fields[].title
- sections[].title
- buttons
array- Optional. Action buttons rendered at the bottom of the card. Maximum 5. See Button fields below.
- theme
string- Must beprompt. - 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.
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. Requiresaction.data.web(string).invoke.function- Triggers a Cliq Function by name. Requiresaction.data.name(string).system.api- Calls a Cliq internal system API. Requiresaction.data.api(string).invoke.bot- Sends a message to a bot. Requiresaction.data.bot_nameandaction.data.message.preview.url- Opens a URL inside a Cliq preview panel without leaving the conversation. Requiresaction.data.web(string).
- buttons[].action.data
object- The payload passed to the action handler. Expected fields depend onaction.typeas listed above.
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.
Allowed values:
poll | modern-inline | prompt
Maximum length: 200 characters.
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.
modern-inline theme only.URL of an image to display as a thumbnail in the card header. Must be a publicly accessible HTTPS URL.
modern-inline theme only.List of field sections. Each section groups related labeled key-value fields under an optional section title.
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.
Maximum length: 30 characters.
type field determines the action category and the expected structure of the data payload.
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.
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_nameandmessage. - preview.url: Requires
web(string - the URL to preview).
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. |
For full details on each slide type, including field-level descriptions and payload examples, refer to Message Content.
Allowed values:
table | list | label | images
type:
- table: Object with
headers(array of strings) androws(array of objects). - list: Array of strings.
- label: Array of objects, each with
labelandvalue. - images: Array of image URL strings.
Path Parameters
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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/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/v2/buddies/987000000654321/message \
--header 'Authorization: Bearer 1000.41d9xxxxxxxxxxxxxxxxxxxxxxxxc2d1.8fccxxxxxxxxxxxxxxxxxxxxxxxx125f' \
--header 'content-type: application/json' \
--data '{"field1":"value1","field2":"value2"}'