# Chatbot messaging protocol reference HTTP protocol reference for integrating third-party chatbots with Zoom Contact Center. This protocol defines the message format and endpoints that chatbot providers implement to support action and trigger mode integration. The integration enables third-party chatbots to act as AI bots within Zoom Contact Center, handling conversation messages, rich media content, and handover to live agents. For the full integration workflow and Marketplace app setup, see [Integrate third-party chatbots with actions and triggers](/docs/contact-center/library/guides/chatbot/). ## Send messages to third-party bot To send messages from Zoom Contact Center to your chatbot endpoint, Zoom sends HTTP requests with the following payload structure. ### Request payload ```json { "id": "xxx", "sessionId": "xxx", "conversationMode": "START_CONVERSATION", "message": { "type": "text", "value": "hi" }, "conversationVariables": { "global_system.Engagement.timezone": "America/New_York", "global_system.Engagement.regionCode": "GA", "global_system.Consumer.email": "a@q.com", "global_system.Engagement.latLong": "34.0409, -84.0237", "global_custom.CustomerVariableGroup.QueueOpenHours": "1698872160000", "global_custom.CustomerVariableGroup.CVariable001": "this is default value", "global_system.Engagement.locale": "en-us", "global_custom.Website_Data_Value.GJavescriptVariable_hostname": "localhost", "global_system.Engagement.regionName": "Georgia", "global_system.Engagement.cityName": "Suwanee" }, "languageCode": "en-US", "additionalPayload": null, "timestamp": 111, "userId": "xxx", "customData": { "trackingId": "xxx", "engagmentId": "xxx" } } ``` ```json { "id": "xxx", "sessionId": "xxx", "conversationMode": "KEEP_CONVERSATION", "conversationVariables": {}, "additionalPayload": null, "languageCode": "en-US", "message": { "type": "text", "value": "Hi, I need some help!" }, "timestamp": 111, "userId": "xxx", "customData": { "trackingId": "xxx", "engagmentId": "xxx" } } ``` ```json { "id": "xxx", "sessionId": "xxx", "conversationMode": "KEEP_CONVERSATION", "message": { "type": "text", "value": "yes" }, "conversationVariables": {}, "additionalPayload": { "action": "optionSubmit", "data": { "interactionId": "a806116e-5301-4b0c-b448-cc09c32ed72a-0fffcb44", "interacted": true, "value": "yes", "originMessage": { "type": "quickReplies", "value": { "title": "Please make your choice", "options": [ { "label": "Yes", "value": "yes" }, { "label": "No", "value": "no" } ] } } } }, "languageCode": "en-US", "timestamp": 111, "userId": "xxx", "customData": { "trackingId": "xxx", "engagmentId": "xxx" } } ``` ```json { "id": "xxx", "sessionId": "xxx", "conversationMode": "KEEP_CONVERSATION", "message": { "type": "text", "value": "info_collection_form(form name)" }, "conversationVariables": {}, "additionalPayload": { "action": "formSubmit", "data": { "interactionId": "a806116e-5301-4b0c-b448-cc09c32ed72a-0fffcb44", "skipped": false, "values": [ { "key": "name", "type": "text", "value": "Tom" }, { "key": "education", "type": "select", "value": "bachelor" }, { "key": "option", "type": "multi-select", "value": ["1", "2"] } ], "originMessage": { "type": "form", "value": { "title": "your title", "description": "

I really like using Markdown.

