Send a card message

Stay organized with collections Save and categorize content based on your preferences.

In addition to text messages, Chat apps can send card messages in spaces and to users. Cards support a defined layout, interactive UI elements like buttons, and rich media like images.

Use card messages to:

  • Present detailed information
  • Gather information from users
  • Guide users to take a next step

This guide describes how to send card messages synchronously (a realtime response to a Chat event, like receiving a message from a user or getting added to a space) and asynchronously (sending a message from the app to a space or user without a prompt using the Chat REST API).

Prerequisites

To send the card messages in this guide, you need the following:

Node.js

Note: The Node.js code samples in this guide are written to run as a Google Cloud Function.

Python

Note: The Python code samples in this guide are written to run as a Google Cloud Function, using Python 3.9.

Apps Script

Anatomy of a card message

Each card, whether it is a dialog or a message, is a JSON object on the spaces.messages resource in Chat API.

The card JSON object consists of the following:

  1. An array called cardsV2[] which contains one or more CardWithId objects.
  2. A cardId, used to identify the card and scoped within a given message. (Cards in different messages can have the same ID.)
  3. A card object, which consists of the following:

    • A header object that specifies things like a title, subtitle, and avatar-style image.
    • One or more section objects that each contain at least one widget.
    • One or more widget objects. Each widget is a composite object that can represent text, images, buttons, and other object types.

      The following widgets are supported in card messages and dialogs:

      • TextParagraph–Displays a paragraph of text with optional simple HTML formatting.
      • Image–Displays a clickable or static .PNG or .JPG image hosted on an HTTPS URL.
      • DecoratedText–Displays text with optional layout and functionality features, like icons and buttons.
      • ButtonList–Displays a set of buttons.

      The following widgets are supported in dialogs (support for card messages coming soon):

      • TextInput–Field in which users can enter text.
      • SelectionInput–Provides a set of selectable items, like a list of checkboxes, radio buttons, switches, or a dropdown menu.

      • Divider–Displays a horizontal line spanning the width of a card between stacked widgets, acting as a visual divider.

      • Grid–Lays a set of items out in a simple grid.

      Support for the following widget is coming soon:

As an example, observe the header, section, and widget objects in the following card message:

A Chat app running a poll in a Chat space using a card message

The following code represents the JSON of the card message:

JSON

{
  "cardsV2": [
    {
      "cardId": "unique-card-id",
      "card": {
        "header": {
          "title": "Sasha",
          "subtitle": "Software Engineer",
          "imageUrl":
          "https://developers.google.com/chat/images/quickstart-app-avatar.png",
          "imageType": "CIRCLE",
          "imageAltText": "Avatar for Sasha",
        },
        "sections": [
          {
            "header": "Contact Info",
            "collapsible": true,
            "uncollapsibleWidgetsCount": 1,
            "widgets": [
              {
                "decoratedText": {
                  "startIcon": {
                    "knownIcon": "EMAIL",
                  },
                  "text": "sasha@example.com",
                }
              },
              {
                "decoratedText": {
                  "startIcon": {
                    "knownIcon": "PERSON",
                  },
                  "text": "<font color=\"#80e27e\">Online</font>",
                },
              },
              {
                "decoratedText": {
                  "startIcon": {
                    "knownIcon": "PHONE",
                  },
                  "text": "+1 (555) 555-1234",
                }
              },
              {
                "buttonList": {
                  "buttons": [
                    {
                      "text": "Share",
                      "onClick": {
                        "openLink": {
                          "url": "https://example.com/share",
                        }
                      }
                    },
                    {
                      "text": "Edit",
                      "onClick": {
                        "action": {
                          "function": "goToView",
                          "parameters": [
                            {
                              "key": "viewType",
                              "value": "EDIT",
                            }
                          ],
                        }
                      }
                    },
                  ],
                }
              },
            ],
          },
        ],
      },
    }
  ],
}

Send a synchronous card message

In this example, a user sends the Chat app a message in Google Chat and the app responds by sending a simple synchronous card message showing the sender's name and avatar image:

Chat app responding with a card featuring the sender's display name and avatar
image

In the following code samples, the Node.js and Python apps are hosted on Google Cloud Functions. The Apps Script example is hosted on Google Apps Script.

For full instructions describing how to build and deploy a Chat app, see Build a Chat app.

Node.js

