Estimated reading time: 8 minutes Updated: 10/6/2026 Created by: Botmaker Team

Development of dynamic WhatsApp Flows in Botmaker

This document includes some recommendations for developers, drawn from experience developing dynamic WhatsApp Flows in Botmaker.



Considerations:

This document includes some recommendations for developers, drawn from experience developing dynamic WhatsApp Flows in Botmaker. It's important to clarify that it doesn't seek to replace Meta's official documentation; rather, it's complementary information.


META, official documentation:
https://developers.facebook.com/docs/whatsapp/flows


TIPS:

  1. Start with something simple and basic, then move on to greater complexity.
  2. Start with a blank template or a "Flow Template": (see: https://developers.facebook.com/docs/whatsapp/flows/templates) From there, you can modify the examples, test them, and copy the structure (JSON). This also works for testing other flows — just replace the example's full JSON with your own, then click "run" and select each screen to validate its structure.
  3. Review the components and tags that are available; it's important to adjust the character count, etc. (see: https://developers.facebook.com/docs/whatsapp/flows/reference/flowjson/components) It's important to know that some components, such as radio buttons, change their appearance depending on whether the platform is iOS or Android.
  4. It can be convenient to design the flow structure using the Playground and then export it to the Botmaker platform using the Copy Flow JSON button: https://developers.facebook.com/docs/whatsapp/flows/playground
  5. To add images, a useful practice is to go to the Playground and select "Add content/Media content/Image"; from there, you can upload an image and then copy the base64 from the JSON. This is useful for quickly checking the size and making sure it isn't too small or too large, and that the image's aspect ratio is what you expected.
  6. Currently, the only components that support the use of dynamic lists are "CheckboxGroup," "RadioButtonsGroup," and "Dropdown." In this regard, it's important to know that the flow must have a defined structure and data type for what it will receive, and these must match what the flow-type CA will send it. The call to the CA occurs when there is a "data_exchange," and this can happen when the footer button is pressed, but it's also available through "on-select-action."
  7. Always check that the "routing_model" has no errors or missing routes for each screen.
  8. Check that "data_channel_uri" matches the one corresponding to the FLOW-type CA, and that it's the correct endpoint.
  9. Flow response: brings back the data defined in the flow; if the variables were previously created on the platform, they will be "filled in" with the flow's data.

Example: Here's an example where the first screen sends a text, sends it to the endpoint, and returns it in uppercase to the second screen:


FLOW JSON

```

{

    "data_api_version": "3.0",

    "data_channel_uri": "https://functions.botmaker.com/whatsapp-flows/TuBusinessID/WabaID/dinamic",

    "routing_model": {

        "SHARE": ["RESPONSE"],

        "RESPONSE": []

    },

    "screens": [{

        "layout": {

            "children": [{

                "children": [{

                    "text": "Aquí puedes escribir tu nombre:",

                    "type": "TextSubheading"

                }, {

                    "name": "comment_text",

                    "label": "",

                    "type": "TextArea",

                    "required": true,

                    "helper-text": "Tus nombres y apellidos"

                }, {

                    "label": "Continuar",

                    "on-click-action": {

                        "payload": {

                            "comment_text": "${form.comment_text}"

                        },

                        "name": "data_exchange"

                    },

                    "type": "Footer"

                }],

                "name": "form",

                "type": "Form"

            }],

            "type": "SingleColumnLayout"

        },

        "data": {

            "comment_text": {

                "type": "string",

                "__example__": "Example"

            }

        },

        "id": "SHARE",

        "terminal": false,

        "title": "Share Name"

    }, {

        "layout": {

            "children": [{

                "children": [{

                    "text": "Antes de continuar revisa que tomamos correctamente tu nombre:",

                    "type": "TextCaption"

                }, {

                    "text": "${data.comment_text}",

                    "type": "TextSubheading"

                }, {

                    "label": "Finalizar",

                    "on-click-action": {

                        "payload": {

                            "comment_text": "${data.comment_text}"

                        },

                        "name": "complete"

                    },

                    "type": "Footer"

                }],

                "name": "form",

                "type": "Form"

            }],

            "type": "SingleColumnLayout"

        },

        "data": {

            "comment_text": {

                "type": "string",

                "__example__": "Example"

            }

        },

        "id": "RESPONSE",

        "terminal": true,

        "title": "Confirmation"

    }],

    "version": "2.1"

}


``` 

CA de tipo FLOW ENDPOINT  “dinamic”

```

const FIRST_SCREEN = screen === 'SHARE';

bmconsole.log(JSON.stringify(data));


if (FIRST_SCREEN) {

  flow.data = {

    comment_text: data.comment_text.toLocaleUpperCase(),

  };

  flow.nextScreen = 'RESPONSE';

  flow.send(); // remember to always call flow.send()

}

```


Remember to visit our Help Center for further information.