", "fields": [ { "type": "text", "label": "Name", "key": "name", "required": true, "defaultValue": "" }, { "type": "select", "label": "Education", "key": "education", "required": true, "options": [ { "label": "High School Diploma", "value": "high_school" }, { "label": "Associate Degree", "value": "associate" }, { "label": "Bachelor's Degree", "value": "bachelor" }, { "label": "Doctoral Degree (Ph.D.)", "value": "doctor" }, { "label": "Other", "value": "other" } ], "defaultValue": "" }, { "type": "multi-select", "label": "Make you chocie", "key": "option", "required": true, "options": [ { "label": "Option1", "value": "1" }, { "label": "Option2", "value": "2" }, { "label": "Option3", "value": "3" } ], "defaultValues": ["1", "2"] } ] } } } }, "languageCode": "en-US", "timestamp": 111, "userId": "xxx", "customData": { "trackingId": "xxx", "engagmentId": "xxx" } } ``` ```json { "id": "xxx", "sessionId": "xxx", "conversationMode": "END_CONVERSATION", "timestamp": 111, "userId": "xxx", "customData": { "trackingId": "xxx", "engagmentId": "xxx" } } ``` ### Request parameters | Parameter Name | Type | Required | Description | Possible Values | | --------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- | | id | String | Yes | Unique identifier for this request. | | | sessionId | String | Yes | Unique identifier for the bot conversations. | | | conversationMode | String | Yes | Parameter to define whether to start a new conversion, continue with the existing, or close the conversation.`START_CONVERSATION`: starts a session `KEEP_CONVERSATION`: keeps the current session. `END_CONVERSATION`: ends the current session | `START_CONVERSATION`, `KEEP_CONVERSATION`, `END_CONVERSATION` | | conversationVariables | Object | No | Will be sent only once when `conversationMode` is `START_CONVERSATION`. Include both system-defined and customer-defined values. Bot providers should store these variables within the conversation context so that customers can reference within the bot's flow. | | | additionalPayload | Object | No | For submissions of forms, cards, action cards, or quick replies, the data will be placed in the `additionalPayload` field. **Note**: `additionalPayload` may be null if the consumer's input is not related to any of these rich media selections. | | | languageCode | String | Yes | Required when `conversationMode` is `START_CONVERSATION` or `KEEP_CONVERSATION`. | `en-US` | | message | Object | Yes | Details of the message to be sent.Required when `conversationMode` is `START_CONVERSATION` or `KEEP_CONVERSATION`. | | | timestamp | Long | Yes | Unix epoch time when the message was sent from the end-user of the chat client. | | | userId | String | Yes | Unique user identifier. This is the identifier of the end-user who is interacting with the bot. | | | customData | Object | Yes | Pass-through JSON-formatted name-value pairs that are sent back in the response. These values are not processed by the endpoint, but can be used to keep specific customer information attached to the conversation. | | ### Message input types #### Text To handle plain text messages from consumers, parse the message object. ```json { "type": "text", "value": "Hi, I need some help!" } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ----------- | ---------- | | value | Yes | String | Plain text | n/a | ## Receive messages from third-party bot To respond with messages from your chatbot to Zoom Contact Center, return HTTP responses with the following payload structure. ### Response payload Basic response example. ```json { "id": "xxx", "sessionId": "xxx", "body": [ { "type": "text", "value": "Hi, I'm your virtual agent!" } ], "timestamp": 111, "userId": "xxx", "completed": false, "customData": { "trackingId": "xxx", "engagmentId": "xxx" } } ``` ### Response parameters | Parameter Name | Type | Required | Description | Possible Values | | -------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | | id | String | Yes | Unique identifier for this request. | | | sessionId | String | No | Unique identifier for the bot conversations. | | | body | Array | Yes | List of objects that describe the elements of the response message body. | | | timestamp | Long | Yes | Unix epoch time when the message was sent from the end-user of the chat client. | | | userId | String | Yes | Unique user identifier. This is the identifier of the end-user who is interacting with the bot. | | | completed | Boolean | No | Flag that indicates whether the ServiceNow Virtual Agent has successfully completed the conversation. `true` means conversation has been successfully completed. `false` means conversation is not complete and this parameter is not returned in the response. | `true`, `false` | | customData | Object | Yes | Pass-through JSON-formatted name-value pairs that are sent back in the response. These values are not processed by the endpoint, but can be used to keep specific customer information attached to the conversation. | | ### Message body structure Each message in the `body` array contains a type and value. | Field | Required | Value | Description | Possible Values | | ------------ | -------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | type | Yes | String | Message content type. | `action`, `text`, `html`, `markdown`, `quickReplies`, `card`, `carousel`, `article`, `image`, `audio`, `video`, `link`, `form`, `attachment` | | value | Yes | Object | Refer to the message content types below. | | | fallbackText | No | String | When a chatbot is integrated with social channels such as Facebook or WhatsApp, these platforms may not fully support rich text messages. Setting a `fallbackText` helps ensure that users can still see a message instead of receiving no prompt at all. | | ## Message content types [Action](#action) | [Article](#article) | [Attachment](#attachment) | [Audio](#audio) | [Card](#card) | [Carousel](#carousel) | [Form](#form) | [HTML](#html) | [Image](#image) | [Link](#link) | [Markdown](#markdown) | [Quick replies](#quick-replies) | [Text](#text) | [Video](#video) ### Action To trigger actions in the conversation, use action messages. #### Set variables To dynamically route to queues, set variables in the conversation context. ```json { "type": "action", "value": { "action": "setVariables", "data": { "variables": [ { "name": "global_custom.dynamic routing.dynamical_queue", "value": "Main Team Queue" } ] } } } ``` > **Note** > > `global_custom` is the prefix used for custom-defined variables. `dynamic routing` is the variable group name. `dynamical_queue` is the variable name. The `value` field contains the queue name. #### Typing indicator To display a typing indicator, send a typing action. ```json { "type": "action", "value": { "action": "typing", "data": { "typingTime": 1000 } } } ``` | Field | Required | Value | Description | Limitation | | ---------- | -------- | ----- | ------------------------------------------------------------------------------------------------------------------- | ---------- | | typingTime | No | long | Typing indicator display duration in milliseconds. If not specified, the default maximum display time is 5 seconds. | n/a | #### Transfer to live agent To transfer the conversation to a live agent, send a transfer action. ```json { "type": "action", "value": "TransferToLiveAgent" } ``` ### Article To send an article with content and sources, use the article type. ```json { "type": "article", "value": { "title": "How Zoom can help you stay safe in cyberspace", "content": "