node/avatar-bot/index.js
/**
 * Google Cloud Function that responds to messages sent from a
 * Hangouts Chat room.
 *
 * @param {Object} req Request sent from Hangouts Chat room
 * @param {Object} res Response to send back
 */
exports.helloChat = function helloChat(req, res) {
  if (req.method === 'GET' || !req.body.message) {
    res.send('Hello! This function is meant to be used in a Hangouts Chat ' +
      'Room.');
  }

  const sender = req.body.message.sender.displayName;
  const image = req.body.message.sender.avatarUrl;

  const data = createMessage(sender, image);

  res.send(data);
};

/**
 * Creates a card with two widgets.
 * @param {string} displayName the sender's display name
 * @param {string} imageUrl the URL for the sender's avatar
 * @return {Object} a card with the user's avatar.
 */
function createMessage(displayName, imageUrl) {
  const cardHeader = {
    title: `Hello ${displayName}!`,
  };

  const avatarWidget = {
    textParagraph: {text: 'Your avatar picture: '},
  };

  const avatarImageWidget = {
    image: {imageUrl},
  };

  const avatarSection = {
    widgets: [
      avatarWidget,
      avatarImageWidget,
    ],
  };

  return {
    cardsV2: [{
      cardId: 'avatarCard',
      card: {
        name: 'Avatar Card',
        header: cardHeader,
        sections: [avatarSection],
      }
    }],
  };
}

Python

python/avatar-bot/main.py
from typing import Any, Mapping

import flask
import functions_framework

# Google Cloud Function that responds to messages sent in
# Google Chat.
#
# @param {Object} req Request sent from Google Chat.
# @param {Object} res Response to send back.
@functions_framework.http
def hello_chat(req: flask.Request):
    if req.method == "GET":
        return "Hello! This function must be called from Google Chat."

    request_json = req.get_json(silent=True)

    display_name = request_json["message"]["sender"]["displayName"]
    avatar = request_json["message"]["sender"]["avatarUrl"]

    response = create_message(name=display_name, image_url=avatar)

    return response


# Creates a card with two widgets.
# @param {string} name the sender's display name.
# @param {string} image_url the URL for the sender's avatar.
# @return {Object} a card with the user's avatar.
def create_message(name: str, image_url: str) -> Mapping[str, Any]:
    avatar_image_widget = {"image": {"imageUrl": image_url}}
    avatar_text_widget = {"textParagraph": {"text": "Your avatar picture:"}}
    avatar_section = {"widgets": [avatar_text_widget, avatar_image_widget]}

    header = {"title": f"Hello {name}!"}

    cards = {
        "cardsV2": [
            {
                "cardId": "avatarCard",
                "card": {
                    "name": "Avatar Card",
                    "header": header,
                    "sections": [avatar_section],
                },
            }
        ]
    }

    return cards

Apps Script

apps-script/avatar-bot/hello-chat.gs
/**
 * Responds to a MESSAGE event in Google Chat.
 *
 * @param {Object} event the event object from Google Chat
 */
function onMessage(event) {
  const displayName = event.message.sender.displayName;
  const avatarUrl = event.message.sender.avatarUrl;

  return createMessage(displayName, avatarUrl);
}

/**
 * Creates a card with two widgets.
 * @param {string} displayName the sender's display name
 * @param {string} avatarUrl the URL for the sender's avatar
 * @return {Object} a card with the sender's avatar.
 */
function createMessage(displayName, avatarUrl) {
  const cardHeader = {
    title: `Hello ${displayName}!`
  };

  const avatarWidget = {
    textParagraph: {text: 'Your avatar picture: '}
  };

  const avatarImageWidget = {
    image: {imageUrl: avatarUrl}
  };

  const avatarSection = {
    widgets: [
      avatarWidget,
      avatarImageWidget
    ],
  };

  return {
    cardsV2: [{
      cardId: 'avatarCard',
      card: {
        name: 'Avatar Card',
        header: cardHeader,
        sections: [avatarSection],
      }
    }],
  };
}

Send an asynchronous card message with Chat API

This example asynchronously creates a message with Chat API and sends it to a space that the Chat app is added to, like the one shown below:

A card message created with Chat REST API.
Figure 1: A card message created with Chat REST API.

