Lectura estimada: 8 minutos Actualizado: 14/7/2026 Creado por: Equipo Botmaker

WhatsApp Flows dinámicos: conecta un endpoint e intercambia datos en tiempo real

En este artículo aprenderás a crear un Flow dinámico, configurar la Client Action que funciona como endpoint, propagar datos entre pantallas y mapear las variables en la plataforma Botmaker.



Un Flow dinámico es un WhatsApp Flow que se comunica con un servidor externo (el endpoint) mientras el usuario navega por las pantallas. A diferencia de un Flow estático —que solo recopila datos y los envía al final— un Flow dinámico intercambia información en tiempo real, lo que te permite cargar listas actualizadas, validar datos en el servidor y personalizar el contenido pantalla por pantalla.

Nota: Este artículo asume que ya sabes crear un Flow estático básico. El foco está exclusivamente en la parte dinámica.

Puedes:

  • Cargar listas de opciones en tiempo real (productos, horarios, ciudades, etc.).
  • Validar datos en el servidor antes de avanzar de pantalla.
  • Personalizar el contenido según el perfil del usuario.
  • Ejecutar lógica de negocio entre las pantallas.
  • Propagar los datos recopilados hasta el final del flujo.

Requisitos previos

Acceso a tu cuenta de Botmaker con permisos para crear Client Actions y administrar WhatsApp Flows. Un WhatsApp Flow ya creado (aunque sea con una sola pantalla) sobre el que vas a trabajar. Conocimiento básico de la estructura de un Flow JSON.


Conceptos clave

Flow dinámico: WhatsApp Flow que se comunica con un endpoint durante la navegación del usuario, en lugar de enviar los datos solo al final.

Endpoint: servicio que recibe los datos de la pantalla actual, ejecuta la lógica necesaria y devuelve la siguiente pantalla junto con los datos que debe mostrar. En Botmaker se implementa mediante una Client Action (CA) del tipo WA Flow Endpoint.

Client Action (CA): acción de código de Botmaker. Para Flows dinámicos debe ser del tipo WA Flow Endpoint — ningún otro tipo funciona como backend de un Flow.

data_exchange: acción que se dispara cuando el usuario hace clic en el botón de una pantalla configurada con ella. Envía los datos de la pantalla actual al endpoint.

Payload: objeto JSON que se intercambia entre el Flow y el endpoint. Botmaker lo entrega ya descifrado.

Propagación de datos: técnica para reenviar manualmente, pantalla a pantalla, los datos recopilados en pantallas anteriores para que lleguen al final del flujo.


Tipos de action que recibe el endpoint

INIT: el Flow se abrió con flow_action: data_exchange (la primera pantalla se carga dinámicamente). Debes devolver los datos iniciales de la primera pantalla. data_exchange: el usuario hizo clic en el botón del footer con esta acción. Debes procesar los datos enviados y devolver la siguiente pantalla.

BACK: el usuario volvió a una pantalla con refresh_on_back: true. Debes recargar los datos de la pantalla anterior.

ping: health check periódico de Meta. Debes responder siempre con { status: 'active' }.



Cómo crear y configurar un Flow dinámico

Paso 1: Crea la Client Action (CA)

  • Accede al menú Código en la plataforma Botmaker y haz clic en Crear nueva acción de código.
  • Completa los campos: Nombre (por ejemplo, flow-agendamiento-endpoint), TipoWA Flow Endpoint, y Plantilla de códigoflow_basic_template para comenzar con la estructura base.
  • Haz clic en Publicar.


Atención: Solo las CA del tipo WA Flow Endpoint son compatibles con Flows dinámicos. Los demás tipos (Usuario, Endpoint común) no funcionan como backend de un Flow.


Paso 2: Copia la URL del servicio

Después de publicar, abre la pestaña General de la CA y copia la URL del servicio. Tiene este formato:

https://functions.botmaker.com/whatsapp-flows/{BusinessID}/{WabaID}/{nombreDeLaCA}

Guarda esta URL: la vas a usar como Endpoint URI en la configuración del Flow.


Atención: El Flow solo funciona en el WABA ID en el que fue configurado. Asegúrate de usar la URL correspondiente al WABA correcto; cambiar de WABA hará que el Flow deje de funcionar.


Paso 3: Vincula el endpoint al Flow

  • Accede a Chatbots → WhatsApp Flows y abre el Flow deseado.
  • Ve a la pestaña General y pega la URL copiada en el campo Endpoint URI.

A partir de ese momento, toda pantalla del Flow configurada con la acción data_exchange llamará a tu CA automáticamente.

Consejo: Cada Flow puede tener un solo endpoint. Si tienes varios flujos con lógicas distintas, crea CAs separadas —o maneja toda la lógica dentro de una sola CA identificando la screen recibida.


Paso 4: Entiende qué recibe y qué debe devolver el endpoint

