Pattern For Handling Chat App Cards With Multiple Input Components

I have created a Chat Bot that, upon some event, sends a message to the user that renders a Zoom Chat App Card (see Sign In | Zoom)

But the way this works seems EXTREMELY limited. Is it really true that a post message is sent for EVERY interaction and that there is no way to develop a simple form-submit design pattern?

This is CRAZY to me. All I want to do is have the user fill in a few fields, click a submit button and have my chatbot endpoint URL receive all the submitted data. This seems impossible without some elaborate caching technique on the backend.

Slack has a proper architecture for this and it seems like Zoom is misrepresenting how functional their alternative is here. The examples lead you to believe it is straightforward to build a submit form when it really, really isn’t.

Not to mention there is no documentation on how to handle multi-part forms.

Please, Zoom, provide some guidance here.

Hi @Luke7
Thanks for reaching out to us and welcome to the Zoom Developer Forum, I am happy to help here!
Have you looked into the Customize chatbot messages section in our docs here:

Please let me know if this helps

Yes. This is similar to the link I posted in my message. The only way I can achieve true multi-form behaviour is to open a modal dialog but … those don’t seem to work on ios as far as I can tell.

So, I have multiple issues with Zoom here and documentation is limited.

@Luke7 , Thank you for posting in the Zoom Developer Forum. It is to develop a simple form-submit design pattern. You want to leverage the Simple Form found in the template section.

Here is example of what the JSON looks like for the Card form structure. Also, it a card form is a standard bot message with two additions:

1. `settings.form: true` — marks the entire card as a form

2. `submit: true` on the action button — designates that button as the form’s submit trigger

Example JSON:

{
  "content": {
    "settings": {
      "form": true
    },
    "head": {
      "text": "Entertainment",
      "style": {
        "bold": true
      }
    },
    "body": [
      {
        "type": "section",
        "sections": [
          {
            "type": "message",
            "text": "Sign up entertainment club",
            "style": {
              "bold": true
            }
          },
          {
            "type": "plain_text_input",
            "action_id": "action_id_001",
            "text": "First name:",
            "value": "",
            "placeholder": "Input first name"
          },
          {
            "type": "plain_text_input",
            "action_id": "action_id_002",
            "text": "Last name:",
            "value": "",
            "placeholder": "Input last name"
          },
          {
            "type": "message",
            "text": "Sex:"
          },
          {
            "type": "radio_buttons",
            "options": [
              {
                "value": "male",
                "text": "Male"
              },
              {
                "value": "female",
                "text": "Female"
              }
            ],
            "action_id": "action_id_003"
          },
          {
            "type": "select",
            "text": "Entertainment Club:",
            "select_items": [
              {
                "text": "basketball",
                "value": "basketball"
              },
              {
                "text": "tennis",
                "value": "tennis"
              },
              {
                "text": "badminton",
                "value": "badminton"
              }
            ]
          },
          {
            "type": "actions",
            "items": [
              {
                "value": "submit",
                "text": "Submit",
                "style": "Primary",
                "submit": true
              }
            ]
          }
        ]
      }
    ]
  }
}

## Webhook event: `chat_message.submit`

Fired when a user clicks a `submit: true` button on a card form. All input field values are delivered in `payload.object.submit_items`.

Event payload structure:

{

"event": "chat_message.submit",

"payload": {

"account_id": "your_account_id",

"object": {

"bot_msg_id": "20260514...",

"parent_msg_id": "uuid",

"reply_main_message_id": "uuid",

"robot_jid": "your_bot_jid",

"submit_form_id": "",

"submit_items": [

        {

"actionItem": {

"text": "Submit",

"value": "my_submit_action",

"action": "command",

"action_id": "my_submit_action"

          }

        },

        {

"plain_text_input": {

"text": "What was done?",

"value": "Helped review a critical blog post before publication.",

"action_id": "what_was_done"

          }

        },

        {

"plain_text_input": {

"text": "Why it mattered",

"value": "The blog needed to be published same day.",

"action_id": "why_it_mattered"

          }

        },

        {

"plain_text_input": {

"text": "Who it helped",

"value": "The entire marketing organization.",

"action_id": "who_it_helped"

          }

        }

      ],

"to_jid": "recipient_jid",

"user_jid": "submitting_user_jid",

"trigger_id": "...",

"timestamp": 1778709054515

    },

"operator_id": "...",

"operator_status": "authorized"

  }

}