This is a heading

This is a paragraph.

", "style": "multi-sources", "sources": [ { "label": "reference 1", "title": "this is reference 1", "content": "

This is a heading

This is a paragraph.

", "contentType": "markdown", "url": "https://www.zoom.com/en/blog/how-zoom-can-help-you-stay-safe-in-cyberspace/" }, { "label": "reference 2", "title": "this is reference 2", "contentType": "html", "content": "

This is a heading

This is a paragraph.

", "url": "https://www.zoom.com/en/blog/how-zoom-can-help-you-stay-safe-in-cyberspace/" } ] } } ``` | Field | Required | Value | Description | Limitation | | ------- | -------- | ------ | ------------------------------------------------------ | ---------- | | title | Yes | String | Article title | 256 Bytes | | content | Yes | String | Standard HTML format or plain text | n/a | | sources | Yes | List | List of article sources | 20 | | style | No | String | Source display style: `single-source`, `multi-sources` | n/a | #### Article source To add source references to an article, include source objects. | Field | Required | Value | Description | Limitation | | ----------- | -------- | ------- | ----------------------------------------- | ---------- | | label | Yes | String | The button or label name | 128 Bytes | | title | Yes | String | The title in the details | 256 Bytes | | content | Yes | String | Standard HTML format or plain text | n/a | | contentType | No | String | Content format type: `markdown` or `html` | n/a | | url | No | String | The article link | n/a | | openNewTab | No | Boolean | The URL will open in new tab | n/a | ### Attachment > **Note** > > Coming soon. To send a file attachment, use the attachment type. ```json { "type": "attachment", "value": { "title": "attachment pdf title", "name": "attachment pdf name.pdf", "url": "https://file-examples.com/storage/fe091522ae6912e509be331/2017/10/file-sample_150kB.pdf" } } ``` > **Warning** > > File size limit: 15MB | Field | Required | Value Type | Description | | ----- | -------- | ---------- | ------------------- | | title | Yes | String | Attachment title | | url | Yes | String | Attachment URL | | name | Yes | String | Attachment filename | ### Audio To send an audio file, use the audio type. ```json { "type": "audio", "value": { "title": "This is a title", "name": "audio name", "url": "https://youtube.com/123456" } } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ----------- | ---------- | | url | Yes | String | Audio URL | n/a | | title | No | String | Audio title | 128 Bytes | | name | No | String | Audio name | 128 Bytes | ### Card To send a card with an image, description, and action buttons, use the card type. ```json { "type": "card", "value": { "title": "card title", "description": "This text is **bold**.", "imageUrl": "https://static-st1.zoomdev.us/static/6.3.34762/image/new/topNav/Zoom_logo.svg", "options": [ { "type": "option", "label": "Select case 1", "value": "case1" }, { "type": "link", "label": "More", "value": "https://example.com/link" } ] } } ``` | Field | Required | Value | Description | Limitation | | ----------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | title | No | String | Card title | 256 Bytes | | description | No | String | Standard Markdown format | 4096 Bytes | | imageUrl | Yes | String | Image URL | n/a | | options | Yes | List | List of card options | 20 | | mandatory | No | Boolean | If true, and the options list contains at least one option type item (button), the live chat client will disable the input box if the button is not clicked. Default: false | n/a | #### Card option types **Option button** To add an option button to a card, use type `option`. | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | -------------------- | ---------- | | type | Yes | String | `option` | | | label | Yes | String | Display name | 128 Bytes | | value | Yes | String | The identified value | n/a | **Link button** To add a link button to a card, use type `link`. | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ------------ | ---------- | | type | Yes | String | `link` | | | label | Yes | String | Display name | 128 Bytes | | value | Yes | String | URL | n/a | ### Carousel To send multiple cards in a carousel, use the carousel type. ```json { "type": "carousel", "value": { "cards": [ { "title": "carousel title 1", "description": "This is the first item.", "imageUrl": "https://images.unsplash.com/photo-1682685794304-99d3d07c57d2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=772&q=80", "options": [ { "type": "option", "label": "Select case 1", "value": "case1" }, { "type": "link", "label": "More", "value": "https://example.com/link" } ] }, { "title": "carousel title 2", "description": "This is the second item.", "imageUrl": "https://plus.unsplash.com/premium_photo-1691852519415-0df4c22e49e1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=774&q=80", "options": [ { "type": "option", "label": "Select case 1", "value": "case1" }, { "type": "link", "label": "More", "value": "https://example.com/link" } ] } ] } } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ----- | ------------------------------------------------------------- | ---------- | | cards | Yes | List | List of card objects with the same structure as the card type | 10 | ### Form To collect information from consumers through a form, use the form type. ```json { "type": "form", "value": { "name": "form name", "title": "form title", "subtitle": "I really like it ", "fields": [ { "type": "text", "label": "Name", "key": "name", "required": true, "defaultValue": "name" }, { "type": "single-select", "label": "Education", "key": "education", "required": true, "options": [ { "label": "High School Diploma", "value": "high_school" }, { "label": "Other", "value": "other" } ], "defaultValue": "high_school" }, { "type": "multi-select", "label": "Make you chocie", "key": "option", "required": true, "options": [ { "label": "Option1", "value": "1" }, { "label": "Option2", "value": "2" }, { "label": "Option3", "value": "3" } ], "defaultValue": ["1", "2"] } ] } } ``` | Field | Required | Value | Description | Limitation | | --------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | | name | No | String | Form name | | | title | No | String | Form title | 256 Bytes | | subtitle | No | String | Form subtitle | 1024 Bytes | | mandatory | No | Boolean | If true, and the field list contains at least one field element, the live chat client will disable the input box before the form has been submitted. Default: false. **Note**: Works with livechat SDK only. | | | fields | Yes | List | List of form fields | | #### Text input field To add a text input field to a form, use the text field type. ```json { "type": "text", "label": "Name", "key": "name", "required": true, "defaultValue": "", "pattern": "text" } ``` | Field | Required | Value | Description | Limitation | | ------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | | label | Yes | String | Field label | 128 Bytes | | key | Yes | String | Field key | 64 Bytes | | required | No | Boolean | Whether field is required | | | defaultValue | No | String | Default value | 256 Bytes | | pattern | No | String | Validation pattern: `text` (no rule)`email` (must be in email address format)`integer` (require input of positive integers)`decimal` (require decimal input)`custom` (use the regex set in field customRegex to do the validation). Default: text | | | customRegex | No | String | Regular expression for custom pattern validation | 128 characters | | errorLabel | No | String | The error message to show while the data is invalid | 128 characters | > **Note** > > Maximum text input value length is 256 Bytes. #### Select field To add a single-select dropdown to a form, use the single-select field type. ```json { "type": "single-select", "label": "Education", "key": "education", "required": true, "options": [ { "label": "High School Diploma", "value": "high_school" }, { "label": "Associate Degree", "value": "associate" }, { "label": "Bachelor's Degree", "value": "bachelor" }, { "label": "Doctoral Degree (Ph.D.)", "value": "doctor" }, { "label": "Other", "value": "other" } ], "defaultValue": "" } ``` | Field | Required | Value | Description | Limitation | | ------------ | -------- | ------- | ------------------------- | ---------- | | label | Yes | String | Field label | 128 Bytes | | key | Yes | String | Field key | 128 Bytes | | required | No | Boolean | Whether field is required | | | defaultValue | No | String | Default option value | | | options | Yes | List | List of select options | | **Select option** Each option in a select field has the following structure. ```json { "label": "Male", "value": "male" } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ------------------ | ---------- | | label | Yes | String | Display name | 128 Bytes | | value | Yes | String | The identify value | 128 Bytes | #### Multi-select field To add a multi-select dropdown to a form, use the multi-select field type. ```json { "type": "multi-select", "label": "Make you chocie", "key": "option", "required": true, "options": [ { "label": "Option1", "value": "1" }, { "label": "Option2", "value": "2" }, { "label": "Option3", "value": "3" } ], "defaultValues": ["1", "2"] } ``` | Field | Required | Value | Description | Limitation | | ------------ | -------- | ------- | ------------------------- | ---------- | | label | Yes | String | Field label | 128 Bytes | | key | Yes | String | Field key | 64 Bytes | | required | No | Boolean | Whether field is required | | | defaultValue | No | List | Default option values | | | options | Yes | List | List of select options | | **Multi-select option** Each option in a multi-select field has the following structure. ```json { "label": "Male", "value": "male" } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ----------------------------------------------------------------------- | ---------- | | label | Yes | String | Display name | 128 Bytes | | value | Yes | String | The identify value. Only strings consisting of a-z and 0-9 are allowed. | 64 Bytes | ### HTML To send HTML-formatted messages, use the html type. ```json { "type": "html", "value": "Page Title