Python

  1. In your working directory, create a file named chat_create_card_message.py.
  2. Include the following code in chat_create_card_message.py:

    from httplib2 import Http
    from oauth2client.service_account import ServiceAccountCredentials
    from apiclient.discovery import build
    
    # Specify required scopes.
    SCOPES = ['https://www.googleapis.com/auth/chat.bot']
    
    # Specify service account details.
    CREDENTIALS = ServiceAccountCredentials.from_json_keyfile_name(
        'service_account.json', SCOPES)
    
    # Build the URI and authenticate with the service account.
    chat = build('chat', 'v1', http=CREDENTIALS.authorize(Http()))
    
    # Create a Chat message.
    result = chat.spaces().messages().create(
    
        # The space to create the message in.
        #
        # Replace SPACE with a space name.
        # Obtain the space name from the spaces resource of Chat API,
        # or from a space's URL.
        parent='spaces/SPACE',
    
        # The message to create.
        body=
        {
          'cardsV2': [{
            'cardId': 'createCardMessage',
            'card': {
              'header': {
                'title': 'A Card Message!',
                'subtitle': 'Created with Chat REST API',
                'imageUrl': 'https://developers.google.com/chat/images/chat-product-icon.png',
                'imageType': 'CIRCLE'
              },
              'sections': [
                {
                  'widgets': [
                    {
                      'buttonList': {
                        'buttons': [
                          {
                            'text': 'Read the docs!',
                            'onClick': {
                              'openLink': {
                                'url': 'https://developers.google.com/chat'
                              }
                            }
                          }
                        ]
                      }
                    }
                  ]
                }
              ]
            }
          }]
        }
    
    ).execute()
    
    print(result)
    
  3. In the code, replace SPACE with a space name, which you can obtain from the spaces.list() method in Chat API, or from a space's URL.

  4. In your working directory, build and run the sample:

    python3 chat_create_card_message.py
    

To learn more about working with messages in Chat REST API, see Create, read, update, delete messages.

Open a dialog

Dialogs are windowed, card-based interfaces that Chat apps open to interact with users. To help users complete multi-step processes, apps can open sequential dialogs. Apps can open dialogs in response to a button click on a card message or in response to a slash command.

Dialogs are useful for many types of user interactions, including:

  • Collecting information from users
  • Authenticating users with Web services
  • Configuring Chat app settings

In this example, a Chat app opens a dialog to help a user create a new contact for their address book:

A dialog featuring a variety of different widgets.

To implement dialogs, see Open dialogs.

Card formatting

Card text formatting

Inside cards, most text fields support basic text formatting via a small subset of HTML tags. The supported tags and their purpose are shown in the table below:

Bold <b> Italic <i>
Underline <> Strikethrough <strike>
Font Color <font color=""> Hyperlink <a href="">
Line Break <br>

Note that the text body of a basic message is parsed using a different markup syntax which is optimized for human users. For details, see Send a text message.

Built-in icons

The DecoratedText and ButtonList widgets support the icon element used to specify one of the built-in icons available in Google Chat:

{
  .
  .
  .
      "knownIcon": "TRAIN",
  .
  .
  .
}

The following table lists the built-in icons that are available for card messages:

AIRPLANE BOOKMARK
BUS CAR
CLOCK CONFIRMATION_NUMBER_ICON
DESCRIPTION DOLLAR
EMAIL EVENT_SEAT
FLIGHT_ARRIVAL FLIGHT_DEPARTURE
HOTEL HOTEL_ROOM_TYPE
INVITE MAP_PIN
MEMBERSHIP MULTIPLE_PEOPLE
PERSON PHONE
RESTAURANT_ICON SHOPPING_CART
STAR STORE
TICKET TRAIN
VIDEO_CAMERA VIDEO_PLAY

Custom icons

The DecoratedText and ButtonList widgets allow you to use the built-in icons listed above, or define your own custom icons. To specify a custom icon, use the iconUrl element as shown here:

{ . . . "iconUrl": "https://developers.google.com/chat/images/quickstart-app-avatar.png" . . . }

Limits and considerations

As you get ready to send card messages, take note of these limits and considerations.

  • The following widgets aren't supported by card messages, but support is coming soon:

    • TextInput, a field in which users can enter text.
    • SelectionInput, which provides a set of selectable items, like a list of checkboxes, radio buttons, switches, or a dropdown menu.
    • DateTimePicker, which lets users specify a date, time, or both.
    • Grid, which lays a set of items out in a simple grid.