Leitura de 8 minutos Atualizada: 14/07/2026 Criado pela: Equipe Botmaker

WhatsApp Flows dinâmicos: conecte um endpoint e troque dados em tempo real

Neste artigo você vai aprender a criar um Flow dinâmico, configurar a Client Action que funciona como endpoint, propagar dados entre telas e mapear as variáveis na plataforma Botmaker.



Um Flow dinâmico é um WhatsApp Flow que se comunica com um servidor externo (o endpoint) enquanto o usuário navega pelas telas. Diferente de um Flow estático — que apenas coleta dados e os envia no final — um Flow dinâmico troca informações em tempo real, o que permite carregar listas atualizadas, validar dados no servidor e personalizar o conteúdo tela a tela.

Observação: Este artigo pressupõe que você já sabe criar um Flow estático básico. O foco está exclusivamente na parte dinâmica.

Você pode:

  • Carregar listas de opções em tempo real (produtos, horários, cidades, etc.).
  • Validar dados no servidor antes de avançar de tela.
  • Personalizar o conteúdo de acordo com o perfil do usuário.
  • Executar lógica de negócio entre as telas.
  • Propagar os dados coletados até o final do fluxo.


Pré-requisitos

Acesso à sua conta Botmaker com permissões para criar Client Actions e administrar WhatsApp Flows. Um WhatsApp Flow já criado (mesmo que com uma única tela) sobre o qual você vai trabalhar. Conhecimento básico da estrutura de um Flow JSON.


Conceitos-chave

Flow dinâmico: WhatsApp Flow que se comunica com um endpoint durante a navegação do usuário, em vez de enviar os dados apenas no final.

Endpoint: serviço que recebe os dados da tela atual, executa a lógica necessária e devolve a próxima tela junto com os dados que ela deve exibir. No Botmaker é implementado por meio de uma Client Action (CA) do tipo WA Flow Endpoint.

Client Action (CA): ação de código do Botmaker. Para Flows dinâmicos, ela deve ser do tipo WA Flow Endpoint — nenhum outro tipo funciona como backend de um Flow.

data_exchange: ação disparada quando o usuário clica no botão de uma tela configurada com ela. Envia os dados da tela atual ao endpoint.

Payload: objeto JSON trocado entre o Flow e o endpoint. O Botmaker o entrega já descriptografado.

Propagação de dados: técnica para reencaminhar manualmente, tela a tela, os dados coletados em telas anteriores para que cheguem ao final do fluxo.


Tipos de action que o endpoint recebe

INIT: o Flow foi aberto com flow_action: data_exchange (a primeira tela é carregada dinamicamente). Você deve devolver os dados iniciais da primeira tela. data_exchange: o usuário clicou no botão do footer com esta ação. Você deve processar os dados enviados e devolver a próxima tela.

ACK: o usuário voltou para uma tela com refresh_on_back: true. Você deve recarregar os dados da tela anterior.

ping: health check periódico da Meta. Você deve responder sempre com { status: 'active' }.



Como criar e configurar um Flow dinâmico

Passo 1: Crie a Client Action (CA)

  • Acesse o menu Código na plataforma Botmaker e clique em Criar nova ação de código.
  • Preencha os campos: Nome (por exemplo, flow-agendamento-endpoint), TipoWA Flow Endpoint e Template de códigoflow_basic_template para começar com a estrutura base.
  • Clique em Publicar.


Atenção: Apenas as CA do tipo WA Flow Endpoint são compatíveis com Flows dinâmicos. Os demais tipos (Usuário, Endpoint comum) não funcionam como backend de um Flow.


Passo 2: Copie a URL do serviço

Depois de publicar, abra a aba Geral da CA e copie a URL do serviço. Ela tem este formato:

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

Guarde esta URL: você vai usá-la como Endpoint URI na configuração do Flow.


Atenção: O Flow só funciona no WABA ID em que foi configurado. Certifique-se de usar a URL correspondente ao WABA correto; trocar de WABA fará com que o Flow pare de funcionar.


Passo 3: Vincule o endpoint ao Flow

  • Acesse Chatbots → WhatsApp Flows e abra o Flow desejado.
  • Vá até a aba Geral e cole a URL copiada no campo Endpoint URI.