HTML message

Zoom

Please type your query below

" } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | -------------------- | ---------- | | value | Yes | String | Standard HTML format | n/a | ### Image To send an image, use the image type. ```json { "type": "image", "value": { "title": "image title", "width": 300, "height": 200, "name": "zoom_logo", "altText": "This is a logo", "url": "https://zoom.us/logo.jpeg" } } ``` | Field | Required | Value Type | Description | Limitation | | ------- | -------- | ---------- | -------------------------------------- | ---------- | | url | Yes | String | Image URL | n/a | | width | No | Number | Image width | n/a | | height | No | Number | Image height | n/a | | name | No | String | Image name | 128 Bytes | | altText | No | String | Text displayed when hovering the mouse | 128 Bytes | ### Link To send a link, use the link type. ```json { "type": "link", "value": { "label": "link name", "url": "https://zoom.us" } } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ----------- | ---------- | | url | Yes | String | Link URL | n/a | | label | No | String | Link label | 128 Bytes | ### Markdown To send Markdown-formatted messages, use the markdown type. ```json { "type": "markdown", "value": "## This text is **bold**." } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ------------------------ | ---------- | | value | Yes | String | Standard Markdown format | n/a | ### Quick replies To provide quick reply buttons for consumer responses, use the quickReplies type. ```json { "type": "quickReplies", "value": { "title": "Please make your choice", "options": [ { "label": "Yes", "type": "postback", "value": "yes" }, { "label": "No", "type": "postback", "value": "no" } ], "mandatory": true } } ``` | Field | Required | Value | Description | Limitation | | ------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------- | ---------- | | title | Yes | String | Title text | 1024 Bytes | | options | Yes | List | List of quick reply options | 20 | | options.label | Yes | String | Display name | 128 Bytes | | options.type | Yes | String | Option type: `postback`, `phone_number`, `web_url`, `trigger_intent` | | | options.value | Yes | String | The identified value | n/a | | mandatory | No | Boolean | If true, the live chat client will disable the input box when the quick reply button is not clicked. Default: false | n/a | ### Text To send plain text messages, use the text type. ```json { "type": "text", "value": "Hi, I'm your virtual agent!" } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ----------- | ---------- | | value | Yes | String | Plain text | n/a | ### Video To send a video (YouTube), use the video type. ```json { "type": "video", "value": { "title": "This is a title", "name": "video name", "url": "https://youtube.com/123456" } } ``` | Field | Required | Value | Description | Limitation | | ----- | -------- | ------ | ----------- | ---------- | | url | Yes | String | Video URL | n/a | | title | No | String | Video title | 128 Bytes | | name | No | String | Video name | 128 Bytes |