Follow-ups
Agende mensagens de acompanhamento automáticas em conversas. Configure templates reutilizáveis, automações baseadas em triggers e regras de follow-up por estágio do pipeline.
Escopos de Follow-up
Follow-ups podem ser criados por conversa (scoped) ou gerenciados globalmente na conta. Templates e automações permitem escalar o processo de acompanhamento.
Follow-ups da Conversa
/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-upsLista follow-ups de uma conversa. Administradores veem todos; os demais usuários veem apenas os follow-ups que criaram. O conversation_id da URL é o display_id da conversa.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/conversations/42/follow-ups" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"payload": [
{
"id": 1,
"message": "Ola! Gostaria de saber se teve chance de avaliar nossa proposta.",
"content": "Ola! Gostaria de saber se teve chance de avaliar nossa proposta.",
"scheduled_at": 1771596000,
"title": null,
"inbox_id": 1,
"conversation_id": 42,
"created_at": 1771212000,
"status": "pending"
}
]
}Campos do follow-up
message e content trazem o mesmo texto (content é o nome usado na escrita). Datas vêm em epoch (segundos) e conversation_id é o display_id. Quando o envio falhou, o objeto ganha error_message com o motivo.whatsapp_template_name traz o nome do template aprovado do WhatsApp quando o follow-up sai como template (null para mensagem comum). Ao editar um follow-up assim, reenviar o mesmo content só troca data e título; um contentdiferente sem template_params transforma em mensagem comum. Este é o mesmo objeto devolvido por detalhe, criação, edição, cancelamento e reenvio.
/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-ups/countRetorna a contagem total de follow-ups da conversa.
{ "count": 3 }/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-upsAgenda um novo follow-up para a conversa. Body envolto em follow_up.
Body envolto em follow_up
Os campos devem estar dentro do wrapper follow_up. O conversation_idna URL é o display_id da conversa (per-account, não ID global); ele é resolvido dentro da conta autenticada e a conversa é ligada automaticamente — não envie conversation_id no corpo.
Body (follow_up)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
content | string | Sim | Conteúdo da mensagem de follow-up. message é aceito como sinônimo (content ganha se os dois vierem) |
scheduled_at | string | integer | Sim | Data/hora de envio: ISO 8601 (sem offset é interpretado no fuso da conta; com offset ou Z, o instante é absoluto) ou epoch em segundos (13 dígitos são lidos como milissegundos). Valor ilegível retorna 422. Na criação deve ser no futuro — uma data no passado retorna 422 ("must be in the future"). |
inbox_id | integer | Nao | ID do inbox para envio (opcional — pode ficar nulo). Se informado, deve pertencer ao mesmo inbox da conversa, senão retorna 422. |
title | string | Nao | Título do follow-up |
follow_up_template_id | integer | Nao | ID do template a usar (da mesma conta) |
template_params | object | Nao | Template aprovado do WhatsApp escolhido para uma caixa oficial (nome, idioma, namespace e parâmetros processados) |
Resposta e erros
Sucesso responde 201 com o objeto do follow-up. Falha de validação responde 422 com { "error": "..." }. Um corpo sem nenhum campo editável também responde 422, nomeando os campos ignorados. O status nasce pending e não pode ser enviado.
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/conversations/42/follow-ups" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"follow_up": {
"content": "Ola! Vi que ainda não respondeu. Posso ajudar?",
"scheduled_at": "2026-02-20T10:00:00Z",
"inbox_id": 1
}
}'/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-ups/{id}Retorna detalhes de um follow-up. Permitido ao administrador ou a quem criou o follow-up.
/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-ups/{id}Atualiza um follow-up pendente (administrador ou quem o criou). Aceita os campos da criação dentro de follow_up; status não é editável. Follow-up que não está pending responde 422 com { error, status } nomeando o status atual — para reativar um follow-up falho use retry_send. Reescrever content sem template_params remove o template do WhatsApp que o follow-up carregava. PUT é aceito como alias.
/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-ups/{id}Remove um follow-up pendente. Responde 200 sem corpo; follow-up que não está pending responde 422.
/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-ups/{id}/cancelCancela um follow-up pendente sem removê-lo do histórico e responde 200 com o follow-up. Follow-up que não está pending responde 422.
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/conversations/42/follow-ups/1/cancel" \
-H "api_access_token: YOUR_TOKEN"/api/v1/accounts/{account_id}/conversations/{conversation_id}/follow-ups/{id}/retry_sendReenvia um follow-up que falhou.
Apenas Follow-ups Falhados
Só é possível reenviar follow-ups com status "failed"; os demais respondem 422. Cada follow-up aceita no máximo 5 reenvios manuais — acima disso a resposta é 422. Um follow-up de sequência que já entregou parte dos itens retoma do primeiro item não entregue; os demais são reagendados para cerca de um minuto depois e voltam a pending.
Follow-ups da Conta
/api/v1/accounts/{account_id}/follow-upsLista os follow-ups de toda a conta (todas as conversas), ordenados por data de agendamento. Aceita filtros e paginação opcional. Apenas a ação index existe nesta rota — criar/cancelar é feito na rota aninhada de conversa.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/follow-ups?status=pending&per_page=25&page=1" \
-H "api_access_token: YOUR_TOKEN" | jq .Query
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
status | string | Nao | pending, sent, failed ou cancelled |
conversation_id | integer | Nao | ID de exibição da conversa (o número mostrado no painel) |
pipeline_card_id | integer | Nao | Follow-ups ligados a este card do Pipeline |
template_id | integer | Nao | Follow-ups gerados a partir deste template |
scheduled_from | string | Nao | Início da janela de agendamento (inclusivo), ISO 8601 ou epoch em segundos |
scheduled_to | string | Nao | Fim da janela de agendamento (inclusivo), ISO 8601 ou epoch em segundos |
page | integer | Nao | Página (padrão 1). Só vale junto com per_page |
per_page | integer | Nao | Itens por página, máximo 100. Sem ele, a resposta traz a lista inteira que casa com os filtros |
Paginação
Com per_page, meta traz count, current_page, per_page e total_pages, e uma página além do fim devolve payload vazio. Sem per_page, meta traz só count. Data ilegível em scheduled_from/scheduled_to retorna 422.
{
"meta": { "count": 1, "current_page": 1, "per_page": 25, "total_pages": 1 },
"payload": [
{
"id": 1,
"message": "Ola! Posso ajudar?",
"scheduled_at": 1771596000,
"title": null,
"inbox_id": 1,
"inbox_name": "WhatsApp Business",
"conversation_id": 42,
"status": "pending",
"user_id": 5,
"user_name": "Joao Silva",
"created_at": 1771212000
}
]
}Buscar Follow-ups
/api/v1/accounts/{account_id}/search/follow_upsBusca global de follow-ups por título e conteúdo. O escopo respeita o chamador: administradores veem todos, agentes veem apenas os próprios. Parâmetros q (opcional — sem ele lista todos) e page (opcional).
curl -s "https://chat.seudominio.com/api/v1/accounts/1/search/follow_ups?q=lembrete" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"payload": {
"follow_ups": [
{
"id": 12,
"title": "Lembrete de proposta",
"content": "Ola! Seguindo sobre a proposta...",
"status": "pending",
"source": "manual",
"scheduled_at": 1771596000,
"conversation_id": 42,
"contact": { "id": 7, "name": "Maria" }
}
]
}
}conversation_id é o ID interno, não o display_id
O campo conversation_id retornado por esta busca é o ID interno da conversa (as listagens de follow-up, ao contrário, devolvem o display_id), não o display_id por conta que as rotas de conversa usam no caminho da URL. Para abrir a conversa via API, use o display_id obtido na API de Conversas.
Importar via CSV
/api/v1/accounts/{account_id}/follow-ups/importImporta follow-ups em massa a partir de um CSV (multipart/form-data, campo import_file). Cria um job assíncrono; cada linha agenda um follow-up na conversa correspondente. Requer admin ou a permissão de função personalizada follow_up_manage. Colunas: conversation_id (display_id), content, scheduled_at (ISO8601) e title (opcional).
curl -s -X POST "https://chat.seudominio.com/api/v1/accounts/1/follow-ups/import" \
-H "api_access_token: YOUR_TOKEN" \
-F "import_file=@follow_ups.csv"{ "success": true }{ "error": "Failed to upload the import file" }Templates de Follow-up
Templates reutilizáveis com variáveis dinâmicas para padronizar mensagens de acompanhamento.
/api/v1/accounts/{account_id}/follow-up-templatesLista todos os templates ativos da conta, em ordem alfabética de nome. Qualquer usuário da conta pode listar.
{
"payload": [
{
"id": 3,
"name": "Acompanhamento pos-proposta",
"content": "Template de acompanhamento",
"variables": ["contact_name"],
"active": true,
"items_count": 2,
"uses_items": true,
"has_attachments": false,
"attachments": [],
"user_id": 5,
"user_name": "Joao Silva",
"created_at": 1767225600,
"updated_at": 1767225600
}
]
}Itens não vêm na listagem
A listagem traz apenas items_count. Para obter os itens individuais (mensagens) de um template, use GET /follow-up-templates/{template_id}/items.
/api/v1/accounts/{account_id}/follow-up-templates/variablesLista variáveis disponíveis para uso nos templates (nomes planos, não aninhados).
{
"variables": [
{ "name": "contact_name", "placeholder": "{{contact_name}}", "description": "Nome do contato" },
{ "name": "contact_phone", "placeholder": "{{contact_phone}}", "description": "Telefone do contato" },
{ "name": "contact_email", "placeholder": "{{contact_email}}", "description": "E-mail do contato" },
{ "name": "conversation_id", "placeholder": "{{conversation_id}}", "description": "ID da conversa" },
{ "name": "inbox_name", "placeholder": "{{inbox_name}}", "description": "Nome do canal (inbox)" },
{ "name": "agent_name", "placeholder": "{{agent_name}}", "description": "Nome do agente responsável" },
{ "name": "card_title", "placeholder": "{{card_title}}", "description": "Título do card no pipeline" },
{ "name": "card_value", "placeholder": "{{card_value}}", "description": "Valor do card no pipeline" },
{ "name": "stage_name", "placeholder": "{{stage_name}}", "description": "Nome do estágio atual" },
{ "name": "pipeline_name", "placeholder": "{{pipeline_name}}", "description": "Nome do pipeline" },
{ "name": "current_date", "placeholder": "{{current_date}}", "description": "Data atual (DD/MM/YYYY)" },
{ "name": "current_time", "placeholder": "{{current_time}}", "description": "Hora atual (HH:MM)" }
]
}/api/v1/accounts/{account_id}/follow-up-templates/{id}Retorna um template ativo, no mesmo formato de cada item da listagem (sem wrapper). Qualquer usuário da conta pode ler.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/follow-up-templates/3" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"id": 3,
"name": "Acompanhamento pos-proposta",
"content": "Ola {{contact_name}}, tudo certo?",
"variables": ["contact_name"],
"active": true,
"created_at": 1767225600,
"updated_at": 1767225600,
"user_id": 5,
"user_name": "Joao Silva",
"attachments": [
{
"id": 88,
"filename": "proposta.pdf",
"content_type": "application/pdf",
"byte_size": 204800,
"url": "/rails/active_storage/blobs/redirect/.../proposta.pdf"
}
],
"has_attachments": true,
"items_count": 2,
"uses_items": true
}Template removido responde 404
A remoção de template é lógica (active: false). Um template removido não aparece na listagem, e detalhe, edição, pré-visualização, remoção de anexo e as rotas de itens respondem 404 para ele.
/api/v1/accounts/{account_id}/follow-up-templatesCria um novo template.
Body (follow_up_template)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
name | string | Sim | Nome do template (único por conta) |
content | string | Nao | Conteúdo de mensagem única (suporta variáveis como {{contact_name}}). Opcional: templates com itens usam o conteúdo de cada item |
active | boolean | Nao | Se o template está ativo (padrão: true) |
attachments[] | file[] | Nao | Anexos do template (multipart/form-data). Enviado FORA do wrapper follow_up_template, como campo top-level attachments[]. Aceito também no PATCH. |
Permissão, resposta e erros
Criar, editar e remover templates (e anexos) exige administrador ou a permissão de função personalizada follow_up_manage; sem ela a resposta é 401. Sucesso responde 201 com o objeto do template; validação falha em 422 com { "errors": ["..."] }.
/api/v1/accounts/{account_id}/follow-up-templates/{id}Atualiza um template (mesmos campos e permissão da criação). Novos attachments[] são acrescentados aos existentes. Responde 200 com o template. PUT é aceito como alias.
/api/v1/accounts/{account_id}/follow-up-templates/{id}Remove um template (soft delete: passa a active=false). Responde 204 sem corpo.
/api/v1/accounts/{account_id}/follow-up-templates/{id}/attachments/{attachment_id}Remove um anexo do template. O attachment_id é o id de um item de attachments no objeto do template. Responde 200 com o template atualizado; anexo que não pertence ao template responde 404 com { error: 'Attachment not found' }.
curl -X DELETE "https://chat.seudominio.com/api/v1/accounts/1/follow-up-templates/3/attachments/88" \
-H "api_access_token: YOUR_TOKEN"Itens do Template
Todas as rotas de itens exigem permissão de gestão
Inclusive a leitura: listar e detalhar itens exigem administrador ou a permissão follow_up_manage, como a edição do template. Sem ela a resposta é 401. Em template removido, as rotas respondem 404.
/api/v1/accounts/{account_id}/follow-up-templates/{template_id}/itemsLista os itens (mensagens) do template, na ordem de envio (position crescente).
curl -s "https://chat.seudominio.com/api/v1/accounts/1/follow-up-templates/3/items" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"payload": [
{
"id": 1,
"position": 0,
"delay_seconds": 0,
"item_type": "text",
"content": "Ola {{contact_name}}! Tudo certo com a proposta?",
"whatsapp_template_name": null,
"whatsapp_template_language": null,
"whatsapp_template_namespace": null,
"whatsapp_template_mapping": {},
"attachment": null,
"created_at": 1767225600,
"updated_at": 1767225600
},
{
"id": 2,
"position": 1,
"delay_seconds": 86400,
"item_type": "document",
"content": null,
"whatsapp_template_name": null,
"whatsapp_template_language": null,
"whatsapp_template_namespace": null,
"whatsapp_template_mapping": {},
"attachment": {
"id": 90,
"filename": "catalogo.pdf",
"content_type": "application/pdf",
"byte_size": 512000,
"url": "/rails/active_storage/blobs/redirect/.../catalogo.pdf"
},
"created_at": 1767225600,
"updated_at": 1767225600
}
]
}/api/v1/accounts/{account_id}/follow-up-templates/{template_id}/items/{item_id}Retorna um item do template, no mesmo formato de cada elemento da listagem (sem wrapper). Item de outro template responde 404.
/api/v1/accounts/{account_id}/follow-up-templates/{template_id}/itemsAdiciona um item (mensagem) ao template. Body envolto em follow_up_template_item.
Body (follow_up_template_item)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
content | string | Nao | Conteúdo da mensagem (suporta variáveis como {{contact_name}}). Obrigatório para item_type text e whatsapp_template; neste último é o texto alternativo (fallback) usado fora do canal oficial. |
item_type | string | Sim | Tipo do item: text, image, audio, video, document, whatsapp_template |
position | integer | Nao | Posição do item na sequência (0, 1, 2...). Se omitida ou 0, é anexado ao final. |
delay_seconds | integer | Nao | Delay em segundos após o item anterior (padrão: 0; máximo 86400 = 24h) |
attachment | file | Nao | Anexo de mídia do item (multipart/form-data). Enviado FORA do wrapper follow_up_template_item, como campo top-level attachment. Aceito também no PATCH. |
whatsapp_template_name | string | Nao | Obrigatório quando item_type=whatsapp_template. Nome do template aprovado pela Meta. |
whatsapp_template_language | string | Nao | Idioma do template aprovado (ex: pt_BR). |
whatsapp_template_namespace | string | Nao | Namespace do template (apenas 360Dialog). |
whatsapp_template_mapping | object | Nao | Mapeamento dos parâmetros do template. Formato: { "body": [ { "type": "variable"|"text", "value": "contact_name" } ], "header": { "media_url": "https://cdn.exemplo.com/arquivo.pdf", "media_type": "document", "media_name": "arquivo.pdf" } }. O "header" é obrigatório quando o template aprovado tem cabeçalho de mídia (DOCUMENT/IMAGE/VIDEO): a Meta rejeita o envio sem esse parâmetro. Dentro dele, "media_url" e "media_type" (document, image ou video) são obrigatórios juntos — sem um deles a criação responde 422. A URL precisa ser pública e ter no máximo 2000 caracteres, porque o WhatsApp busca o arquivo no momento do envio. Em inbox WhatsApp oficial fora da janela de 24h envia o template; em WAHA/UazAPI ou dentro da janela envia o content (texto, sem o anexo). |
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/follow-up-templates/3/items" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"follow_up_template_item": {
"item_type": "text",
"content": "Ola {{contact_name}}! Tudo certo com a proposta?",
"delay_seconds": 86400
}
}'Resposta e erros
Sucesso responde 201 com o item. Validação falha em 422 com { "errors": ["..."] }.
/api/v1/accounts/{account_id}/follow-up-templates/{template_id}/items/{item_id}Atualiza um item do template (mesmos campos da criação, dentro de follow_up_template_item). Responde 200 com o item. PUT é aceito como alias.
/api/v1/accounts/{account_id}/follow-up-templates/{template_id}/items/{item_id}Remove um item do template. Responde 204 sem corpo.
/api/v1/accounts/{account_id}/follow-up-templates/{template_id}/items/reorderReordena itens do template.
Body
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
items | array | Sim | Array de objetos { id, delay_seconds } na nova ordem. A posição de cada item é definida pelo índice no array. delay_seconds é opcional: omitido, o atraso atual do item é mantido. Sem o array, a resposta é 400; id de item que não pertence ao template, 404. Sucesso responde 200 com { payload } na nova ordem. |
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/follow-up-templates/3/items/reorder" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": 2, "delay_seconds": 0 },
{ "id": 1, "delay_seconds": 86400 }
]
}'/api/v1/accounts/{account_id}/follow-up-templates/{id}/previewPré-visualiza o template com variáveis substituídas.
Body
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
context | object | Nao | Objeto com pares variável: valor para substituir (ex: { "contact_name": "Maria" }). Apenas variáveis suportadas são usadas. Se omitido, retorna o conteúdo com os placeholders preservados. |
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/follow-up-templates/3/preview" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "context": { "contact_name": "Maria", "agent_name": "Joao" } }'{
"original": "Ola {{contact_name}}, tudo certo?",
"rendered": "Ola Maria, tudo certo?",
"sample": "Ola [Nome do contato], tudo certo?"
}Automações de Follow-up
Configure triggers automáticos para iniciar sequências de follow-up baseados em eventos.
/api/v1/accounts/{account_id}/follow-up-automationsLista as automações de follow-up da conta, da mais recente para a mais antiga (chave payload). Qualquer usuário da conta pode listar.
/api/v1/accounts/{account_id}/follow-up-automations/{id}Retorna uma automação, no mesmo formato de cada item da listagem (sem wrapper). Qualquer usuário da conta pode ler; automação de outra conta responde 404.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/follow-up-automations/7" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"id": 7,
"name": "Follow-up pos-resolucao",
"trigger_type": "conversation_resolved",
"trigger_description": "When a conversation is resolved",
"trigger_config": {},
"content_mode": "template",
"ai_instruction": null,
"follow_up_template_id": 3,
"follow_up_template_name": "Acompanhamento pos-proposta",
"delay_minutes": 0,
"delay_description": "Immediately",
"send_window": { "enabled": true, "days": [1, 2, 3, 4, 5], "start": "08:00", "end": "18:00" },
"conditions": {},
"enabled": true,
"executions_count": 14,
"last_executed_at": 1771596000,
"created_at": 1767225600,
"updated_at": 1767225600,
"user_id": 5,
"user_name": "Joao Silva"
}/api/v1/accounts/{account_id}/follow-up-automationsCria uma automação de follow-up.
Body (follow_up_automation)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
name | string | Sim | Nome da automação (único por conta) |
content_mode | string | Nao | Origem da mensagem: 'template' (padrão) usa um follow_up_template; 'ai' gera a mensagem por IA no envio. |
follow_up_template_id | integer | Nao | ID do template a executar. Obrigatório quando content_mode='template'. |
ai_instruction | string | Nao | Instrução/objetivo do follow-up. Obrigatório quando content_mode='ai'; a IA escreve a mensagem usando esta instrução + o histórico da conversa. |
trigger_type | string | Sim | Tipo de gatilho: label_added, label_removed, contact_created, conversation_created, conversation_resolved, conversation_inactivity |
enabled | boolean | Nao | Se a automação está ativa (padrão: true) |
delay_minutes | integer | Nao | Delay em minutos antes de executar (padrão: 0). Ignorado para conversation_inactivity. |
trigger_config | object | Nao | Configuração específica do gatilho. label_added/label_removed: { label_id }. conversation_inactivity: { inactivity_minutes } (silêncio do cliente desde a última mensagem recebida). |
conditions | object | Nao | Condições adicionais para filtrar quando a automação dispara |
send_window | object | Nao | Janela de horário de envio. Quando habilitada, follow-ups que cairiam fora do intervalo são adiados para a próxima abertura (no fuso da conta). Formato: { "enabled": true, "days": [1,2,3,4,5], "start": "08:00", "end": "18:00" }. days usa 0=domingo..6=sábado; end deve ser maior que start. |
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/follow-up-automations" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"follow_up_automation": {
"name": "Follow-up pos-resolucao",
"follow_up_template_id": 3,
"trigger_type": "conversation_resolved",
"enabled": true,
"send_window": {
"enabled": true,
"days": [1, 2, 3, 4, 5],
"start": "08:00",
"end": "18:00"
}
}
}'Exemplo: disparar por inatividade do cliente (1h sem responder após a última mensagem recebida) com mensagem gerada por IA.
curl -X POST "https://chat.seudominio.com/api/v1/accounts/1/follow-up-automations" \
-H "api_access_token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"follow_up_automation": {
"name": "Reengajar inativos (IA)",
"trigger_type": "conversation_inactivity",
"trigger_config": { "inactivity_minutes": 60 },
"content_mode": "ai",
"ai_instruction": "Reengaje o cliente cordialmente e ofereca ajuda para avancar a negociacao.",
"enabled": true
}
}'Permissão, resposta e erros
Criar, editar e remover automações exige administrador ou a permissão follow_up_manage; sem ela a resposta é 401. Sucesso responde 201 com o objeto da automação; validação falha em 422 com { "errors": ["..."] }.
/api/v1/accounts/{account_id}/follow-up-automations/{id}Atualiza uma automação (mesmos campos e permissão da criação, dentro de follow_up_automation). Responde 200 com a automação. PUT é aceito como alias.
/api/v1/accounts/{account_id}/follow-up-automations/{id}Remove uma automação. Responde 204 sem corpo.
Regras de Follow-up por Pipeline
Configure follow-ups automáticos baseados na movimentação de cards entre estágios do pipeline.
Acesso
Estas rotas pertencem ao módulo Pipeline Pro (conta sem o módulo responde 403 com "code": "pipeline_board_disabled"). Pipeline de outra conta ou inexistente responde 404; agente que não é membro do pipeline recebe 403. Para Agent Bot, um pipeline fora do seu escopo (lista agent_bots do pipeline preenchida sem o bot) também responde 404 em todas estas rotas — ler, criar, editar e remover; lista vazia deixa o pipeline aberto a todo bot. Administradores e agentes leem as regras; criar e editar exige administrador, a permissão follow_up_manage ou a permissão pipeline_manage; remover exige administrador ou follow_up_manage. Sem a permissão de escrita a resposta é 401.
/api/v1/accounts/{account_id}/pipelines/{pipeline_id}/follow-up-rulesLista as regras de follow-up do pipeline, ordenadas por to_stage (chave payload).
/api/v1/accounts/{account_id}/pipelines/{pipeline_id}/follow-up-rules/{id}Retorna uma regra do pipeline, no mesmo formato de cada item da listagem (sem wrapper). Regra de outro pipeline responde 404.
curl -s "https://chat.seudominio.com/api/v1/accounts/1/pipelines/9/follow-up-rules/4" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"id": 4,
"pipeline_id": 9,
"follow_up_template_id": 3,
"follow_up_template_name": "Acompanhamento pos-proposta",
"sender_id": 5,
"sender_name": "Joao Silva",
"sender_agent_bot_id": null,
"sender_agent_bot_name": null,
"content_mode": "template",
"ai_instruction": null,
"from_stage": null,
"to_stage": "proposta",
"delay_minutes": 1440,
"delay_description": "1 day",
"send_window": { "enabled": true, "days": [1, 2, 3, 4, 5], "start": "08:00", "end": "18:00" },
"enabled": true,
"conditions": {},
"created_at": 1767225600,
"updated_at": 1767225600
}/api/v1/accounts/{account_id}/pipelines/{pipeline_id}/follow-up-rulesCria uma regra de follow-up para o pipeline. Responde 201 com a regra; validação falha em 422 com { errors: [...] }.
Body (pipeline_follow_up_rule)
| Nome | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
to_stage | string | Sim | ID do estágio destino que aciona a regra (ex: "755_entrada_de_lead"). Precisa existir no pipeline |
content_mode | string | Nao | 'template' (padrão) envia um follow_up_template; 'ai' faz a NooviAI redigir a mensagem a partir de ai_instruction e do histórico da conversa |
follow_up_template_id | integer | Nao | ID do template a executar (da mesma conta). Obrigatório na criação quando content_mode='template' |
ai_instruction | string | Nao | Instrução para a IA. Obrigatória quando content_mode='ai' (máximo 4096 caracteres) |
from_stage | string | Nao | ID do estágio de origem (opcional, filtra apenas cards vindos deste estágio) |
delay_minutes | integer | Nao | Delay em minutos após entrar no estágio (padrão: 0) |
enabled | boolean | Nao | Se a regra está ativa (padrão: true) |
sender_id | integer | Nao | Agente da conta que assina a mensagem. Sem remetente, a autoria segue o responsável do card, depois o responsável da conversa e, por fim, um administrador |
sender_agent_bot_id | integer | Nao | Agent bot que assina a mensagem, no lugar de um humano. Não pode ser enviado junto com sender_id (422) |
conditions | object | Nao | Condições adicionais da regra |
send_window | object | Nao | Janela de horário de envio. Quando habilitada, follow-ups (incluindo itens de sequência) que cairiam fora do intervalo são adiados para a próxima abertura, no fuso da conta. Formato: { "enabled": true, "days": [1,2,3,4,5], "start": "08:00", "end": "18:00" }. days usa 0=domingo..6=sábado; end deve ser maior que start. |
/api/v1/accounts/{account_id}/pipelines/{pipeline_id}/follow-up-rules/{id}Atualiza uma regra (mesmos campos da criação, dentro de pipeline_follow_up_rule). Responde 200 com a regra; validação falha em 422 com { errors: [...] }. PUT é aceito como alias.
/api/v1/accounts/{account_id}/pipelines/{pipeline_id}/follow-up-rules/{id}Remove uma regra. Responde 204 sem corpo.
Relatórios de Follow-ups
Métricas agregadas de follow-ups (taxas de envio, sucesso, falha e cancelamento, além de quebras por status, origem, usuário e template). Disponível na API v2. Requer permissão de visualização de relatórios.
Filtros (query) — comuns a todos os endpoints
Todos os endpoints abaixo aceitam os mesmos filtros opcionais via query string:
sinceeuntil— intervalo de tempo em epoch (segundos Unix). Filtram porscheduled_at. Devem ser enviados juntos.status—pending|sent|failed|cancelledsource—pipeline|automation| (nulo = manual)user_id— filtra por agente responsáveltemplate_id— filtra por template usado
/api/v2/accounts/{account_id}/reports/follow-upsRelatório completo: métricas, quebras por status/origem/usuário/template e série temporal.
curl -s "https://chat.seudominio.com/api/v2/accounts/1/reports/follow-ups?since=1769904000&until=1772323200" \
-H "api_access_token: YOUR_TOKEN" | jq .{
"metrics": {
"total": 120,
"sent": 98,
"pending": 10,
"failed": 7,
"cancelled": 5,
"success_rate": 81.7,
"cancellation_rate": 4.2,
"failure_rate": 5.8,
"from_pipeline": 60,
"from_automation": 30,
"manual": 30,
"unique_conversations": 85,
"avg_per_conversation": 1.4
},
"by_status": { "sent": 98, "pending": 10, "failed": 7, "cancelled": 5 },
"by_source": { "pipeline": 60, "automation": 30, "manual": 30 },
"by_user": [
{ "user_id": 5, "user_name": "Joao Silva", "count": 40, "sent": 35, "success_rate": 87.5 }
],
"by_template": [
{ "template_id": 3, "template_name": "Lembrete 24h", "count": 22, "sent": 20, "success_rate": 90.9 }
],
"timeseries": {
"labels": ["2026-02-01", "2026-02-02"],
"sent": [12, 8],
"scheduled": [15, 10],
"failed": [1, 0]
}
}/api/v2/accounts/{account_id}/reports/follow-ups/summaryApenas o bloco de métricas agregadas (mesmo objeto metrics do relatório completo).
/api/v2/accounts/{account_id}/reports/follow-ups/by_userQuebra por usuário: { data: [...] } com count, sent e success_rate por agente, ordenado por volume.
/api/v2/accounts/{account_id}/reports/follow-ups/by_templateQuebra por template: { data: [...] } com count, sent e success_rate por template, ordenado por volume.
/api/v2/accounts/{account_id}/reports/follow-ups/exportExporta os follow-ups filtrados. Aceita os mesmos filtros de query. Retorna CSV (Accept: text/csv) ou JSON ({ data: [...] }, timestamps em epoch).
# CSV
curl -s "https://chat.seudominio.com/api/v2/accounts/1/reports/follow-ups/export.csv?since=1769904000&until=1772323200" \
-H "api_access_token: YOUR_TOKEN" -o follow_ups_report.csv
# JSON
curl -s "https://chat.seudominio.com/api/v2/accounts/1/reports/follow-ups/export.json" \
-H "api_access_token: YOUR_TOKEN" | jq .