Runbook — Campanhas (palavras-chave) do Sagazchat
Manual operacional pra IA ou pessoa operar a feature Campanha por frase sem tentar visualmente.
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:
| Coluna | Conteúdo presumido |
|---|---|
| Nome | Nome do disparo por frase (campo do modal) |
| Link | [a validar] — possivelmente wa.me/<numero>?text=<frase> gerado pra compartilhar |
| Status | Ativo ou Pausado (controlado pelo checkbox Status no modal) |
| Ação | Kebab/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:
| Campo | Tipo | Detalhes |
|---|---|---|
| Nome do disparo por frase | input[type="text"][name="text"] | Nome interno |
| Escolha um fluxo | Autocomplete (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 |
| Status | input[type="checkbox"] (marcado por padrão) | true = campanha ativa, false = pausada |
| Escolha qual whatsapp aceitará a campanha | Combobox 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:
- Detecta o match.
- Não responde como conversa normal.
- 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— criarPUT /flowcampaign/<id>— editarDELETE /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 compartilhamname. 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ãoCriar 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 fluxoneste modal —/flowbuilder/all/getou outro?
10. Scripts criados
scripts/sagaz-campanhas-investigar.mjs— abre modal, captura camposscripts/sagaz-campanhas-ciclo.mjs— bloqueado pelo classifier; serve como referência se for autorizar criar/deletar campanha LAB no futuro