Al ser llamado por el Flow, el endpoint recibe un payload JSON ya descifrado por Botmaker:

{

  "version": "3.0",

  "action": "data_exchange",

  "flow_token": "<token>",

  "screen": "NOMBRE_DE_LA_SCREEN_ACTUAL",

  "data": {

    "campo_enviado": "valor ingresado por el usuario"

  }

}

El endpoint siempre debe devolver un JSON con la siguiente pantalla y los datos que necesita para renderizar:

{

  "screen": "PROXIMA_SCREEN",

  "data": {

    "variable_de_la_siguiente_pantalla": "valor"

  }

}

Para listas dinámicas usadas en componentes como RadioButtonsGroup, CheckboxGroup o Dropdown, el array debe seguir este formato:

{

  "screen": "SELECCION",

  "data": {

    "lista_opciones": [

      { "id": "1", "title": "Opción A" },

      { "id": "2", "title": "Opción B" }

    ]

  }

}

Nota: Solo CheckboxGroup, RadioButtonsGroup y Dropdown soportan listas dinámicas. El tipo de dato definido en el Flow JSON debe coincidir exactamente con lo que devuelve la CA.


Paso 5: Escribe la lógica de la Client Action

La CA recibe las variables globales screen y data. Úsalas para identificar en qué pantalla está el usuario y qué envió. Esta es la estructura base:

// Manejar el ping (health check obligatorio)

if (!screen || data.action === 'ping') {

  flow.data = { status: 'active' };

  flow.send();

  return;

}


// Primera pantalla: devolver lista dinámica

if (screen === 'SELECCION') {

  flow.data = {

    lista_productos: [

      { id: 'p1', title: 'Producto A' },

      { id: 'p2', title: 'Producto B' },

    ],

  };

  flow.nextScreen = 'CONFIRMACION';

  flow.send();


// Segunda pantalla: procesar selección

} else if (screen === 'CONFIRMACION') {

  flow.data = {

    resumen: `Elegiste: ${data.producto_seleccionado}`,

  };

  flow.nextScreen = 'RESULTADO';

  flow.send();

}


Atención: Llama siempre a flow.send() al final de cada bloque. Si lo olvidas, el Flow queda bloqueado esperando la respuesta del endpoint.


Importante: El ping debe manejarse obligatoriamente. Si el endpoint no responde correctamente al health check de Meta, el Flow puede marcarse como no disponible y dejar de funcionar para los usuarios.

Cuando una pantalla tiene la propiedad refresh_on_back: true en el Flow JSON, al volver hacia ella el endpoint se llama con action: BACK. Úsalo para recargar datos o limpiar selecciones anteriores:

if (data.action === 'BACK' && screen === 'SELECCION') {

  flow.data = {

    lista_productos: buscarProductosActualizados(),

  };

  flow.nextScreen = 'SELECCION';

  flow.send();

}


Paso 6: Referencia los datos en las pantallas (Flow JSON)

Los datos devueltos por el endpoint quedan disponibles en las pantallas con la sintaxis ${data.nombre_del_campo}. Los datos completados por el usuario en un formulario se acceden con ${form.nombre_del_campo}.

Para mostrar un dato del endpoint:

{

  "type": "TextSubheading",

  "text": "${data.resumen}"

}

Para enviar un dato del formulario al endpoint:

{

  "on-click-action": {

    "name": "data_exchange",

    "payload": {

      "producto_seleccionado": "${form.producto_seleccionado}"

    }

  }

}


Paso 7: Propaga los datos entre pantallas

Meta envía a Botmaker solo las variables presentes en el payload de la última pantalla, no las de todas las pantallas automáticamente. Para que los datos recopilados en pantallas anteriores lleguen al final, tienes que propagarlos manualmente: al navegar de una pantalla a otra, incluye en el payload del on-click-action tanto los campos completados en la pantalla actual como los datos recibidos de pantallas anteriores vía ${data.xxx}.

Por ejemplo, en un Flow de registro con tres pantallas, la Pantalla 1 recopila datos y navega a la Pantalla 2 pasándolos:

"on-click-action": {

  "name": "navigate",

  "next": { "type": "screen", "name": "PANTALLA_2" },

  "payload": {

    "nombre":               "${form.TextInput_nombre}",

    "razon_social":         "${form.TextInput_razon}",

    "cuit":                 "${form.TextInput_cuit}",

    "inscripcion_estadual": "${form.TextInput_ie}"

  }

}

La Pantalla 2 recibe esos campos vía ${data.xxx}, agrega los nuevos y los reenvía a la Pantalla 3. La Pantalla final usa complete (no data_exchange) y acumula todo para enviarlo a Botmaker:

