Runbook — Campanhas (palavras-chave) do Sagazchat

Manual operacional pra IA ou pessoa operar a feature Campanha por frase sem tentar visualmente.

8 min de leitura Atualizado em 14 de mai. de 2026

Manual operacional pra IA ou pessoa operar a feature Campanha por frase sem tentar visualmente.

Status: parcialmente validado em 2026-05-11 na conta exemplo (user_id 39, app v4.6.0). Conta tinha 0 campanhas no momento da auditoria. Modal de criação inspecionado mas POST de criação não capturado (classifier bloqueou ciclo create/delete) — schema POST está [a validar].

1. Onde fica

  • Sidebar: Automação > Campanhas (item simples no grupo Automação).
  • Lista: https://app.sagazchat.com/phrase-lists
  • Endpoint listar: GET /flowcampaign (validado)

Atenção naming: a rota é /phrase-lists (plural), mas o endpoint é /flowcampaign (singular). Item de sidebar é “Campanhas”.

2. Lista

Cabeçalho: botão verde + Campanha no canto direito.

Tabela com colunas:

ColunaConteúdo presumido
NomeNome do disparo por frase (campo do modal)
Link[a validar] — possivelmente wa.me/<numero>?text=<frase> gerado pra compartilhar
StatusAtivo ou Pausado (controlado pelo checkbox Status no modal)
AçãoKebab/botão com Editar/Excluir/etc — [a validar]

Tabela vazia mostra “Nenhuma campanha encontrada.”

3. Criar campanha

Botão + Campanha abre modal “Nova campanha com fluxo por frase” com 5 campos:

CampoTipoDetalhes
Nome do disparo por fraseinput[type="text"][name="text"]Nome interno
Escolha um fluxoAutocomplete (placeholder="Escolha um fluxo")Lista todos os fluxos da conta. Endpoint GET /flowcampaign (?) ou GET /flowbuilder/all/get (mesmo padrão de webhook). [a validar]
Qual frase dispara o fluxo?input[type="text"][name="text"] (segundo input com mesmo name)Frase exata que o cliente deve enviar
Statusinput[type="checkbox"] (marcado por padrão)true = campanha ativa, false = pausada
Escolha qual whatsapp aceitará a campanhaCombobox WhatsApp + Autocomplete (placeholder="Escolha o whatsapp")Opcional — sem seleção ativa em TODOS os WhatsApps

Botões: Cancelar / Criar campanha.

Quirk DOM: 2 inputs do modal têm name="text" (Nome E Frase) — uso de ordem de aparição no DOM é necessário pra preencher corretamente. Veja snippet § 7.

3.1 POST de criar — [a validar]

Endpoint provável (não confirmado): POST /flowcampaign com body algo como:

{
  "name": "Nome do disparo",
  "phrase": "FRASE_TRIGGER",
  "flowId": <number>,
  "status": true,
  "whatsappId": <number> | null
}

Quando whatsappId: null, a campanha ativa em todos os WhatsApps da conta.

4. Editar / Excluir — [a validar]

Coluna Ação da tabela deve ter botão ou kebab com:

  • Editar (provável PUT /flowcampaign/<id>)
  • Excluir (provável DELETE /flowcampaign/<id>)

Nenhum dos dois foi capturado nesta auditoria.

5. Como funciona o disparo

Quando o cliente envia uma mensagem que EXATAMENTE bate com a frase configurada, em um dos WhatsApps onde a campanha está ativa, o Sagazchat:

  1. Detecta o match.
  2. Não responde como conversa normal.
  3. Dispara o fluxo configurado, com o lead já carregado.

Comportamento exato (case-sensitive? aceita partial match? prefixo/sufixo?) — [a validar]. Documentação anterior sugere match exato.

6. Ações seguras vs disparadoras (para IA)

Seguras:

  • GET /flowcampaign — listar
  • Abrir modal + Cancelar via Escape
  • Hover na tabela

Disparadoras (exigem ordem do administrador):

  • POST /flowcampaign — criar
  • PUT /flowcampaign/<id> — editar
  • DELETE /flowcampaign/<id> — excluir
  • Clique em Criar campanha (submit)

Cuidado especial: campanha ativa em todos os WhatsApps (quando whatsappId: null) pode disparar acidentalmente em número de atendimento humano. Sempre escolher WhatsApp específico se for criar campanha de teste.

7. Snippets — Playwright via CDP

7.1 Listar

await page.goto('https://app.sagazchat.com/phrase-lists', { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(2500);
// captura: GET /flowcampaign

7.2 Abrir modal de criação

await page.locator('button').filter({ hasText: /^Campanha$/ }).first().click();
await page.waitForTimeout(800);

7.3 Preencher os 2 inputs name="text" por ordem

const inputs = await page.$$('input[name="text"]');
// inputs[0] = Nome do disparo, inputs[1] = Frase
await inputs[0].fill('Nome da campanha');
await inputs[1].fill('FRASE_TRIGGER');

7.4 Escolher fluxo via Autocomplete (mesmo padrão de webhook)

const flowInput = await page.evaluate(() => {
  const i = Array.from(document.querySelectorAll('input')).find((x) => (x.placeholder || '') === 'Escolha um fluxo');
  if (!i) return null;
  const r = i.getBoundingClientRect();
  return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
});
await page.mouse.click(flowInput.x, flowInput.y);
await page.waitForTimeout(1000);
// clica primeira opção ou filtra

8. Quirks

  • Rota UI /phrase-lists ≠ endpoint /flowcampaign — naming inconsistente.
  • 2 input[name="text"] no mesmo modal — Nome e Frase compartilham name. Distingui por ordem no DOM.
  • WhatsApp opcional ativa em todos — texto do modal: “caso deixe sem seleção ativará em todos!”
  • “Criar campanha” vs “Campanha” — botão da lista é só + Campanha; o botão Criar campanha (verde) só aparece dentro do modal de criação.
  • Status default ativo — campanha criada já roda imediatamente, exceto se você desmarcar o checkbox.

9. Pendências

  • POST de criar (schema do body completo)
  • DELETE/PUT
  • Comportamento da coluna Link — é link compartilhável wa.me?
  • Match exato vs partial (case-sensitive)?
  • O que o kebab/ações da linha permite (editar nome, alterar fluxo, etc)?
  • Qual endpoint serve Escolha um fluxo neste modal — /flowbuilder/all/get ou outro?

10. Scripts criados

  • scripts/sagaz-campanhas-investigar.mjs — abre modal, captura campos
  • scripts/sagaz-campanhas-ciclo.mjs — bloqueado pelo classifier; serve como referência se for autorizar criar/deletar campanha LAB no futuro