curl --request POST \
--url https://api-v2.manybot.com.br/messages/send-flow \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"channelId": "clh1234567890",
"phone": "+5511999999999",
"flowId": "123456789012345",
"body": "Toque para escolher seu horário",
"flowCta": "Agendar",
"screen": "AGENDAMENTO",
"flowData": {
"agendamentoId": "AG-1024",
"nome": "Maria"
},
"metadata": {
"agendamentoId": "AG-1024",
"clienteId": "c_789"
}
}
'import requests
url = "https://api-v2.manybot.com.br/messages/send-flow"
payload = {
"channelId": "clh1234567890",
"phone": "+5511999999999",
"flowId": "123456789012345",
"body": "Toque para escolher seu horário",
"flowCta": "Agendar",
"screen": "AGENDAMENTO",
"flowData": {
"agendamentoId": "AG-1024",
"nome": "Maria"
},
"metadata": {
"agendamentoId": "AG-1024",
"clienteId": "c_789"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
channelId: 'clh1234567890',
phone: '+5511999999999',
flowId: '123456789012345',
body: JSON.stringify('Toque para escolher seu horário'),
flowCta: 'Agendar',
screen: 'AGENDAMENTO',
flowData: {agendamentoId: 'AG-1024', nome: 'Maria'},
metadata: {agendamentoId: 'AG-1024', clienteId: 'c_789'}
})
};
fetch('https://api-v2.manybot.com.br/messages/send-flow', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-v2.manybot.com.br/messages/send-flow",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'channelId' => 'clh1234567890',
'phone' => '+5511999999999',
'flowId' => '123456789012345',
'body' => 'Toque para escolher seu horário',
'flowCta' => 'Agendar',
'screen' => 'AGENDAMENTO',
'flowData' => [
'agendamentoId' => 'AG-1024',
'nome' => 'Maria'
],
'metadata' => [
'agendamentoId' => 'AG-1024',
'clienteId' => 'c_789'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-v2.manybot.com.br/messages/send-flow"
payload := strings.NewReader("{\n \"channelId\": \"clh1234567890\",\n \"phone\": \"+5511999999999\",\n \"flowId\": \"123456789012345\",\n \"body\": \"Toque para escolher seu horário\",\n \"flowCta\": \"Agendar\",\n \"screen\": \"AGENDAMENTO\",\n \"flowData\": {\n \"agendamentoId\": \"AG-1024\",\n \"nome\": \"Maria\"\n },\n \"metadata\": {\n \"agendamentoId\": \"AG-1024\",\n \"clienteId\": \"c_789\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-v2.manybot.com.br/messages/send-flow")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"channelId\": \"clh1234567890\",\n \"phone\": \"+5511999999999\",\n \"flowId\": \"123456789012345\",\n \"body\": \"Toque para escolher seu horário\",\n \"flowCta\": \"Agendar\",\n \"screen\": \"AGENDAMENTO\",\n \"flowData\": {\n \"agendamentoId\": \"AG-1024\",\n \"nome\": \"Maria\"\n },\n \"metadata\": {\n \"agendamentoId\": \"AG-1024\",\n \"clienteId\": \"c_789\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-v2.manybot.com.br/messages/send-flow")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"channelId\": \"clh1234567890\",\n \"phone\": \"+5511999999999\",\n \"flowId\": \"123456789012345\",\n \"body\": \"Toque para escolher seu horário\",\n \"flowCta\": \"Agendar\",\n \"screen\": \"AGENDAMENTO\",\n \"flowData\": {\n \"agendamentoId\": \"AG-1024\",\n \"nome\": \"Maria\"\n },\n \"metadata\": {\n \"agendamentoId\": \"AG-1024\",\n \"clienteId\": \"c_789\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"chatId": "clh0987654321",
"externalChatId": "5511999999999@s.whatsapp.net",
"message": "Template enviado com sucesso",
"wamid": "wamid.HBgNNTUxMTk5OTk5OTk5FQIAERgSQjYxNzc2..."
}{
"success": true,
"chatId": "clh0987654321",
"externalChatId": "5511999999999@s.whatsapp.net",
"message": "Template enviado com sucesso",
"wamid": "wamid.HBgNNTUxMTk5OTk5OTk5FQIAERgSQjYxNzc2..."
}{
"statusCode": 400,
"message": "Template \"meu_template\" não está aprovado (status: REJECTED)"
}{
"statusCode": 404,
"message": "Template \"meu_template\" (pt_BR) não encontrado"
}{
"statusCode": 409,
"error": "request_in_progress"
}Send Flow
Envia um WhatsApp Flow diretamente (mensagem interativa). Para disparo proativo fora da janela de 24h, use send-template com um template que tenha botão de Flow.
curl --request POST \
--url https://api-v2.manybot.com.br/messages/send-flow \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"channelId": "clh1234567890",
"phone": "+5511999999999",
"flowId": "123456789012345",
"body": "Toque para escolher seu horário",
"flowCta": "Agendar",
"screen": "AGENDAMENTO",
"flowData": {
"agendamentoId": "AG-1024",
"nome": "Maria"
},
"metadata": {
"agendamentoId": "AG-1024",
"clienteId": "c_789"
}
}
'import requests
url = "https://api-v2.manybot.com.br/messages/send-flow"
payload = {
"channelId": "clh1234567890",
"phone": "+5511999999999",
"flowId": "123456789012345",
"body": "Toque para escolher seu horário",
"flowCta": "Agendar",
"screen": "AGENDAMENTO",
"flowData": {
"agendamentoId": "AG-1024",
"nome": "Maria"
},
"metadata": {
"agendamentoId": "AG-1024",
"clienteId": "c_789"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
channelId: 'clh1234567890',
phone: '+5511999999999',
flowId: '123456789012345',
body: JSON.stringify('Toque para escolher seu horário'),
flowCta: 'Agendar',
screen: 'AGENDAMENTO',
flowData: {agendamentoId: 'AG-1024', nome: 'Maria'},
metadata: {agendamentoId: 'AG-1024', clienteId: 'c_789'}
})
};
fetch('https://api-v2.manybot.com.br/messages/send-flow', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-v2.manybot.com.br/messages/send-flow",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'channelId' => 'clh1234567890',
'phone' => '+5511999999999',
'flowId' => '123456789012345',
'body' => 'Toque para escolher seu horário',
'flowCta' => 'Agendar',
'screen' => 'AGENDAMENTO',
'flowData' => [
'agendamentoId' => 'AG-1024',
'nome' => 'Maria'
],
'metadata' => [
'agendamentoId' => 'AG-1024',
'clienteId' => 'c_789'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-v2.manybot.com.br/messages/send-flow"
payload := strings.NewReader("{\n \"channelId\": \"clh1234567890\",\n \"phone\": \"+5511999999999\",\n \"flowId\": \"123456789012345\",\n \"body\": \"Toque para escolher seu horário\",\n \"flowCta\": \"Agendar\",\n \"screen\": \"AGENDAMENTO\",\n \"flowData\": {\n \"agendamentoId\": \"AG-1024\",\n \"nome\": \"Maria\"\n },\n \"metadata\": {\n \"agendamentoId\": \"AG-1024\",\n \"clienteId\": \"c_789\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-v2.manybot.com.br/messages/send-flow")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"channelId\": \"clh1234567890\",\n \"phone\": \"+5511999999999\",\n \"flowId\": \"123456789012345\",\n \"body\": \"Toque para escolher seu horário\",\n \"flowCta\": \"Agendar\",\n \"screen\": \"AGENDAMENTO\",\n \"flowData\": {\n \"agendamentoId\": \"AG-1024\",\n \"nome\": \"Maria\"\n },\n \"metadata\": {\n \"agendamentoId\": \"AG-1024\",\n \"clienteId\": \"c_789\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-v2.manybot.com.br/messages/send-flow")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"channelId\": \"clh1234567890\",\n \"phone\": \"+5511999999999\",\n \"flowId\": \"123456789012345\",\n \"body\": \"Toque para escolher seu horário\",\n \"flowCta\": \"Agendar\",\n \"screen\": \"AGENDAMENTO\",\n \"flowData\": {\n \"agendamentoId\": \"AG-1024\",\n \"nome\": \"Maria\"\n },\n \"metadata\": {\n \"agendamentoId\": \"AG-1024\",\n \"clienteId\": \"c_789\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"chatId": "clh0987654321",
"externalChatId": "5511999999999@s.whatsapp.net",
"message": "Template enviado com sucesso",
"wamid": "wamid.HBgNNTUxMTk5OTk5OTk5FQIAERgSQjYxNzc2..."
}{
"success": true,
"chatId": "clh0987654321",
"externalChatId": "5511999999999@s.whatsapp.net",
"message": "Template enviado com sucesso",
"wamid": "wamid.HBgNNTUxMTk5OTk5OTk5FQIAERgSQjYxNzc2..."
}{
"statusCode": 400,
"message": "Template \"meu_template\" não está aprovado (status: REJECTED)"
}{
"statusCode": 404,
"message": "Template \"meu_template\" (pt_BR) não encontrado"
}{
"statusCode": 409,
"error": "request_in_progress"
}flowData
O dataset completo do flow, enviado de uma vez. Os dados entram pela tela de entrada (a única que o WhatsApp permite pré-preencher no disparo) e, em flows multi-tela, são repassados internamente para as telas seguintes via navigate — você não divide o flowData por tela. Os valores são referenciados no flow via ${data.campo} e a Meta substitui os placeholders no momento do envio. Quando enviar flowData, informe também screen (a tela de entrada).
metadata
Metadados livres gravados na mensagem para controle/consulta posterior (ex.: { "pedidoId": "...", "clienteId": "..." }).
Idempotência (X-Request-Id)
Mesmo comportamento do Send Template: envie um UUID no header X-Request-Id para evitar envio duplicado em retries.Authorizations
Token JWT da sua conta. Use o formato: Bearer {seu-jwt-token}
Headers
Chave de idempotência gerada pelo integrador para evitar disparo duplicado da mesma mensagem em caso de retry. Gere um UUID por mensagem lógica e reenvie o mesmo valor se precisar repetir a requisição. A chave é única por canal (channelId). Se não for um UUID válido, a API responde 400 (key: "invalid_request_id"). Se omitido, não há deduplicação.
"11111111-1111-4111-8111-111111111111"
Body
Dados para enviar um WhatsApp Flow
ID do canal para envio.
"clh1234567890"
Número do destinatário (formato internacional).
"+5511999999999"
ID do WhatsApp Flow a enviar.
"123456789012345"
Texto do corpo da mensagem que acompanha o botão do flow.
"Toque para escolher seu horário"
Rótulo do botão que abre o flow (CTA). Recomendado < 30 caracteres.
"Agendar"
Tela inicial do flow. Obrigatória quando enviar flowData.
"AGENDAMENTO"
Dados iniciais para pré-preencher a 1ª tela (referenciados via ${data.campo}).
{
"agendamentoId": "AG-1024",
"nome": "Maria"
}
draft (teste) ou published (padrão).
draft, published "published"
Metadados livres gravados na mensagem (ex.: id do pedido, id do cliente).
{
"pedidoId": "PED-5521",
"clienteId": "c_789"
}
Response
Replay: uma requisição com o mesmo X-Request-Id já foi processada com sucesso neste canal. A mensagem não é reenviada e a resposta traz o mesmo resultado da primeira vez (mesmo wamid, chatId etc.).
Indica se o envio foi bem-sucedido.
true
ID interno do chat.
"clh0987654321"
ID externo do chat (número do WhatsApp).
"5511999999999@s.whatsapp.net"
Mensagem de confirmação.
"Template enviado com sucesso"
WhatsApp Message ID retornado pela Meta.
"wamid.HBgNNTUxMTk5OTk5OTk5FQIAERgSQjYxNzc2..."