"on-click-action": {

  "name": "complete",

  "payload": {

    "nombre":               "${data.nombre}",

    "razon_social":         "${data.razon_social}",

    "cuit":                 "${data.cuit}",

    "inscripcion_estadual": "${data.inscripcion_estadual}",

    "tel_celular":          "${data.tel_celular}",

    "tel_fijo":             "${data.tel_fijo}",

    "email":                "${form.TextInput_email}",

    "clave":                "${form.TextInput_clave}"

  }

}


Importante: Sin esta propagación explícita, solo los campos de la última pantalla llegarán al payload; todos los datos anteriores se perderán.


Paso 8: Mapea las variables en la plataforma Botmaker

Cuando el Flow se completa, los datos del payload llegan a Botmaker con nombres genéricos generados automáticamente (por ejemplo, screen_0_TextInput_3). Para usarlos con facilidad en tus automatizaciones, mapea cada campo a una variable con nombre amigable.

  • Abre el Flow y haz clic en la pestaña Variables. Verás la lista de todos los campos recopilados con sus nombres genéricos.
  • Para cada campo, haz clic en el selector de la derecha y define la variable de Botmaker donde se guardará el dato.


Por ejemplo, el campo screen_0_TextInput_0 se mapea a ${nombreEmpresa}, screen_0_TextInput_1 a ${razonSocial}, y así sucesivamente.

Nota: Si no configuras ninguna variable, los datos se guardarán con los nombres genéricos del Flow —funcionales, pero menos legibles para quienes configuran automatizaciones.


Checklist antes de publicar

Antes de poner tu Flow dinámico en producción, verifica que:

  • El routing_model cubre todas las pantallas y no tiene rutas faltantes.
  • El data_channel_uri apunta a la CA correcta con el endpoint correspondiente.
  • El ping se maneja en la CA y devuelve { status: 'active' }.
  • Cada bloque de la CA llama a flow.send().
  • Los datos se propagan entre pantallas en el payload del on-click-action.
  • La pantalla final usa complete (no data_exchange) y no llama al endpoint.
  • Las variables fueron mapeadas en la pestaña Variables del Flow.
  • El Flow fue probado en el Playground con el JSON completo.


Consejo: Para probar el Flow JSON antes de publicar, accede al Playground de Meta (developers.facebook.com/docs/whatsapp/flows/playground), reemplaza el JSON de ejemplo por el tuyo, haz clic en Run y selecciona cada pantalla para validar la estructura.


Ejemplo completo comentado

Este Flow tiene dos pantallas: el usuario escribe su nombre en la primera, el endpoint lo devuelve en mayúsculas y la segunda muestra el resultado para confirmación.

Flow JSON:

{

  "data_api_version": "3.0",

  "data_channel_uri": "https://functions.botmaker.com/whatsapp-flows/{BusinessID}/{WabaID}/dinamic",

  "routing_model": {

    "SHARE": ["RESPONSE"],

    "RESPONSE": []

  },

  "screens": [

    {

      "id": "SHARE",

      "title": "Ingresá tu nombre",

      "terminal": false,

      "data": { "comment_text": { "type": "string", "__example__": "Ejemplo" } },

      "layout": {

        "type": "SingleColumnLayout",

        "children": [{

          "type": "Form", "name": "form",

          "children": [

            { "type": "TextSubheading", "text": "Escribí tu nombre completo:" },

            { "type": "TextArea", "name": "comment_text", "required": true,

              "helper-text": "Nombre y apellido" },

            { "type": "Footer", "label": "Continuar",

              "on-click-action": {

                "name": "data_exchange",

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

              }}

          ]

        }]

      }

    },

    {

      "id": "RESPONSE",

      "title": "Confirmación",

      "terminal": true,

      "data": { "comment_text": { "type": "string", "__example__": "EJEMPLO" } },

      "layout": {

        "type": "SingleColumnLayout",

        "children": [{

          "type": "Form", "name": "form",

          "children": [

            { "type": "TextCaption", "text": "Confirmá tu nombre:" },

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

            { "type": "Footer", "label": "Finalizar",

              "on-click-action": {

                "name": "complete",

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

              }}

          ]

        }]

      }

    }

  ],

  "version": "2.1"

}

CA de tipo WA Flow Endpoint — dinamic:

// Manejar ping

if (!screen || data.action === 'ping') {

  flow.data = { status: 'active' };

  flow.send();

  return;

}


// Pantalla SHARE: devolver el nombre en mayúsculas

if (screen === 'SHARE') {

  flow.data = {

    comment_text: data.comment_text.toLocaleUpperCase(),

  };

  flow.nextScreen = 'RESPONSE';

  flow.send();

}



Para dar tus primeros pasos con WhatsApp Flows en Botmaker, te compartimos el artículo "Paso a paso de creación de WhatsApp Flows en Botmaker". Para crear la acción de código, consulta "Creación de acción de código en Botmaker", y para el mapeo, "Creación de variables en Botmaker".



Recuerda visitar nuestro Centro de Ayuda para mayor información