A partir desse momento, toda tela do Flow configurada com a ação data_exchange chamará sua CA automaticamente.


Dica: Cada Flow pode ter apenas um endpoint. Se você tem vários fluxos com lógicas diferentes, crie CAs separadas — ou trate toda a lógica dentro de uma única CA identificando a screen recebida.


Passo 4: Entenda o que o endpoint recebe e o que ele deve devolver

Ao ser chamado pelo Flow, o endpoint recebe um payload JSON já descriptografado pelo Botmaker:

{

  "version": "3.0",

  "action": "data_exchange",

  "flow_token": "<token>",

  "screen": "NOME_DA_SCREEN_ATUAL",

  "data": {

    "campo_enviado": "valor informado pelo usuário"

  }

}

O endpoint sempre deve devolver um JSON com a próxima tela e os dados que ela precisa para renderizar:

{

  "screen": "PROXIMA_SCREEN",

  "data": {

    "variavel_da_proxima_tela": "valor"

  }

}


Para listas dinâmicas usadas em componentes como RadioButtonsGroup, CheckboxGroup ou Dropdown, o array deve seguir este formato:

{

  "screen": "SELECAO",

  "data": {

    "lista_opcoes": [

      { "id": "1", "title": "Opção A" },

      { "id": "2", "title": "Opção B" }

    ]

  }

}


Observação: Apenas CheckboxGroup, RadioButtonsGroup e Dropdown suportam listas dinâmicas. O tipo de dado definido no Flow JSON deve corresponder exatamente ao que a CA devolve.


Passo 5: Escreva a lógica da Client Action

A CA recebe as variáveis globais screen e data. Use-as para identificar em qual tela o usuário está e o que ele enviou. Esta é a estrutura base:

// Tratar o ping (health check obrigatório)

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

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

  flow.send();

  return;

}


// Primeira tela: devolver lista dinâmica

if (screen === 'SELECAO') {

  flow.data = {

    lista_produtos: [

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

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

    ],

  };

  flow.nextScreen = 'CONFIRMACAO';

  flow.send();


// Segunda tela: processar seleção

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

  flow.data = {

    resumo: `Você escolheu: ${data.produto_selecionado}`,

  };

  flow.nextScreen = 'RESULTADO';

  flow.send();

}


Atenção: Chame sempre flow.send() no final de cada bloco. Se você esquecer, o Flow fica travado aguardando a resposta do endpoint.

Importante: O ping deve ser tratado obrigatoriamente. Se o endpoint não responder corretamente ao health check da Meta, o Flow pode ser marcado como indisponível e parar de funcionar para os usuários.

Quando uma tela tem a propriedade refresh_on_back: true no Flow JSON, ao voltar para ela o endpoint é chamado com action: BACK. Use isso para recarregar dados ou limpar seleções anteriores:

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

  flow.data = {

    lista_produtos: buscarProdutosAtualizados(),

  };

  flow.nextScreen = 'SELECAO';

  flow.send();

}


Passo 6: Referencie os dados nas telas (Flow JSON)

Os dados devolvidos pelo endpoint ficam disponíveis nas telas com a sintaxe ${data.nome_do_campo}. Os dados preenchidos pelo usuário em um formulário são acessados com ${form.nome_do_campo}.

Para exibir um dado do endpoint:

{

  "type": "TextSubheading",

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

}

Para enviar um dado do formulário ao endpoint:

{

  "on-click-action": {

    "name": "data_exchange",

    "payload": {

      "produto_selecionado": "${form.produto_selecionado}"

    }

  }

}


Passo 7: Propague os dados entre as telas

A Meta envia ao Botmaker apenas as variáveis presentes no payload da última tela, e não as de todas as telas automaticamente. Para que os dados coletados em telas anteriores cheguem ao final, você precisa propagá-los manualmente: ao navegar de uma tela para outra, inclua no payload do on-click-action tanto os campos preenchidos na tela atual quanto os dados recebidos de telas anteriores via ${data.xxx}.

Por exemplo, em um Flow de cadastro com três telas, a Tela 1 coleta dados e navega para a Tela 2 passando-os:

"on-click-action": {

  "name": "navigate",

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

  "payload": {

    "nome":               "${form.TextInput_nome}",

    "razao_social":       "${form.TextInput_razao}",

    "cnpj":               "${form.TextInput_cnpj}",

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

  }

}


A Tela 2 recebe esses campos via ${data.xxx}, adiciona os novos e os reencaminha para a Tela 3. A tela final usa complete (não data_exchange) e acumula tudo para enviar ao Botmaker:

"on-click-action": {

  "name": "complete",

  "payload": {

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

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

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

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

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

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

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

    "senha":              "${form.TextInput_senha}"

  }

}


Importante: Sem essa propagação explícita, apenas os campos da última tela chegarão ao payload; todos os dados anteriores serão perdidos.


Passo 8: Mapeie as variáveis na plataforma Botmaker

Quando o Flow é concluído, os dados do payload chegam ao Botmaker com nomes genéricos gerados automaticamente (por exemplo, screen_0_TextInput_3). Para usá-los com facilidade nas suas automações, mapeie cada campo para uma variável com nome amigável.

  • Abra o Flow e clique na aba Variáveis. Você verá a lista de todos os campos coletados com seus nomes genéricos.
  • Para cada campo, clique no seletor à direita e defina a variável do Botmaker onde o dado será salvo.


Por exemplo, o campo screen_0_TextInput_0 é mapeado para ${nomeEmpresa}, screen_0_TextInput_1 para ${razaoSocial}, e assim por diante.


Observação: Se você não configurar nenhuma variável, os dados serão salvos com os nomes genéricos do Flow — funcionais, mas menos legíveis para quem configura automações.


Checklist antes de publicar

Antes de colocar seu Flow dinâmico em produção, verifique se:

  • O routing_model cobre todas as telas e não tem rotas faltando.
  • O data_channel_uri aponta para a CA correta com o endpoint correspondente.
  • O ping é tratado na CA e devolve { status: 'active' }.
  • Cada bloco da CA chama flow.send().
  • Os dados são propagados entre as telas no payload do on-click-action.
  • A tela final usa complete (não data_exchange) e não chama o endpoint.
  • As variáveis foram mapeadas na aba Variáveis do Flow.
  • O Flow foi testado no Playground com o JSON completo.


Dica: Para testar o Flow JSON antes de publicar, acesse o Playground da Meta (developers.facebook.com/docs/whatsapp/flows/playground), substitua o JSON de exemplo pelo seu, clique em Run e selecione cada tela para validar a estrutura.


Exemplo completo comentado

Este Flow tem duas telas: o usuário digita o nome na primeira, o endpoint o devolve em maiúsculas e a segunda exibe o resultado para confirmação.

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": "Informe seu nome",

      "terminal": false,

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

      "layout": {

        "type": "SingleColumnLayout",

        "children": [{

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

          "children": [

            { "type": "TextSubheading", "text": "Digite seu nome completo:" },

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

              "helper-text": "Nome e sobrenome" },

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

              "on-click-action": {

                "name": "data_exchange",

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

              }}

          ]

        }]

      }

    },

    {

      "id": "RESPONSE",

      "title": "Confirmação",

      "terminal": true,

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

      "layout": {

        "type": "SingleColumnLayout",

        "children": [{

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

          "children": [

            { "type": "TextCaption", "text": "Confirme seu nome:" },

            { "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 do tipo WA Flow Endpoint — dinamic:

// Tratar ping

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

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

  flow.send();

  return;

}


// Tela SHARE: devolver o nome em maiúsculas

if (screen === 'SHARE') {

  flow.data = {

    comment_text: data.comment_text.toLocaleUpperCase(),

  };

  flow.nextScreen = 'RESPONSE';

  flow.send();

}


Para dar seus primeiros passos com WhatsApp Flows no Botmaker, veja o artigo "Passo a passo de criação do WhatsApp Flows no Botmaker". Para criar a ação de código, consulte "Criação de ação de código no Botmaker" e, para o mapeamento, "Criação de variáveis no Botmaker".



Lembre-se de visitar nossa Central de Ajuda para obter mais informações.