/flows), pela API REST (/v1/flows), ou anexar um Flow a um template com um botão FLOW.
Flows existem apenas em números Meta (API Oficial). Eles pertencem à conta WhatsApp Business (WABA), não a um número — então todo número daquela WABA envia os mesmos Flows.
Dois tipos de Flow
A diferença é se o seu backend participa enquanto o formulário está aberto.
Um Flow
NAVIGATE é entregue, preenchido e enviado uma vez. Você recebe a resposta inteira no fim. A maioria dos Flows é assim, e não precisa de nada além do Flow JSON.
Um Flow data_exchange responde no meio do formulário: o cliente escolhe a data e a tela seguinte mostra os horários que estão de fato livres. Isso exige um endpoint HTTPS que a Meta chama a cada tela — e a Meta cifra cada uma dessas chamadas.
Ciclo de vida
1
Criar
O Flow nasce em
DRAFT. Dê um nome e uma ou mais categorias (SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY, OTHER).2
Subir o Flow JSON
As telas são um documento JSON. A Meta responde
200 com a lista de erros de validação em vez de recusar — então resposta verde não significa que o documento compilou. Leia sempre validationErrors.3
Publicar
Publicar torna o Flow enviável — e é irreversível do lado da Meta. Um Flow publicado nunca mais pode ser editado.
4
Clonar para fazer uma nova versão
Como publicar é definitivo, a forma de mudar um Flow no ar é clonar. O clone é um Flow novo, com id novo, e o Pilot Status grava a linhagem para você seguir a cadeia de uma versão à seguinte.
5
Depreciar
Aposentar um Flow não o apaga, e não apaga as respostas que já foram enviadas. Você pode nomear o Flow que o substitui, que é o que mantém a cadeia de versões legível.
Enviar um Flow
Anexe o Flow a um template usando um botão FLOW. O botão amarra porflow_id, por flow_name ou por flow_json embutido. Todo envio cunha um flow_token novo — um valor de uso único que liga aquele envio específico à resposta que chega depois.
Receber a resposta
Quando o cliente envia, a Meta manda umnfm_reply com o flow_token e o formulário preenchido como string JSON. O Pilot Status guarda e expõe em GET /v1/flows/{id}/responses, já ligado ao contato que respondeu.
As respostas ficam guardadas por uma janela de retenção e são podadas depois. A janela é aplicada na leitura, então uma resposta vencida nunca é servida — mesmo que o podador ainda não tenha chegado nela.
data_exchange: o Pilot Status cuida da criptografia
Essa é a parte que costuma impedir os times de colocar um Flow interativo no ar.
A Meta cifra cada chamada ao endpoint: um payload AES-GCM cuja chave chega embrulhada em RSA-2048/OAEP-SHA-256 sob a sua chave pública, e a resposta tem de voltar cifrada com a mesma chave AES sob um IV invertido bit a bit. Errar qualquer detalhe disso produz um Flow que simplesmente não avança, sem erro nenhum dos dois lados.
Então o endpoint é o Pilot Status. A gente guarda a chave, decifra a requisição da Meta e repassa JSON puro por HTTPS para um webhook seu. A sua resposta é cifrada na volta. Você nunca implementa RSA, AES-GCM nem o IV invertido.
data_exchange ainda não é self-service. Tudo descrito abaixo está construído e funcionando, mas os três passos de configuração ainda não têm endpoint público nem tela no painel — fale com o suporte para configurar um número. Flows NAVIGATE não precisam de nada disso e são self-service hoje.1
Registrar uma chave para o número
O Pilot Status gera um par RSA-2048, guarda a metade privada cifrada e registra a pública na Meta para aquele número. Você recebe de volta a URL do endpoint.
2
Apontar o Flow para ela
Registre essa URL como o endpoint do Flow. Ela tem dois segmentos — um identificando o número, outro identificando o Flow — porque a requisição da Meta não diz a qual Flow ela pertence.
3
Configurar a URL do seu webhook no Flow
É para onde repassamos o JSON decifrado. Fica configurado por Flow, porque um número serve vários formulários e cada um costuma ser um serviço diferente do seu lado.
O que o seu webhook recebe
action é INIT quando o formulário abre, BACK quando o cliente volta, e data_exchange quando ele envia uma tela.
A requisição vai assinada com HMAC-SHA256 do corpo cru no cabeçalho x-pilot-status-signature — o mesmo cabeçalho e o mesmo esquema dos webhooks de saída do Pilot Status, então quem já valida aqueles não precisa de um segundo caminho.
O que o seu webhook precisa devolver
JSON puro, nomeando a próxima tela e os dados dela:SUCCESS:
Responda em poucos segundos. A Meta segura a requisição aberta enquanto uma pessoa olha para um spinner, e não há retentativa — resposta lenta é tela falhada. Faça o trabalho demorado depois de responder, não antes.
Quando o seu webhook falha
Se o seu servidor está fora, estoura o tempo ou responde algo inutilizável, o Pilot Status não repassa a falha como tela quebrada. O cliente vê um erro genérico na tela em que já está, e pode tentar de novo — nada do que ele digitou se perde, e nada sobre a sua infraestrutura é mostrado a ele.Saúde e estado
Cada Flow carrega um estado (DRAFT, PUBLISHED, DEPRECATED, BLOCKED, THROTTLED), a versão do Flow JSON que a Meta compilou, e um veredito de saúde.
A Meta descontinuou a Flows Metrics API em 30/04/2026, sem sucessor. O webhook
flows passou a ser o único canal que reporta um Flow sendo limitado ou uma chave pública vencendo — o Pilot Status assina esse webhook e grava o que ele diz no Flow, para o sinal sobreviver à janela dos logs.