The AI agents Chat API uses webhooks to provide immediate, asynchronous event delivery. When you send a message to the Chat API, it responds with an empty 200 OK to acknowledge the request. The actual bot response is delivered separately to your configured webhook as soon as it’s ready.

This approach enables:

  • Proactive bot messaging: The bot can send messages or updates without waiting for a user prompt.
  • Real-time delivery: Each event (message, escalation, and so forth) generates an immediate webhook to your application.

For example, if a conversation begins and the user hasn't sent a message within a certain time, the bot can proactively send a prompt via webhook, such as "Are you still there?"

Supported webhook events

The Chat API webhook can receive the following event types:

Event TypeDescriptionExample Use
sendMessageBot sends a message to the visitorDisplay a message, carousel, or quick reply
escalateBot requests escalation to a human agentRoute the conversation to a support agent
isTeamOnlineBot checks if a team or agent is availableConfirm agent or team availability

Example: Handling webhook events

In the template project, webhooks are sent as POST requests to the /converse-webhook endpoint, but your application can use any endpoint you choose. Each payload includes details about the event type and relevant message data. Your application should process each event asynchronously, handle any required business logic, and respond with a 200 OK.

Here is an example handler in TypeScript:

/*** This method processes the Converse Webhook * It receives a DTO of type ConverseWebhookDto with the event details** It processes the request differently depending on the eventType field * of the payload** @param req* @param res* @param next*/public processEvent = async (req: Request, res: Response, next: NextFunction): Promise<void> => {  const requestBody: ConverseWebhookDto = req.body;  try {    this.converseWebhookService.processConverseWebhookEvent(requestBody);    res.status(200).send();  } catch (error: any) {    next(error);  }};

sendMessage event

The sendMessage event is the most common event sent to your application. It represents a message from the bot to the visitor and can deliver a simple text message, a list of buttons, or carousel cards. Your webhook should process each event asynchronously and respond with 200 OK to acknowledge receipt.

In the template project, you can handle sendMessage events using ConverseWebhookService. This service receives incoming webhook events from the bot and processes them asynchronously. Your application can then choose to forward the message directly to the customer or apply any custom logic before delivering it.

Example handler in TypeScript:

/** * Handles the Converse Webhook event. * @param converseWebhookDto Event payload from the bot */public processConverseWebhookEvent(converseWebhookDto: ConverseWebhookDto): void {  switch (converseWebhookDto.data.eventType) {    case ConverseWebhookEventTypes.SEND_MESSAGE:      // Process messages from the bot (text, button list, carousel, etc.)      logger.info(        `Received ${ConverseWebhookEventTypes.SEND_MESSAGE} event: ${JSON.stringify(converseWebhookDto)}`      );      // Add your application's logic here      break;    default:      // Handle other event types as needed      break;  }}

Text message

A simple text message from the bot.

FieldTypeDescription
botIdstringThe ID of the bot sending the event
data.eventTypestringSet to sendMessage
data.platformConversationIdstringConversation ID (external)
data.conversationIdstringInternal conversation ID (can be ignored)
data.typestringSet to text for a text message
data.replyIdstringThe reply ID that triggered this message
data.textstringThe text content of the message
data.buttonsarrayAlways empty for a simple text message
data.carouselCardsarrayAlways empty for a simple text message
data.predictedIntentsarrayArray of predicted intents for visitor message. Each object must contain:
- value: string (intent id)
- name: string (intent name)
- confidence: number (confidence score, 0–1)

Example:

{  "botId": "BOT_ID",  "data": {    "eventType": "sendMessage",    "platformConversationId": "13427e90-f76a-47c2-a26d-ea0b4f1836c5",    "conversationId": "CONVERSATION_ID",    "type": "text",    "replyId": "REPLY_ID",    "buttons": [],    "text": "Hello, this is a bot text message",    "carouselCards": [],    "predictedIntents": [      { "value": "1234", "name": "intent name", "confidence": 1 }    ]  }}

Button list message

A message from the bot containing a list of buttons the user can select.

FieldTypeDescription
botIdstringThe id of the bot sending the event
data.eventTypestringSet to sendMessage
data.platformConversationIdstringConversation id (external)
data.conversationIdstring(Optional) Internal conversation id
data.typestringSet to text for a button list message
data.replyIdstringThe reply id that triggered this message
data.textstringOptional. Main message text (can be omitted)
data.buttonsarrayArray of button objects. See Button object
data.carouselCardsarrayAlways empty for a button list message
data.predictedIntentsarrayArray of predicted intent objects. Each object must contain:
- value: string (intent id)
- name: string (intent name)
- confidence: number (confidence score, 0–1)

Button object

FieldTypeDescription
typestringMust be "button"
textstringThe button display text

Example:

{  "botId": "BOT_ID",  "data": {    "eventType": "sendMessage",    "platformConversationId": "13427e90-f76a-47c2-a26d-ea0b4f1836c5",    "conversationId": "CONVERSATION_ID",    "type": "text",    "replyId": "REPLY_ID",    "buttons": [      { "type": "button", "text": "YES" },      { "type": "button", "text": "NO" }    ],    "text": "It's a bot text message with 2 buttons",    "carouselCards": [],    "predictedIntents": [      { "value": "1234", "name": "intent name", "confidence": 1 }    ]  }}

A message from the bot containing a carousel of cards, each with optional buttons.

FieldTypeDescription
botIdstringThe id of the bot sending the event
data.eventTypestringSet to sendMessage
data.platformConversationIdstringConversation id (external)
data.conversationIdstring(Optional) Internal conversation id
data.typestringSet to carousel
data.replyIdstringThe reply id that triggered this message
data.textstringOptional. Message text (can be omitted for carousels)
data.buttonsarrayAlways empty for a carousel message
data.carouselCardsarrayArray of CarouselCard objects. See CarouselCard
data.predictedIntentsarrayArray of predicted intent objects. Each object must contain:
- value: string (intent id)
- name: string (intent name)
- confidence: number (confidence score, 0–1)

CarouselCard

Each object of type CarouselCard in the array must contain the following fields:

FieldTypeDescription
titlestringTitle of the carousel card
descriptionstringDescription of the card
imageUrlstringURL to the card image
buttonsarrayEach object of type Button must contain the following fields:
- type: string (set to the value "button")
- text:string (button text)

Example:

{  "botId": "BOT_ID",  "data": {    "eventType": "sendMessage",    "platformConversationId": "13427e90-f76a-47c2-a26d-ea0b4f1836c5",    "conversationId": "CONVERSATION_ID",    "type": "carousel",    "replyId": "REPLY_ID",    "buttons": [],    "text": "",    "carouselCards": [      {        "title": "card 1",        "description": "card 1 description",        "imageUrl": "URL",        "buttons": [          { "text": "button 1", "type": "button" },          { "text": "button 2", "type": "button" }        ]      },      {        "title": "card 2",        "description": "card 2 description",        "imageUrl": "URL",        "buttons": [          { "text": "button 1", "type": "button" },          { "text": "button 2", "type": "button" }        ]      }    ],    "predictedIntents": [      { "value": "1234", "name": "intent name", "confidence": 1 }    ]  }}

Response handling

A successful sendMessage will return a 200 response to the webhook request and no response body. A failed sendMessage will return a 4XX - 5XX range response to the webhook request.

escalate event

The escalate event occurs when the bot requests escalation to a human agent. Once this event is received, the bot stops sending messages to the visitor, and your application becomes responsible for managing the conversation flow—such as checking agent availability or adding the customer to a queue.

The template project processes this event using ConverseWebhookService. After the event is received, your application is responsible for handling the next steps, such as checking agent availability, adding the customer to a queue, or implementing any other relevant business logic.

Example webhook handler (TypeScript)

/**  * This method processes the Converse Webhook event.  * @param converseWebhookDto  */  public processConverseWebhookEvent(converseWebhookDto: ConverseWebhookDto): void {    switch (converseWebhookDto.data.eventType) {      case ConverseWebhookEventTypes.ESCALATE:        /**          * This event represents an escalation request from the bot.          *          * The payload of this event is represented in the BotEscalationEvent class.          *          * The request will be processed SYNCHRONOUSLY and respond if the escalation was successful (200) or not (4xx-5xx).          */        logger.info(          Received ${ConverseWebhookEventTypes.ESCALATE} event: \n ${JSON.stringify(converseWebhookDto)}`        );        break;      default:        break;    }  }}

Payload structure

FieldTypeDescription
botIdstringThe id of the bot sending the event
data.eventTypestringSet to escalate
data.platformConversationIdstringThe external conversation id
data.conversationIdstring(Optional) Internal conversation id
data.escalateTostring(Optional) The escalation team’s CRM id

Example:

{  "botId": "BOT_ID",  "data": {    "eventType": "escalate",    "platformConversationId": "13427e90-f76a-47c2-a26d-ea0b4f1836c5",    "escalateTo": "team_123"  }}

A successful escalation should return a 200 OK with no response body. Failure scenarios should return an appropriate 4XX or 5XX error code.

isTeamOnline event

The isTeamOnline event is sent when the bot needs to check if a specific support team or agent group is available. Your webhook should handle this event synchronously and respond with a boolean value indicating whether the requested team is online.

The ConverseWebhookService in our template project handles this event. After receiving the event, your application should implement the necessary logic internally, such as checking the availability of specific agents or agent groups.

Example handler (TypeScript)

/** * Processes the Converse Webhook event. * @param converseWebhookDto The event payload from the bot */public processConverseWebhookEvent(converseWebhookDto: ConverseWebhookDto): void {  switch (converseWebhookDto.data.eventType) {    case ConverseWebhookEventTypes.IS_TEAM_ONLINE:      /**       * Handles the event where the bot needs to check the availability of human agents.       * The payload for this event is defined in the BotIsTeamOnlineEvent class.       * Your application should process the request and respond with agent/team       * availability using the BotIsTeamOnlineEventResponse class.       */      logger.info(        `Received ${ConverseWebhookEventTypes.IS_TEAM_ONLINE} event: \n${JSON.stringify(          converseWebhookDto        )}`      );      // Add your availability-check logic here      break;    default:      break;  }}

Payload structure

FieldTypeDescription
botIdstringThe id of the bot sending the event
data.eventTypestringSet to isTeamOnline
data.conversationIdstring(Optional) Internal conversation id
data.teamIdstring(Optional) The team id to check for availability

Example:

{  "botId": "BOT_ID",  "data": {    "eventType": "isTeamOnline",    "teamId": "team_abc"  }}

Response structure

FieldTypeDescription
isOnlinebooleanReturns true if the team is available, false otherwise

Example:

{  "isOnline": true}