@lionchat/mcp-server 1.30.0 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/instructions.md +12 -2
- package/dist/docs/resources/agenda-multiplas-unidades.md +62 -2
- package/dist/docs/resources/assinatura-eletronica.md +19 -2
- package/dist/docs/resources/best-practices.md +7 -1
- package/dist/docs/resources/conversation-flows.md +12 -4
- package/dist/docs/resources/data-model.md +143 -2
- package/dist/docs/resources/filtros-e-relatorios.md +31 -2
- package/dist/docs/resources/flowbuilder-design-guide.md +99 -9
- package/dist/docs/resources/flowbuilder-patterns.md +33 -0
- package/dist/docs/resources/formularios-publicos.md +159 -2
- package/dist/docs/resources/glossary.md +23 -0
- package/dist/docs/resources/kanban-deep-dive.md +162 -8
- package/dist/docs/resources/reports-guide.md +11 -2
- package/dist/docs/resources/troubleshooting.md +20 -2
- package/dist/tools.js +88 -18
- package/dist/tools.js.map +1 -1
- package/endpoints.json +1006 -99
- package/package.json +1 -1
|
@@ -62,7 +62,7 @@ Todo node tem essa estrutura base:
|
|
|
62
62
|
|
|
63
63
|
**ATENÇÃO — chave `items`, não `triggers` (corrigido 19/08/2026).** Os gatilhos vão em **`data.items`**, cada item no formato **`{ "key": "...", "config": { ...filtros... } }`**. O formato antigo (`data.triggers` + `type` + filtros soltos no topo) ainda é aceito pelo motor por compatibilidade, mas **NÃO deve ser usado em fluxo novo**: o editor do FlowBuilder lê apenas `data.items`, então um fluxo gravado no formato antigo **dispara normalmente mas abre com o bloco Início EM BRANCO no painel do cliente** — e um clique em "Concluir" naquele modal apagava o gatilho em silêncio. Foram 53 fluxos de 9 contas nesse estado até o conserto de 19/08. Alguns leitores do backend (`has_webhook_trigger?` do disparo por webhook, o filtro de Campanha de Fluxo, o gatilho LionTrack e o histórico de execução) também só entendem `items`.
|
|
64
64
|
|
|
65
|
-
**Triggers válidos:** `message_received`, `message_sent`, `conversation_created`, `conversation_resolved`, `conversation_reopened`, `team_changed`, `assignee_changed`, `label_added`, `label_removed`, `sla_missed`, `card_created`, `card_moved`, `card_won`, `card_lost`, `conversation_attribute_changed`, `card_attribute_changed`, `contact_attribute_changed`, `date_trigger`, `campaign_trigger`, `manual_trigger`, `webhook_received`, `page_track`, `group_participant_joined`, `group_participant_left`, `lead_form_completed`, `lead_form_milestone`, `lead_form_abandoned`, `booking_created`, `booking_cancelled`, `booking_rescheduled`, `booking_completed`.
|
|
65
|
+
**Triggers válidos:** `message_received`, `message_sent`, `conversation_created`, `conversation_resolved`, `conversation_reopened`, `team_changed`, `assignee_changed`, `label_added`, `label_removed`, `sla_missed`, `card_created`, `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `conversation_attribute_changed`, `card_attribute_changed`, `contact_attribute_changed`, `date_trigger`, `campaign_trigger`, `manual_trigger`, `webhook_received`, `page_track`, `group_participant_joined`, `group_participant_left`, `lead_form_completed`, `lead_form_milestone`, `lead_form_abandoned`, `booking_created`, `booking_cancelled`, `booking_rescheduled`, `booking_completed`.
|
|
66
66
|
|
|
67
67
|
**NÃO existem** os gatilhos `webhook` (o correto é **`webhook_received`**) nem `cron` (para disparo por data use `date_trigger`; para disparo em lote use `campaign_trigger` + Campanha de Fluxo). Até 19/08/2026 este guia listava os dois por engano — o fluxo 180 da conta 54 ficou ATIVO com `webhook` e **nunca disparou uma vez em 26 dias**, sem erro nenhum.
|
|
68
68
|
|
|
@@ -74,6 +74,7 @@ Todo node tem essa estrutura base:
|
|
|
74
74
|
- `label_added` / `label_removed`: `label_names` (array de slugs). NÃO use `label` (singular) — é ignorado.
|
|
75
75
|
- `card_created` / `card_moved`: `funnel_ids` (array de STRINGS, ex.: `["37"]` — número puro `[37]` NÃO casa) + `funnel_stages` (array de `"funnel_id:chave_da_etapa"`, ex.: `"37:agendamento_pendente"`). A `chave_da_etapa` é a CHAVE INTERNA da etapa no funil (slug legível em funis de template; pode ser um UUID/`stage_<n>` em etapa criada à mão ou funil duplicado) — NÃO o nome exibido na tela. Sem `funnel_ids` → dispara em qualquer funil; com `funnel_ids` mas sem `funnel_stages` → qualquer etapa daquele(s) funil(is). O card precisa estar num funil listado em `funnel_ids` pra o filtro de etapa valer. ATENÇÃO: dois flows ATIVOS na mesma inbox com `card_created`/`card_moved` de funil/etapa sobrepostos são bloqueados na criação/ativação (ver `flow_trigger_conflict` no fim deste guia).
|
|
76
76
|
- `team_changed`: `team_ids` (array de STRINGS; vazio = qualquer equipe). `assignee_changed`: `agent_ids` (array de STRINGS; vazio = qualquer atendente). `card_won` / `card_lost`: `funnel_ids` (array de STRINGS) — disparam SÓ quando o STATUS do card vira ganho/perdido, nunca por etapa com esse nome.
|
|
77
|
+
- `card_opened` ("Card aberto") / `card_snoozed` ("Card adiado") — NOVOS 11/10/2026, mesma config `funnel_ids` (array de STRINGS; vazio = qualquer funil). `card_snoozed` dispara quando o card é ADIADO. `card_opened` dispara quando um card adiado ABRE (pela data, por alguém ou por automação) e também quando um card ganho/perdido é REABERTO — card NOVO não dispara (para isso existe `card_created`). Pela data, o fluxo sai pela fila de disparos agendados, uma vez por card. Use `{{trigger.kanban.previous_status}}` (`snoozed`/`won`/`lost`) para separar "voltou do adiamento" de "reabriram um ganho/perdido".
|
|
77
78
|
- `page_track` (LionTrack, só flow individual): `{ "track_type": "visited_page"|"event_fired", "urls": [...], "operator": "contains"|"exact"|"starts_with", "event_names": [...], "event_operator": "equals"|"contains", "cooldown_hours": 24 }` — `cooldown_hours` (padrão 24, mínimo 1) não re-dispara pro mesmo contato dentro da janela.
|
|
78
79
|
- `conversation_attribute_changed` / `card_attribute_changed` (novo 2026-07-08): disparam na VIRADA de um atributo (da CONVERSA ou do CARD do kanban) pro valor que casa — RE-ENTRAM toda vez que o atributo muda pro valor alvo. Config: `{ "logic": "and"|"or", "rules": [ { "attr_key": "...", "operator": "...", "value": "..." } ] }` (uma rule pode usar `values: [...]` no lugar de `value` pra multi-valor). O `attrSource` é IMPLÍCITO pela chave do gatilho (conversa vs card) — NÃO informe. Operadores (contexto REATIVO — desde 09/07 `is_empty`/`is_not_empty` NÃO valem aqui, pois "está vazio AGORA" dispararia a cada evento; use-os só no nó Condição): `equal`/`not_equal`/`contains`/`not_contains`/`starts_with`/`ends_with`/`greater_than`/`less_than`/`number_range`. Só `card_attribute_changed` aceita `funnel_id`/`card_source` opcionais dentro da rule (pra achar o card). Rule sem `attr_key` é ignorada.
|
|
79
80
|
- `contact_attribute_changed` (novo 2026-07-22 — "Atributo do contato muda"): dispara quando um atributo personalizado do **CONTATO** muda e a condição casa — mesmo com o contato fora de flow. Item: `{ "key": "contact_attribute_changed", "config": { "logic": "and"|"or", "rules": [ { "attrSource": "contact", "attr_key": "...", "operator": "...", "value": "..." } ] } }` (1 a 10 rules; `values: [...]` pra multi-valor). **DIFERENTE dos irmãos de 08/07: aqui o `attrSource` VAI na rule e é SEMPRE `"contact"`.** Operadores iguais aos do nó Condição. **VERSÃO SEGURA por decisão de produto:** dispara SÓ na conversa mais recente que JÁ EXISTE numa caixa do flow (reabre se resolvida); contato sem conversa NÃO dispara e NUNCA cria conversa. Dedup de 30s por contato + anti-loop por profundidade de cadeia (flow que muda atributo que dispara flow…). Só flows de conversa.
|
|
@@ -152,7 +153,7 @@ Receita completa: `flows_create`/`flows_update` com o item no start → `flows_l
|
|
|
152
153
|
4. Salvar o flow (`flows_update`) — o save sincroniza a ativação do webhook embutido (remover o item desativa a integração automaticamente).
|
|
153
154
|
Webhooks embutidos NÃO aparecem na listagem de integrações standalone; excluir o flow destrói o webhook; duplicar o flow NÃO copia o gatilho embutido. Rate limit do endpoint público: 60/min por token.
|
|
154
155
|
|
|
155
|
-
**Gatilhos de AGENDAMENTO — Booking NATIVO do LionChat (2026-08-20):** `booking_created` (alguém marcou pelo link público, pela IA ou pelo painel), `booking_cancelled` (paciente cancelou pelo link, IA cancelou ou a equipe cancelou na Agenda), `booking_rescheduled` (a data/hora mudou — link do paciente, IA, editar/adiar na Agenda), `booking_completed` (equipe concluiu na Agenda; exige a Agenda unificada ligada na conta). **Não é e-Clínica.** Config (tudo opcional, vazio = todos): `booking_event_type_ids` (array de ids de tipo de agendamento, **STRING**), `agent_ids` (array de ids de usuário — o RESPONSÁVEL da tarefa), `create_conversation` (boolean, padrão `false`: só dispara para quem já tem conversa numa caixa do flow; `true` = cria a conversa na 1ª caixa do flow). Exemplo: `{ "key": "booking_created", "config": { "booking_event_type_ids": ["44"], "agent_ids": [], "create_conversation": true } }`. São INERTES a evento de conversa (quem dispara é o `Booking::FlowTriggerDispatcher`, por CONTA — caixa do flow só define onde a conversa é criada/reusada). Variáveis no flow: `{{booking.date}}` (DD/MM/AAAA), `{{booking.time}}`, `{{booking.weekday}}`, `{{booking.datetime}}` (ISO), `{{booking.type}}`, `{{booking.type_format}}` (presencial/videochamada), `{{booking.duration}}`, `{{booking.agent}}`, `{{booking.status}}` (confirmado/cancelado/remarcado/concluído), `{{booking.description}}`, `{{booking.cancel_url}}`, `{{booking.reschedule_url}}`, `{{booking.color}}`, `{{booking.id}}`; só no remarcado: `{{booking.previous_date}}`, `{{booking.previous_time}}`, `{{booking.previous_datetime}}`; `{{booking.meeting_url}}` NÃO vem no criado (nasce vazio). Data/hora vêm da TAREFA da Agenda (sempre atuais). Regras: o evento mais novo SUBSTITUI a rodada ativa do mesmo flow na mesma conversa (2ª consulta do mesmo paciente, ou cancelado chegando com o criado ainda esperando resposta); excluir a tarefa, reabrir cancelada ou desfazer conclusão NÃO disparam; adiar (snooze) conta como remarcado; tipo com confirmação/lembrete próprios ligados + `booking_created` = o paciente pode receber duas mensagens (a tela avisa). Colisão entre flows é por CONTA: mesmo kind + tipos se cruzando + agentes se cruzando (vazio = todos). Há também `{{booking.event}}` (`created`|`cancelled`|`rescheduled`|`completed` — bom pra condição; não aparece no seletor da tela, mas resolve); `{{trigger.type}}` = a chave do gatilho (ex.: `booking_created`), `{{trigger.kind}}` = `created`|`cancelled`|`rescheduled`|`completed` e `{{trigger.booking_id}}`. SÓ flow de conversa **individual** (a tela nem oferece em flow de grupo); **nunca dispara flow `ai_tool`**. Em caixa WhatsApp OFICIAL, conversa criada nova (ou parada há mais de 24h) está FORA da janela — texto livre no 1º bloco cai em `window_closed`/erro; comece por template.
|
|
156
|
+
**Gatilhos de AGENDAMENTO — Booking NATIVO do LionChat (2026-08-20):** `booking_created` (alguém marcou pelo link público, pela IA ou pelo painel), `booking_cancelled` (paciente cancelou pelo link, IA cancelou ou a equipe cancelou na Agenda), `booking_rescheduled` (a data/hora mudou — link do paciente, IA, editar/adiar na Agenda), `booking_completed` (equipe concluiu na Agenda; exige a Agenda unificada ligada na conta). **Não é e-Clínica.** Config (tudo opcional, vazio = todos): `booking_event_type_ids` (array de ids de tipo de agendamento, **STRING**), `agent_ids` (array de ids de usuário — o RESPONSÁVEL da tarefa), `create_conversation` (boolean, padrão `false`: só dispara para quem já tem conversa numa caixa do flow; `true` = cria a conversa na 1ª caixa do flow). Exemplo: `{ "key": "booking_created", "config": { "booking_event_type_ids": ["44"], "agent_ids": [], "create_conversation": true } }`. São INERTES a evento de conversa (quem dispara é o `Booking::FlowTriggerDispatcher`, por CONTA — caixa do flow só define onde a conversa é criada/reusada). Variáveis no flow: `{{booking.date}}` (DD/MM/AAAA), `{{booking.time}}`, `{{booking.weekday}}`, `{{booking.datetime}}` (ISO), `{{booking.type}}`, `{{booking.type_format}}` (presencial/videochamada), `{{booking.duration}}`, `{{booking.agent}}`, `{{booking.status}}` (confirmado/cancelado/remarcado/concluído), `{{booking.description}}`, `{{booking.cancel_url}}`, `{{booking.reschedule_url}}`, `{{booking.confirm_url}}`, `{{booking.calendar_url}}` (16/10: página onde o cliente salva o compromisso na agenda DELE, sem e-mail; no remarcado já sai com a hora nova — é o jeito de avisar a mudança, pedindo para apagar o compromisso antigo), `{{booking.color}}`, `{{booking.id}}`; só no remarcado: `{{booking.previous_date}}`, `{{booking.previous_time}}`, `{{booking.previous_datetime}}`; `{{booking.meeting_url}}` NÃO vem no criado (nasce vazio). Data/hora vêm da TAREFA da Agenda (sempre atuais). Regras: o evento mais novo SUBSTITUI a rodada ativa do mesmo flow na mesma conversa (2ª consulta do mesmo paciente, ou cancelado chegando com o criado ainda esperando resposta); excluir a tarefa, reabrir cancelada ou desfazer conclusão NÃO disparam; adiar (snooze) conta como remarcado; tipo com confirmação/lembrete próprios ligados + `booking_created` = o paciente pode receber duas mensagens (a tela avisa). Colisão entre flows é por CONTA: mesmo kind + tipos se cruzando + agentes se cruzando (vazio = todos). Há também `{{booking.event}}` (`created`|`cancelled`|`rescheduled`|`completed` — bom pra condição; não aparece no seletor da tela, mas resolve); `{{trigger.type}}` = a chave do gatilho (ex.: `booking_created`), `{{trigger.kind}}` = `created`|`cancelled`|`rescheduled`|`completed` e `{{trigger.booking_id}}`. SÓ flow de conversa **individual** (a tela nem oferece em flow de grupo); **nunca dispara flow `ai_tool`**. Em caixa WhatsApp OFICIAL, conversa criada nova (ou parada há mais de 24h) está FORA da janela — texto livre no 1º bloco cai em `window_closed`/erro; comece por template.
|
|
156
157
|
|
|
157
158
|
**TRAVA DE GATILHO DUPLICADO (2026-06-16) — leia ANTES de ativar/criar flow ativo:** o sistema BLOQUEIA ter dois flows ATIVOS com o MESMO gatilho na MESMA inbox e mesmo `conversation_mode` (evita o evento disparar dois flows). Colisão = mesmo tipo de gatilho + config cruzando (mesmas keywords/funil/labels/url/etc) + inbox compartilhada + mesmo modo. EXCEÇÕES que podem coexistir: `webhook_received`, `manual_trigger` e `campaign_trigger` (este último porque não dispara por evento — é só uma autorização para a campanha).
|
|
158
159
|
- **`date_trigger` separa por HORÁRIO (24/09/2026):** dois flows no mesmo campo de data, mesma direção e mesmos dias NÃO colidem se os dois tiverem horário FIXO diferente (ex.: "1 dia depois às 08:00" e "às 14:00"). Horário vindo de atributo/fórmula continua colidindo (só existe na hora do disparo); `send_time` vazio conta como 09:00 e "8:00" = "08:00". A entrega é de 10 em 10 minutos — horários a menos de 10 min podem sair juntos.
|
|
@@ -397,6 +398,7 @@ só pra destravar, ela pode sair.
|
|
|
397
398
|
| `conversation_has_ai_agent` / `conversation_no_ai_agent` / `conversation_not_ai_agent` | agente de IA atribuído (novo 2026-08-01) — ver abaixo |
|
|
398
399
|
| `contact_has_label` / `contact_no_label` / `conversation_has_label` / `conversation_no_label` | labels |
|
|
399
400
|
| `kanban_exists` / `kanban_in_stage` / `kanban_won` / `kanban_lost` | card no funil. `funnel_id` é CHAVE SEPARADA da condição (número, ex.: `"funnel_id": 37`). A etapa vai em `value` (slug puro da etapa, ex.: `"avaliacao_aceita"`) ou em `stage` — NÃO no formato `"37:etapa"`. Ex.: `{ "operator": "kanban_in_stage", "funnel_id": 37, "value": "avaliacao_aceita" }` |
|
|
401
|
+
| `kanban_snoozed` (11/10/2026) | card ADIADO no funil — `field: '_kanban_status'`, `funnel_id` separado, igual às irmãs `kanban_won`/`kanban_lost` (mesma regra do card que iniciou o fluxo). Não existe condição "card aberto" |
|
|
400
402
|
| `card_attr_equals` / `card_attr_contains` | atributo do card (`attrSource: 'card'` + `attr_key`; aceita `card_source: 'trigger'` p/ ler o card que iniciou o flow) |
|
|
401
403
|
| `pagetrack_visited` / `pagetrack_event` | LionTrack |
|
|
402
404
|
| `sla_check` | status do SLA da conversa (usa `value` = código fixo; ver abaixo) |
|
|
@@ -457,7 +459,7 @@ campanha"):
|
|
|
457
459
|
`origin_first_kind`/`origin_first_platform`, `origin_last_kind`/`origin_last_platform`, `origin_*` em geral
|
|
458
460
|
(origem unificada), `ctwa_*` (anúncio click-to-WhatsApp: `ctwa_ad_id`, `ctwa_ad_title`, `ctwa_campaign_name`,
|
|
459
461
|
`ctwa_adset_name`...), `meta_lead_*` (formulário Meta Lead Ads), `lt_*` (LionTrack: UTMs, página, dispositivo).
|
|
460
|
-
Veja a lista real com `lionchat_custom_attributes_list` (`attribute_model: conversation
|
|
462
|
+
Veja a lista real com `lionchat_custom_attributes_list` (`attribute_model: conversation_attribute` — com o sufixo; só `conversation` devolve a lista VAZIA —, `include_system: true` — as chaves de campanha são atributos de sistema).
|
|
461
463
|
- **Valores fechados** de `origin_kind` (e `origin_first_kind`/`origin_last_kind`): `paid_ad` (Anúncio),
|
|
462
464
|
`lead_form` (Formulário), `organic` (Orgânico), `direct` (Direto), `referral` (Indicação), `manual` (Origem
|
|
463
465
|
cadastrada). O painel mostra o rótulo em português, mas a comparação é pelo VALOR — `"Anúncio"` nunca casa.
|
|
@@ -558,6 +560,7 @@ o botão "Usar variável" ao lado do campo alterna lista fixa ↔ variável.
|
|
|
558
560
|
| `set_kanban_item_status` | `{ status: 'won' \| 'lost' \| 'active' }` | Marca status do card |
|
|
559
561
|
| `set_won` | `{}` | Atalho pra ganho |
|
|
560
562
|
| `set_lost` | `{ reason? }` | Atalho pra perdido |
|
|
563
|
+
| `snooze_kanban_item` (11/10/2026) | `{ funnel_id, amount, unit: 'hours' \| 'days', card_source? }` | "Adiar card": ADIA o card por N horas ou dias a partir da execução (`amount` inteiro, 1 ou mais; mínimo 1 hora). Só card aberto; adiar de novo troca a data. `card_source: 'trigger'` mira o card que iniciou o fluxo (aí `funnel_id` não é exigido). Diferente das irmãs de card: card ganho/perdido, sem card ou fluxo que NÃO veio de card com `card_source: 'trigger'` = ERRO visível no passo, nunca pulado. `set_open` (e `set_kanban_item_status` com `open`) num card ADIADO abre o card na hora e dispara "Card aberto". Ver "Card adiado" no kanban-deep-dive |
|
|
561
564
|
| `assign_agent_card` | `{ agent_id, mode? }` | Responsável do card. `mode`: `'add'` (default — SOMA na lista), `'replace'` (só o escolhido fica; atribui antes de remover os demais) ou `'remove_all'` (tira TODOS os responsáveis; `agent_id` dispensado) |
|
|
562
565
|
| `add_card_note` | `{ text }` | Nota no card. **A chave é `text`**, igual à irmã `add_private_note`. Aqui é mais grave: o motor lê SÓ `text`, sem rede — nota criada com `content` sairia REALMENTE vazia, não só invisível no formulário. Corrigido em 04/09 (a linha dizia `content`); a gravação normaliza `content` para `text` |
|
|
563
566
|
| `add_card_checklist` | `{ template_id, funnel_id?, card_source? }` | Aplica um MODELO de checklist ao card (vira um grupo). `template_id` de `kanban_config.checklist_templates`. Um modelo por bloco (repita o bloco pra mais de um) |
|
|
@@ -567,13 +570,50 @@ o botão "Usar variável" ao lado do campo alterna lista fixa ↔ variável.
|
|
|
567
570
|
| `send_conversion` (novo 2026-09-01; `event_names` 2026-09-02; `messaging_event_names` 2026-09-10) | `{ destinations: ['meta'\|'ga4'\|'google_ads'], event_names: { meta?, google_ads?, ga4? }, messaging_event_names: { meta? }, event_name (reserva), value? }` | Manda o evento de conversão pro Meta (CAPI), Google Ads e/ou GA4 — o mesmo caminho do Funil, de dentro do fluxo. Aba Sistema (só flow `conversation`). Ver bloco próprio abaixo |
|
|
568
571
|
| `deactivate_flow` ou `disable_flow` | `{}` | Encerra fluxo atual |
|
|
569
572
|
| `set_booking_situation` (novo 2026-09-14) | `{ situation: 'cancelled' \| 'completed' \| 'attended' \| 'no_show' \| 'confirmed' }` | Muda a situação do agendamento **que disparou o fluxo** (gatilho de agendamento do bloco Início, ou fluxo ligado na configuração do tipo de agendamento). Aba **Agenda** (só flow `conversation`, só com a Agenda ligada na conta). Disparado por outra coisa: **não faz efeito e o passo fica com erro visível** (não há como adivinhar o agendamento). Já no estado pedido = passo PULADO, sem escrita (sem evento, sem laço). `cancelled` cancela o **agendamento** (desarma lembretes, invalida o link de gerenciar). Origem gravada = `fluxo`, ator = o próprio flow. Sem `rescheduled`/`snoozed`: o bloco não mexe em data |
|
|
573
|
+
| `create_account_task` (novo 2026-10-20) | `{ title, description?, task_type, agenda_id?, priority?, occupies_agenda?, due: {amount, unit: 'hours' \| 'days', at?, business_days?}, responsible: {mode: 'card_owner' \| 'fixed' \| 'funnel_rotation' \| 'team_rotation', user_id?, team_id?, fallback_user_id?}, card_source: 'funnel' \| 'trigger', funnel_id? }` | "Criar tarefa": cria uma tarefa COMUM da Agenda, presa ao card do fluxo (ou só à conversa, se não houver card). Os campos de `title` a `responsible` são os MESMOS da ação `create_task` da automação do funil (ver `kanban-deep-dive`). Aba **Agenda**; exige a Agenda unificada ligada na conta. **NÃO roda em fluxo `ai_tool` nem em fluxo de grupo** (o motor recusa com erro visível no passo; o save aceita, a tela esconde o item). Detalhes logo abaixo |
|
|
570
574
|
| `update_attribute` | `{ attr_source: 'contact'\|'conversation'\|'card', attr_key, attr_value }` | Seta custom_attribute (ver abaixo) |
|
|
571
575
|
| `assign_captain` (ou `assign_captain_assistant`) | `{ assistant_id }` | Atribui IA Captain |
|
|
572
576
|
| `deactivate_captain` | `{}` | Tira a IA da conversa |
|
|
573
577
|
|
|
574
578
|
**Handles que SAEM:** `success`. Não tem handle `error` — falhas viram warning silencioso e o flow continua.
|
|
575
579
|
|
|
576
|
-
**`card_source` (blocos de card) — opcional:** as ações de card aceitam `card_source`: `'funnel'` (default — procura o card pelo `funnel_id`) ou `'trigger'` (usa o card que DISPAROU o flow, em flows iniciados por `card_created`/`card_moved`/`card_won`/`card_lost`). Com `'trigger'`, `funnel_id` deixa de ser obrigatório — EXCETO em `move_kanban_stage`/`create_kanban_item`, cujo funil/etapa são o DESTINO. Sem card-gatilho disponível, a ação é pulada (não cai no fallback de funil). Aplica-se a `move_kanban_stage`, `set_won`/`set_lost`/`set_open`, `assign_agent_card`, `add_card_note`, `add_card_checklist`, `add_card_offer`, `update_attribute` (com `attr_source: 'card'`) e às condições `card_attr_equals`/`card_attr_contains` (gravando `card_source` na própria regra).
|
|
580
|
+
**`card_source` (blocos de card) — opcional:** as ações de card aceitam `card_source`: `'funnel'` (default — procura o card pelo `funnel_id`) ou `'trigger'` (usa o card que DISPAROU o flow, em flows iniciados por `card_created`/`card_moved`/`card_won`/`card_lost`/`card_opened`/`card_snoozed`). Com `'trigger'`, `funnel_id` deixa de ser obrigatório — EXCETO em `move_kanban_stage`/`create_kanban_item`, cujo funil/etapa são o DESTINO. Sem card-gatilho disponível, a ação é pulada (não cai no fallback de funil). Aplica-se a `move_kanban_stage`, `set_won`/`set_lost`/`set_open`, `snooze_kanban_item` (esta, sem card-gatilho, dá ERRO em vez de pular), `assign_agent_card`, `add_card_note`, `add_card_checklist`, `add_card_offer`, `create_account_task` (aqui sem card-gatilho = ERRO; ver abaixo), `update_attribute` (com `attr_source: 'card'`) e às condições `card_attr_equals`/`card_attr_contains` (gravando `card_source` na própria regra).
|
|
581
|
+
|
|
582
|
+
**`create_account_task` — Criar tarefa (2026-10-20):**
|
|
583
|
+
|
|
584
|
+
```json
|
|
585
|
+
{ "key": "create_account_task", "config": {
|
|
586
|
+
"title": "Ligar para {{contact.name}}", "description": "", "task_type": "call", "agenda_id": null,
|
|
587
|
+
"priority": "none", "occupies_agenda": false,
|
|
588
|
+
"due": { "amount": 3, "unit": "days", "at": "09:00", "business_days": true },
|
|
589
|
+
"responsible": { "mode": "card_owner", "fallback_user_id": 12 },
|
|
590
|
+
"card_source": "trigger", "funnel_id": ""
|
|
591
|
+
} }
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
- **Os campos da regra** (`title`, `description`, `task_type`, `agenda_id`, `priority`, `due`, `responsible`,
|
|
595
|
+
`occupies_agenda`) têm o mesmo formato e os mesmos limites da ação `create_task` do funil: `title` obrigatório; `due`
|
|
596
|
+
em horas (1 a 720) ou dias (0 a 365, com `at` "HH:MM" e `business_days` só em dias); `responsible.mode` com a chave
|
|
597
|
+
obrigatória do modo (`fallback_user_id`, `user_id` ou `team_id`; `funnel_rotation` não pede nenhuma no save,
|
|
598
|
+
mas no fluxo SEM card o rodízio do funil não tem funil e cai na pessoa reserva `fallback_user_id` — sem reserva a
|
|
599
|
+
tarefa não nasce, com o motivo no histórico: mande `fallback_user_id` se o fluxo puder rodar sem card). Regra torta =
|
|
600
|
+
passo VERMELHO com a frase do campo a consertar, sem tarefa.
|
|
601
|
+
- **De onde vem o card (`card_source`)**: `'trigger'` = o card que INICIOU o fluxo (gatilhos `card_created`,
|
|
602
|
+
`card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`); fluxo que não nasceu de card = ERRO
|
|
603
|
+
visível, nunca pulado. `'funnel'` (o padrão da tela) = o card DESSA conversa no funil `funnel_id` (**obrigatório**
|
|
604
|
+
neste modo; funil sem `funnel_id` ou que não existe mais = erro). Conversa sem card naquele funil não é erro: a
|
|
605
|
+
tarefa nasce SÓ na conversa e o passo diz "sem card". Variáveis `{{ }}` em `title` e `description` resolvem pelo
|
|
606
|
+
resolvedor do FLUXO.
|
|
607
|
+
- **Uma tarefa por passagem do bloco**: repetir o MESMO passo (nova tentativa do sistema) não duplica; uma nova
|
|
608
|
+
passagem pelo bloco (o fluxo rodando de novo) cria outra tarefa.
|
|
609
|
+
- **Ritmo**: há um freio de 1 tarefa por segundo por conta. Passo com vaga futura já fica verde ("nasce às
|
|
610
|
+
HH:MM:SS"); se depois a tarefa for reprovada (responsável que saiu da conta, dado inválido), o aviso vai para a
|
|
611
|
+
linha do card ("Fluxo X não criou a tarefa", só com card) e para o log — o passo não muda.
|
|
612
|
+
- **Histórico do card**: "Fluxo X criou uma tarefa (tipo) para Fulana" / "Fluxo X não criou a tarefa: motivo".
|
|
613
|
+
A tarefa grava o Fluxo como quem agendou (`booking_source` `fluxo`).
|
|
614
|
+
- O interruptor de emergência da automação do funil NÃO vale para o fluxo; a Agenda unificada desligada vale (erro
|
|
615
|
+
visível no passo).
|
|
616
|
+
- **Fluxo `ai_tool` e fluxo de grupo**: não use este item (recusado na execução, com erro visível no passo).
|
|
577
617
|
|
|
578
618
|
**`send_conversion` — Enviar conversão (2026-09-01):**
|
|
579
619
|
|
|
@@ -623,6 +663,12 @@ o botão "Usar variável" ao lado do campo alterna lista fixa ↔ variável.
|
|
|
623
663
|
|
|
624
664
|
**Empresa e Cargo (2026-09-25):** `contact.company_name` e `contact.job_title` valem em CONDIÇÃO (`attr_source: 'contact'`, `attr_key` igual ao path), em filtro de regras e como variável (`{{contact.company_name}}`, `{{contact.job_title}}`). São SÓ LEITURA: a ação "Alterar atributo do contato" NÃO grava esses dois (o texto Empresa anda junto com a empresa vinculada — para ligar a empresa use `lionchat_contacts_update` com `company_id`).
|
|
625
665
|
|
|
666
|
+
**Empresa do contato (2026-10-16):** a empresa ligada ao contato da conversa (no máximo UMA por contato) vale como VARIÁVEL e como CONDIÇÃO, só com o módulo Empresas ligado.
|
|
667
|
+
- Variável em qualquer bloco de mensagem: `{{contact.company.name}}`, `{{contact.company.legal_name}}`, `{{contact.company.cnpj}}`, `{{contact.company.phone}}`, `{{contact.company.email}}`, `{{contact.company.address.city}}`, `{{contact.company.address.state}}` e `{{contact.company.custom_attribute.<chave>}}` (campo personalizado da empresa). Contato sem empresa = vazio. Data do campo personalizado: DD/MM/AAAA no bloco de mensagem; crua (AAAA-MM-DD) em API, Definir variável e Condição — igual ao atributo do contato.
|
|
668
|
+
- Condição (bloco Condição, aba Atributos, card "Atributo da empresa"): `{ "valueType": "attr_config", "attrSource": "company", "attr_key": "segmento", "operator": "equal", "value": "", "values": ["Varejo"] }`. `attr_key` = chave do campo personalizado OU cadastro com prefixo `company.name`, `company.legal_name`, `company.cnpj` (comparado só pelos dígitos), `company.phone`, `company.email`, `company.address.city`, `company.address.state`. Contato sem empresa = valor vazio (`not_equal`/`is_empty` casam). Módulo Empresas DESLIGADO = a regra NUNCA casa, nem a negativa.
|
|
669
|
+
- `attrSource` fora de `contact`/`conversation`/`card`/`company` NÃO casa (antes comparava a última mensagem do cliente) e marca o bloco com aviso.
|
|
670
|
+
- NÃO vale em condição de SAÍDA (`exit_conditions`), gatilho de entrada, parâmetro de ferramenta de IA nem em `update_attribute` (a ação não grava na empresa).
|
|
671
|
+
|
|
626
672
|
**Campos NATIVOS do contato (2026-07-29):** com `attr_source: 'contact'`, `attr_key` também aceita os paths canônicos `contact.name`, `contact.email`, `contact.cpf`, `contact.cnpj`, `contact.rg`, `contact.passport`, `contact.date_of_birth`, `contact.gender`, `contact.marital_status`, `contact.profession` e `contact.address.{cep,street,number,complement,neighborhood,city,state,country}` — gravam na ficha nativa do contato (não em custom_attributes). Regras: telefone/identifier/etiquetas NÃO são aceitos (mapa fechado — chave fora dele vira atributo personalizado comum); documentos, nascimento, gênero e **e-mail** só preenchem campo VAZIO; nome/profissão/estado civil/endereço sobrescrevem; valor em branco nunca grava; gênero aceita `m|f|o|na` e estado civil `solteiro|casado|uniao_estavel|divorciado|separado|viuvo`; data de nascimento em `dd/mm/aaaa` ou `aaaa-mm-dd`. Recusas aparecem no histórico de execução (passo 'skipped'/'error' com mensagem).
|
|
627
673
|
|
|
628
674
|
**Campos NATIVOS do contato em CONDIÇÃO (2026-08-13):** o bloco de Condições e o filtro do gatilho de data passaram a LER os mesmos paths nativos (`contact.name`, `contact.cpf`, `contact.marital_status`, `contact.address.city`, ...) na fonte `contact` — antes só liam atributo personalizado e o campo da ficha voltava vazio, jogando tudo na saída padrão em silêncio. Use com `is_empty`/`is_not_empty` para montar "o CPF está preenchido?". Aceita a forma curta (`contact.cpf`) e a longa (`contact.cadastral.cpf`). **`contact.label` NÃO é aceito** em condição (consulta cara em caminho reativo). **Gênero e estado civil são listas fechadas**: compare com o valor canônico (`m|f|o|na`, `solteiro|casado|uniao_estavel|divorciado|separado|viuvo`) — comparar com "Masculino" nunca casa.
|
|
@@ -959,6 +1005,24 @@ erro). Número de celular BR escrito sem o 9 é corrigido pelo WhatsApp antes de
|
|
|
959
1005
|
sessão do canal, orçamento 8 s). Antes de 21/08 o passo dava SUCESSO mesmo com o lead fora do grupo. A
|
|
960
1006
|
mesma correção do 9º dígito vale no `add_participants`.
|
|
961
1007
|
|
|
1008
|
+
**Quem volta só com o código interno (2026-10-09):** o WhatsApp devolve a pessoa RECÉM-COLOCADA só com o
|
|
1009
|
+
código interno dela (`<código>@lid`, sem telefone) — e horas depois continua assim. Até 09/10 o bloco comparava
|
|
1010
|
+
só telefone: `add_participants` acusava `nobody_changed`/`not_added` com a pessoa DENTRO do grupo (o fluxo
|
|
1011
|
+
parava), `create` dava `partial` falso (e mandava convite para quem já estava) e `remove_participants` dava
|
|
1012
|
+
SUCESSO falso. Desde 09/10 o bloco confere pelo telefone e, só para quem não casou, pergunta ao WhatsApp o
|
|
1013
|
+
código daquele telefone. Sem resposta do WhatsApp = conta como NÃO colocado (nunca inventa que entrou). Limite
|
|
1014
|
+
conhecido: número que não passou pela conferência de existência (fora do Brasil) e volte só com o código
|
|
1015
|
+
continua contando como fora.
|
|
1016
|
+
|
|
1017
|
+
**De onde veio cada número (2026-10-09):** nas operações com `groupParticipants`, o passo do bloco no
|
|
1018
|
+
HISTÓRICO da execução (não a variável `{{grupo.*}}`) traz `participant_sources` — um item por número com
|
|
1019
|
+
`number`, `source` (a LINHA do campo de participantes de onde ele saiu), `typed` (`true` = digitado, sem
|
|
1020
|
+
variável), `informed` (o número como foi escrito, quando o WhatsApp usa outra forma) e, quando a linha é UM
|
|
1021
|
+
atributo personalizado sozinho (`{{conversation.custom_attribute.x}}` / `{{contact.custom_attribute.x}}`),
|
|
1022
|
+
`filled_by`/`filled_at` (quem preencheu aquele atributo e quando). É só anotação: nunca muda quem vai no
|
|
1023
|
+
pedido; origem e autor podem faltar, mas nunca saem errados. Use para responder "de onde saiu esse número?"
|
|
1024
|
+
em vez de concluir que o número "não está configurado".
|
|
1025
|
+
|
|
962
1026
|
**Convite no privado de quem ficou de fora (opcional, nasce desligado; só `create`/`add_participants`;
|
|
963
1027
|
2026-08-21 — entra com o próximo deploy do app depois de 21/08/2026):** `groupInviteOnFailure: true` +
|
|
964
1028
|
`groupInviteMessage` (texto OBRIGATÓRIO nesse modo — sem texto = `invite_status: 'sem_mensagem'` e nada
|
|
@@ -1064,6 +1128,31 @@ de conexão e viram bola de neve visual. Ao gerar `position`:
|
|
|
1064
1128
|
|
|
1065
1129
|
---
|
|
1066
1130
|
|
|
1131
|
+
### 2.15 `ai_call` — "Ligar com IA" (17/10/2026)
|
|
1132
|
+
|
|
1133
|
+
So em conta com `ai_calling` + `lioncalls_calling`. A IA liga para o **telefone do contato** da conversa do flow
|
|
1134
|
+
pela linha de ligacao do WhatsApp (LionCalls).
|
|
1135
|
+
|
|
1136
|
+
```json
|
|
1137
|
+
{ "id": "ligar", "type": "ai_call", "position": {"x": 600, "y": 0},
|
|
1138
|
+
"data": { "aiCallAgentId": 4, "aiCallInboxId": 82 } }
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
- `aiCallAgentId`: id de `lionchat_captain_call_agents_list`. O que a IA fala, a voz e o **tempo maximo** da ligacao
|
|
1142
|
+
vem do agente (`max_duration_seconds`, 30-600 s; no tempo o motor desliga sozinho).
|
|
1143
|
+
- `aiCallInboxId`: id de `meta.dial_inboxes` da mesma lista (caixa com a ligacao ligada).
|
|
1144
|
+
- Saidas: `answered` (atendeu), `no_answer` (nao atendeu/recusou), `error` (nao deu pra ligar; motivo no historico).
|
|
1145
|
+
`answered`/`no_answer` sem edge = o flow termina; `error` sem edge = execucao "Falhou".
|
|
1146
|
+
- Liga **uma vez**. Para insistir, outro `ai_call` depois de `no_answer` (com um `wait` no meio). **Nunca** ligue
|
|
1147
|
+
`error` direto em outro `ai_call`.
|
|
1148
|
+
- Nao confere horario (use `condition` antes). Linha ocupada: espera a vez por ate 2 h (a IA sempre deixa uma vaga
|
|
1149
|
+
para a equipe).
|
|
1150
|
+
- **Proibido** em flow `action`, em flow de grupo e em `ai_tool` (o save recusa). Id de outra conta tambem e recusado.
|
|
1151
|
+
|
|
1152
|
+
**Receita — a IA de atendimento pede a ligacao:** etiqueta `ligar`; o cenario manda por a etiqueta quando o cliente
|
|
1153
|
+
pede para falar por telefone; flow `conversation` com gatilho `label_added` (`label_names: ["ligar"]`) -> action
|
|
1154
|
+
`remove_conversation_label` (`labels: ["ligar"]`) logo depois do start -> `ai_call`.
|
|
1155
|
+
|
|
1067
1156
|
## 2-B. Três tipos de flow: `conversation`, `ai_tool` e `action`
|
|
1068
1157
|
|
|
1069
1158
|
O campo `flow_type` (definido na criação, IMUTÁVEL depois) decide a natureza do flow:
|
|
@@ -1180,7 +1269,7 @@ Sempre presente:
|
|
|
1180
1269
|
|
|
1181
1270
|
| Variável | Conteúdo |
|
|
1182
1271
|
|---|---|
|
|
1183
|
-
| `{{trigger.type}}` | código do **EVENTO** que disparou — **NÃO é a chave do item do Início**. Valores reais: `message_created` (gatilho `message_received`), `message_sent`, `conversation_created`, `conversation_opened` (gatilho `conversation_reopened`), `conversation_resolved`, `label_added`, `label_removed`, `team_changed`, `assignee_changed`, `sla_missed`, `kanban_item_created`/`card_created`, `kanban_item_stage_changed`/`card_moved`, `card_status_changed` (`card_won` e `
|
|
1272
|
+
| `{{trigger.type}}` | código do **EVENTO** que disparou — **NÃO é a chave do item do Início**. Valores reais: `message_created` (gatilho `message_received`), `message_sent`, `conversation_created`, `conversation_opened` (gatilho `conversation_reopened`), `conversation_resolved`, `label_added`, `label_removed`, `team_changed`, `assignee_changed`, `sla_missed`, `kanban_item_created`/`card_created`, `kanban_item_stage_changed`/`card_moved`, `card_status_changed` (`card_won`, `card_lost`, `card_opened` e `card_snoozed` — olhe `{{trigger.kanban.status}}`: `won`/`lost`/`open`/`snoozed`; rótulo "Situação do card mudou" desde 11/10/2026), `conversation_attributes_changed`, `card_attributes_changed`, `contact_attribute_changed`, `group_participant_joined`/`_left`, `webhook_received`, `date_trigger`, `manual` (sidebar), `kanban_manual` (botão do card), `campaign` (Campanha de Fluxo), `page_track`, `activated_by_flow` (fluxo chamou fluxo), `lead_form` (os 3 gatilhos de formulário — `trigger.kind` diz `completed`/`milestone`/`abandoned`), `booking_created`/`booking_cancelled`/`booking_rescheduled`/`booking_completed`. Compare SEMPRE com esses códigos numa condição |
|
|
1184
1273
|
| `{{trigger.name}}` | rótulo legível do MESMO evento ("Mensagem recebida", "Card mudou de etapa") — use este pra ESCREVER pro cliente, e o `type` pra COMPARAR em condição |
|
|
1185
1274
|
| `{{trigger.activated_at}}` | quando disparou (ISO 8601). Desde 20/08/2026 `name` e `activated_at` são preenchidos em TODOS os caminhos de disparo (antes só no de evento de conversa) |
|
|
1186
1275
|
| `{{trigger.kanban_item_id}}` / `{{trigger.funnel_id}}` | só quando veio do Kanban |
|
|
@@ -1220,9 +1309,10 @@ Oferecidos no autocompletar (só quando o bloco Início tem o gatilho que os pre
|
|
|
1220
1309
|
|
|
1221
1310
|
| Gatilhos do Início | Variáveis |
|
|
1222
1311
|
|---|---|
|
|
1223
|
-
| `card_created`, `card_moved`, `card_won`, `card_lost`, `card_attribute_changed` | `{{trigger.kanban.title}}`, `{{trigger.kanban.funnel_name}}`, `{{trigger.kanban.stage_name}}`, `{{trigger.kanban.stage}}` (código da etapa) |
|
|
1312
|
+
| `card_created`, `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `card_attribute_changed` | `{{trigger.kanban.title}}`, `{{trigger.kanban.funnel_name}}`, `{{trigger.kanban.stage_name}}`, `{{trigger.kanban.stage}}` (código da etapa) |
|
|
1224
1313
|
| `card_moved` | `{{trigger.kanban.previous_stage_name}}`, `{{trigger.kanban.previous_stage}}` |
|
|
1225
|
-
| `card_won`, `card_lost` | `{{trigger.kanban.status}}` (`won`/`lost`) |
|
|
1314
|
+
| `card_won`, `card_lost`, `card_opened`, `card_snoozed` | `{{trigger.kanban.status}}` (`won`/`lost`/`open`/`snoozed`) |
|
|
1315
|
+
| `card_opened` | `{{trigger.kanban.previous_status}}` (`snoozed` = voltou do adiamento; `won`/`lost` = reabriram um ganho/perdido) |
|
|
1226
1316
|
| `label_added`, `label_removed` | `{{trigger.label.name}}` |
|
|
1227
1317
|
| `assignee_changed` | `{{trigger.assignee.name}}` (vazio = responsável removido) |
|
|
1228
1318
|
| `team_changed` | `{{trigger.team.name}}` (vazio = equipe removida) |
|
|
@@ -1235,7 +1325,7 @@ Resolvem mas NÃO aparecem no seletor (produtor único — só o gatilho daquela
|
|
|
1235
1325
|
`{{trigger.eclinica.event|unit|date|time|compromisso|idagenda}}`, `{{trigger.lead.form|page|ad|adset|campaign|platform}}`
|
|
1236
1326
|
(nome do anúncio, não dado de pessoa), `{{trigger.dtmf.key|campaign}}`, `{{trigger.reminder.date|time|compromisso|unit|days_before}}`,
|
|
1237
1327
|
além de `{{trigger.kanban.id}}`/`funnel_id` (use `{{trigger.kanban_item_id}}`/`{{trigger.funnel_id}}`),
|
|
1238
|
-
`{{trigger.assignee.id}}`, `{{trigger.team.id}}
|
|
1328
|
+
`{{trigger.assignee.id}}`, `{{trigger.team.id}}` (`{{trigger.kanban.previous_status}}` passou a ser oferecida no `card_opened`, 11/10/2026) e
|
|
1239
1329
|
`{{trigger.group.participants_count}}`. As RESPOSTAS do lead do Meta não viram variável (só aparecem no
|
|
1240
1330
|
histórico). Sessões anteriores a 22/08 não têm fatos gravados: essas variáveis saem vazias nelas.
|
|
1241
1331
|
O bloco do card chama-se `kanban` — nunca `card`. Se o cliente precisar de um dado que não está aqui,
|
|
@@ -1280,7 +1370,7 @@ texto trocava o protocolo pelo id interno do banco.
|
|
|
1280
1370
|
{ "attr_key": "status", "attrSource": "conversation", "operator": "equal", "value": "cancelado" }
|
|
1281
1371
|
] }
|
|
1282
1372
|
```
|
|
1283
|
-
- `attrSource` (`'contact'`|`'conversation'`|`'card'`) VAI na rule (ao contrário do gatilho de entrada por atributo, onde é implícito).
|
|
1373
|
+
- `attrSource` (`'contact'`|`'conversation'`|`'card'`) VAI na rule (ao contrário do gatilho de entrada por atributo, onde é implícito). `'company'` NÃO vale aqui (só no bloco Condição): a regra de saída não lê a empresa.
|
|
1284
1374
|
- `operator` (contexto REATIVO — desde 09/07 SEM `is_empty`/`is_not_empty`, que dispararia a cada evento; use-os só no nó Condição): `equal`/`not_equal`/`contains`/`not_contains`/`starts_with`/`ends_with`/`greater_than`/`less_than`/`number_range`. Multi-valor via `values: [...]` no lugar de `value`.
|
|
1285
1375
|
- Reativa (09/07): só é reavaliada quando o atributo VIGIADO daquela rule realmente muda — não a cada mensagem. Cada rule exige `attr_key` + (`value` ou `values`); rule sem isso é ignorada.
|
|
1286
1376
|
- `card` aceita `funnel_id`/`card_source` opcionais na rule.
|
|
@@ -663,6 +663,39 @@ uma entrada por vez; quem entrar enquanto os balões da pessoa anterior saem nã
|
|
|
663
663
|
|
|
664
664
|
---
|
|
665
665
|
|
|
666
|
+
## 18. Tarefa de acompanhamento ao ganhar um card (`create_account_task`)
|
|
667
|
+
|
|
668
|
+
**Caso:** quando um card é marcado como GANHO, criar para o responsável do card uma tarefa "Ligar para <cliente>" daqui a
|
|
669
|
+
3 dias úteis, às 09:00 (pula sábado, domingo e feriado de dia inteiro da agenda). Usa o item "Criar tarefa" do bloco
|
|
670
|
+
Ações (aba Agenda). Pré-requisito: Agenda unificada ligada na conta. Não funciona em fluxo `ai_tool` nem de grupo.
|
|
671
|
+
|
|
672
|
+
```json
|
|
673
|
+
{
|
|
674
|
+
"nodes": [
|
|
675
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "items": [{ "key": "card_won", "config": { "funnel_ids": ["1"] } }] } },
|
|
676
|
+
{ "id": "n2", "type": "action", "position": { "x": 370, "y": 300 }, "data": { "label": "Tarefa de pós-venda", "items": [
|
|
677
|
+
{ "key": "create_account_task", "config": {
|
|
678
|
+
"title": "Ligar para {{contact.name}} (pós-venda)", "description": "", "task_type": "call", "agenda_id": null,
|
|
679
|
+
"priority": "medium", "occupies_agenda": false,
|
|
680
|
+
"due": { "amount": 3, "unit": "days", "at": "09:00", "business_days": true },
|
|
681
|
+
"responsible": { "mode": "card_owner", "fallback_user_id": 12 },
|
|
682
|
+
"card_source": "trigger", "funnel_id": ""
|
|
683
|
+
} }
|
|
684
|
+
] } }
|
|
685
|
+
],
|
|
686
|
+
"edges": [
|
|
687
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true }
|
|
688
|
+
]
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Notas:
|
|
693
|
+
- `card_source: "trigger"` usa o card que ganhou; sem `funnel_id`. Para agir sobre o card da conversa em outro funil
|
|
694
|
+
(fluxo disparado por mensagem, por exemplo), use `card_source: "funnel"` com `funnel_id` preenchido.
|
|
695
|
+
- `fallback_user_id` (12 aqui) é a pessoa que recebe quando o card não tem responsável: troque por um id de
|
|
696
|
+
`agents_list`. `task_type` é um dos 7 de fábrica ou uma `key` de `account_task_types_list`.
|
|
697
|
+
- Para a tarefa aparecer SÓ no card (sem bloquear o horário da Agenda) deixe `occupies_agenda` em `false`.
|
|
698
|
+
|
|
666
699
|
## Como usar este catálogo
|
|
667
700
|
|
|
668
701
|
1. **Identifique o pattern mais próximo** do que o cliente pediu
|
|
@@ -35,6 +35,7 @@ caixa de WhatsApp vinculada e (opcionalmente) dispara um fluxo do FlowBuilder no
|
|
|
35
35
|
| **Formulário público** (este documento) | Página de captação hospedada pelo LionChat, com blocos e link próprio |
|
|
36
36
|
| **MetaLeadForm** | Formulário de anúncio da Meta (Facebook/Instagram Lead Ads) — outro módulo |
|
|
37
37
|
| **Flow / FlowBuilder** | Motor de automação de conversa. O formulário *dispara* fluxos, mas não é um fluxo |
|
|
38
|
+
| **Formulário do WhatsApp** (17/10/2026) | Formulário nativo da Meta, preenchido DENTRO do WhatsApp, aberto por botão de modelo de mensagem. Ferramentas `lionchat_whatsapp_forms_*` — seção própria no fim deste documento |
|
|
38
39
|
|
|
39
40
|
## Ferramentas disponíveis
|
|
40
41
|
|
|
@@ -450,7 +451,7 @@ em `responses_show.milestones`.
|
|
|
450
451
|
|
|
451
452
|
**`lionchat_lead_forms_responses_list`** aceita `status` (`in_progress`, `completed`,
|
|
452
453
|
`abandoned`), `days` e `page` (até 10.000). A lista nunca traz as respostas em si — só `{id, status,
|
|
453
|
-
contact, current_node_label, answered_count, created_at, completed_at}` e `meta: {current_page,
|
|
454
|
+
contact, current_node_label, answered_count, created_at, completed_at, filled_by}` e `meta: {current_page,
|
|
454
455
|
per_page: 25, total_count}`. **`contact` pode vir `{id: null, name, phone, pending: true}`** — é
|
|
455
456
|
quem ainda está preenchendo (o contato só nasce nos três momentos); nome e telefone saem do que a
|
|
456
457
|
pessoa já digitou. `answered_count` conta todas as chaves de `answers`, inclusive as sintéticas.
|
|
@@ -478,6 +479,24 @@ falha de transporte sem código), `timeout`, `ssrf_blocked`, `result_too_large`,
|
|
|
478
479
|
`no_ai_key`, `ai_error`. (Os motivos `busy` e `unresolved_variable`, citados antes, não existem no
|
|
479
480
|
código.)
|
|
480
481
|
|
|
482
|
+
### Preenchimento pela equipe, dentro da conversa — 20/10/2026 (entra com o próximo deploy do app)
|
|
483
|
+
|
|
484
|
+
No painel, a barra lateral da conversa ganhou o quadro **Formulários**: o atendente (SDR) abre qualquer formulário
|
|
485
|
+
publicado e ligado numa janela e preenche durante a ligação. Essa resposta é **da equipe**:
|
|
486
|
+
|
|
487
|
+
- `filled_by` (lista, show e Preenchimentos do contato): `null` = o próprio cliente pelo link; `{id, name}` = o
|
|
488
|
+
atendente que preencheu; `{id, removed: true}` = o atendente foi apagado (o selo continua).
|
|
489
|
+
- Contato e conversa ficam **fixos**: os da conversa. Telefone digitado nunca troca de contato nem cria ficha; se já
|
|
490
|
+
for de outra ficha (com ou sem o nono dígito) não é gravado.
|
|
491
|
+
- Todos os blocos rodam como no link (atributos, etiquetas, marco, API, IA, WhatsApp, contrato, agenda). A única
|
|
492
|
+
diferença: os fluxos **"Formulário concluído"** e **"Formulário abandonado"** NÃO disparam — o pulo fica registrado
|
|
493
|
+
com o motivo `filled_by_team`. "Marco do formulário" dispara.
|
|
494
|
+
- Fica **fora** de `lionchat_lead_forms_stats` (funil, conclusão) e dos contadores da lista (`responses_count`,
|
|
495
|
+
`completed_count`), e do relatório de formulários. Aparece em `responses_list`/`responses_show` com o selo.
|
|
496
|
+
- Não há ferramenta do MCP para começar esse preenchimento — ele só existe na janela do painel.
|
|
497
|
+
- Atributo gravado por QUALQUER formulário (link ou equipe) acorda o mesmo que a edição manual: automação "atributo
|
|
498
|
+
alterado", fluxos de atributo e webhook (desde 20/10/2026).
|
|
499
|
+
|
|
481
500
|
## Preenchimentos do contato (`lionchat_contacts_form_entries_list` / `_show`) — 21/08 (entra com o próximo deploy do app depois de 21/08/2026)
|
|
482
501
|
|
|
483
502
|
A aba "Preenchimentos" da ficha junta, numa lista só ordenada por data, tudo que a pessoa preencheu
|
|
@@ -487,7 +506,7 @@ FlowBuilder cria pro gatilho de um fluxo (`flow`, com o nome do fluxo). É a ún
|
|
|
487
506
|
"o que esta PESSOA preencheu" — as outras são por formulário/integração, e duas delas são só de
|
|
488
507
|
administrador; esta é liberada a qualquer agente.
|
|
489
508
|
|
|
490
|
-
- **Lista**: `{payload: [{source, id, title, status, at, count, conversation}], meta: {total,
|
|
509
|
+
- **Lista**: `{payload: [{source, id, title, status, at, count, conversation, filled_by}], meta: {total,
|
|
491
510
|
truncated}}`. `id` é o id do registro NA ORIGEM — só identifica junto com `source`. `status` é
|
|
492
511
|
`in_progress|completed|abandoned` no nosso formulário e `received` nas demais. `count` = respostas
|
|
493
512
|
(nosso) ou campos vinculados e gravados (de fora). `conversation` só existe em `lead_form`. Sem
|
|
@@ -608,3 +627,141 @@ agendar (com `required: true` essa saída deixa de existir). O tipo de evento ve
|
|
|
608
627
|
blocos. Teste o trecho seguinte pela página pública.
|
|
609
628
|
- **`stats.views` é de vida inteira** (ignora `days`); `stats.milestones` não vê marco em `items`.
|
|
610
629
|
- **`name` é interno; `settings.public_title` é o que o lead vê** (vazio = cai no `name`).
|
|
630
|
+
|
|
631
|
+
## Formulário do WhatsApp (WhatsApp Flows da Meta) — 17/10/2026
|
|
632
|
+
|
|
633
|
+
Segundo tipo da área Formulários. É o formulário **nativo do WhatsApp**: o cliente toca num botão de um modelo de
|
|
634
|
+
mensagem e preenche sem sair do WhatsApp; as respostas voltam para a conversa ("Formulário respondido", pergunta por
|
|
635
|
+
pergunta). Só caixa do **WhatsApp Oficial** (Cloud API). Montar, publicar, aposentar e excluir = só administrador;
|
|
636
|
+
listar e ver = qualquer pessoa da conta. Não confundir com o **Formulário público** (o resto deste documento, página
|
|
637
|
+
com link próprio) nem com o formulário de anúncio da Meta (MetaLeadForm).
|
|
638
|
+
|
|
639
|
+
### Ferramentas
|
|
640
|
+
|
|
641
|
+
| Ferramenta | Para quê |
|
|
642
|
+
|---|---|
|
|
643
|
+
| `lionchat_whatsapp_forms_list` | Lista (`inbox_id` filtra pela conta do WhatsApp; `with_questions=true` traz `questions: [{code, label}]`; `refresh=true` relê o estado na Meta) |
|
|
644
|
+
| `lionchat_whatsapp_forms_show` | Rascunho completo, `save_targets`, `image_urls`, `limits` (os limites da Meta, por tipo), `published_version`, `version_outdated` |
|
|
645
|
+
| `lionchat_whatsapp_forms_create` | Cria rascunho `{name, inbox_id, editor_data?}` — nada vai para a Meta ainda |
|
|
646
|
+
| `lionchat_whatsapp_forms_update` | Salva `name`, `editor_data` (SUBSTITUI o rascunho inteiro) e/ou `save_targets` |
|
|
647
|
+
| `lionchat_whatsapp_forms_images` | Sobe imagem POR LINK (`url` http/https de imagem pública): o servidor baixa, reduz para o limite da Meta e devolve `{blob_id, url, width, height}` |
|
|
648
|
+
| `lionchat_whatsapp_forms_publish` | Gera o arquivo, cria/edita na Meta e publica |
|
|
649
|
+
| `lionchat_whatsapp_forms_preview` | Endereço da prévia oficial da Meta (abre sem login, 30 dias) |
|
|
650
|
+
| `lionchat_whatsapp_forms_deprecate` | Aposenta na Meta — IRREVERSÍVEL |
|
|
651
|
+
| `lionchat_whatsapp_forms_destroy` | Exclui rascunho ou aposentado |
|
|
652
|
+
|
|
653
|
+
### Passo a passo
|
|
654
|
+
1. `_create` com `name` (único na conta do WhatsApp — a Meta recusa nome repetido ao publicar) e `inbox_id` de uma
|
|
655
|
+
caixa oficial da conta (outra caixa = 422 `inbox_must_be_official`).
|
|
656
|
+
2. Imagem (se houver): `_images` com o link → use o `blob_id` em `{ "type": "image", "image": "<blob_id>" }`.
|
|
657
|
+
3. `_update` com o `editor_data` completo (leia com `_show` antes de editar: o rascunho é substituído inteiro).
|
|
658
|
+
4. `_publish`. Fica PARA SEMPRE na conta do WhatsApp do cliente (só dá para aposentar). Republicar depois de editar
|
|
659
|
+
mantém os modelos funcionando, sem nova aprovação.
|
|
660
|
+
5. Botão no modelo: `lionchat_inboxes_whatsapp_templates_create` com
|
|
661
|
+
`{type: 'BUTTONS', buttons: [{type: 'FLOW', text: 'Preencher', flow_id: '<meta_flow_id>', flow_action: 'navigate'}]}`
|
|
662
|
+
(`meta_flow_id` vem do `_list`/`_show`; o formulário tem de estar publicado; no máximo 1 botão FLOW por modelo; texto
|
|
663
|
+
do botão até 25). A Meta costuma aprovar em minutos e pode trocar a categoria para Marketing. Trocar o formulário do
|
|
664
|
+
botão de um modelo aprovado manda o modelo de volta para análise.
|
|
665
|
+
6. Envie o modelo como qualquer outro (conversa, campanha, fluxo, automação). O componente que a Meta exige para o
|
|
666
|
+
botão de formulário é montado pelo servidor — não mande nada a mais.
|
|
667
|
+
7. (Opcional) Fluxo com gatilho `whatsapp_form_answered` — config `{whatsapp_form_id: '<id nosso, STRING>'}` (vazio =
|
|
668
|
+
qualquer formulário; lista também é aceita). Variáveis `{{trigger.form.name}}`, `{{trigger.form.id}}`,
|
|
669
|
+
`{{trigger.form.f_<n>}}` (a resposta de cada pergunta já em texto).
|
|
670
|
+
|
|
671
|
+
### O `editor_data`
|
|
672
|
+
```json
|
|
673
|
+
{ "category": "SURVEY", "next_label": "Continuar", "submit_label": "Enviar",
|
|
674
|
+
"screens": [
|
|
675
|
+
{ "title": "Seus dados",
|
|
676
|
+
"fields": [
|
|
677
|
+
{ "type": "heading", "text": "Conte um pouco sobre você" },
|
|
678
|
+
{ "type": "image", "image": "123", "alt_text": "Logo da clínica" },
|
|
679
|
+
{ "type": "short_text", "label": "Seu nome", "required": true, "max_chars": 60 },
|
|
680
|
+
{ "type": "single_choice", "label": "Como nos achou?",
|
|
681
|
+
"options": [{ "label": "Instagram" }, { "label": "Indicação", "description": "Amigo ou parente" }] },
|
|
682
|
+
{ "type": "calendar", "label": "Entrada", "mode": "range", "end_label": "Saída", "days": ["Fri", "Sat"] },
|
|
683
|
+
{ "type": "photo", "label": "Foto do documento", "max_files": 2 },
|
|
684
|
+
{ "type": "link", "text": "Nossos termos", "url": "https://exemplo.com/termos" }
|
|
685
|
+
] } ] }
|
|
686
|
+
```
|
|
687
|
+
- `category`: SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY, OTHER.
|
|
688
|
+
- `next_label` (botão das telas do meio) e `submit_label` (botão da última tela, que envia): até 35 caracteres.
|
|
689
|
+
Só a ÚLTIMA tela envia; as anteriores levam para a seguinte.
|
|
690
|
+
- Campo NOVO vai sem `code`: o servidor dá `f_<n>` (opções `o_<n>`). Código já publicado NUNCA é reaproveitado.
|
|
691
|
+
- Perguntas (limite do texto da pergunta entre parênteses — use `helper`, até 80, para explicar mais):
|
|
692
|
+
`short_text`, `email`, `phone`, `number`, `long_text` (20); `date` e `calendar` (40); `single_choice` (30; até 200
|
|
693
|
+
opções, passou de 20 vira lista suspensa) e `multiple_choice` (30; até 20 opções); opção até 30, descrição da opção
|
|
694
|
+
até 300; `opt_in` (aceite, 120; `read_more_url` mostra um "Ler mais" que abre o link); `photo` e `document` (80;
|
|
695
|
+
`description` até 300, `max_files` 1-10, `max_size_mb` 1-25 — a foto sai SEMPRE com no máximo 5 MB, o limite de
|
|
696
|
+
recebimento do WhatsApp oficial; foto: `source` camera_gallery|camera|gallery; arquivo: `file_kinds`
|
|
697
|
+
pdf|word|spreadsheet|presentation|image|text|compressed|video). `required: true` = obrigatória (na foto/arquivo
|
|
698
|
+
vira "pelo menos 1").
|
|
699
|
+
- Ajustes: `max_chars` (NÚMERO 1-4000), `min_date`/`max_date` "AAAA-MM-DD" (data fixa — não existe "a partir de
|
|
700
|
+
hoje"), calendário `mode` single|range + `end_label`/`end_helper` (rótulo e ajuda do fim; a ajuda vai nas DUAS
|
|
701
|
+
pontas ou em nenhuma) + `title` (80) + `description` (300) + `days` (Mon..Sun, os dias que podem ser escolhidos);
|
|
702
|
+
escolha múltipla `min_selected`/`max_selected` (nunca acima do número de opções, mínimo nunca acima do máximo).
|
|
703
|
+
- Conteúdo (`text`): `heading` e `subheading` (80), `paragraph` e `caption` (4096), `link` (`text` até 25 + `url`
|
|
704
|
+
http/https), `image` (`image` = `blob_id` do `_images`, `alt_text` até 100).
|
|
705
|
+
- Tetos: 10 telas; 40 campos e 5 aceites por tela; título de tela 30; por tela 1 foto/arquivo, 3 imagens e 2 links;
|
|
706
|
+
até 10 arquivos no formulário inteiro (soma do `max_files`).
|
|
707
|
+
|
|
708
|
+
### Salvar x publicar (onde cada erro aparece)
|
|
709
|
+
- **Salvar** (`_create`/`_update`) recusa com 422 `{errors: [...]}` só o FORMATO: tipo desconhecido, número fora da
|
|
710
|
+
faixa, data fora do formato, lista com valor desconhecido, `category` fora da lista, telas fora de 1-10, mais de 40
|
|
711
|
+
campos ou 5 aceites numa tela, opções em formato errado. Limite de caracteres da Meta NÃO barra o salvar
|
|
712
|
+
(dá para salvar no meio do caminho).
|
|
713
|
+
- **Publicar** recusa com 422 `{problems: [{code, screen, field, limit}], error, form}` (`screen`/`field` começam em
|
|
714
|
+
0). Códigos de `problems`:
|
|
715
|
+
|
|
716
|
+
| code | O que corrigir |
|
|
717
|
+
|---|---|
|
|
718
|
+
| `no_questions` | o formulário não tem nenhuma pergunta |
|
|
719
|
+
| `empty_label` / `empty_text` | pergunta sem texto / conteúdo sem texto |
|
|
720
|
+
| `too_long` (`limit`) | texto acima do limite daquele tipo (pergunta, ajuda, fim do intervalo, link, texto alternativo) |
|
|
721
|
+
| `title_too_long` / `button_too_long` | título de tela acima de 30 / botão acima de 35 |
|
|
722
|
+
| `description_too_long` | descrição de foto/arquivo/calendário acima de 300 |
|
|
723
|
+
| `no_options` / `empty_option` / `option_too_long` / `option_description_too_long` | escolha sem opções / opção vazia / opção acima de 30 / descrição de opção acima de 300 |
|
|
724
|
+
| `selection_invalid` | mínimo/máximo de marcações impossível |
|
|
725
|
+
| `date_range_invalid` | data mínima depois da máxima |
|
|
726
|
+
| `empty_end_label` / `range_helper_incomplete` / `calendar_title_too_long` | intervalo sem rótulo do fim / ajuda numa ponta só / título do calendário acima de 80 |
|
|
727
|
+
| `invalid_url` / `invalid_read_more_url` | link ou "Ler mais" sem http/https |
|
|
728
|
+
| `no_image` / `image_missing` | imagem sem arquivo / arquivo que não é deste formulário (suba de novo pelo `_images`) |
|
|
729
|
+
| `too_many_links` / `too_many_images` / `too_many_pickers` | mais de 2 links / 3 imagens / 1 foto-arquivo na mesma tela |
|
|
730
|
+
| `too_many_files` | soma de arquivos acima de 10 no formulário |
|
|
731
|
+
|
|
732
|
+
`error.kind`: `no_channel` (nenhuma caixa oficial dessa conta do WhatsApp), `busy` (publicação em andamento),
|
|
733
|
+
`duplicate_name` (nome já usado nessa conta do WhatsApp), `validation` (a Meta recusou o arquivo; a mensagem diz
|
|
734
|
+
onde), `meta`, `network`, `too_large`, `unexpected`.
|
|
735
|
+
- `_update` durante uma publicação devolve 409 `busy`.
|
|
736
|
+
|
|
737
|
+
### "Salvar em" (`save_targets`)
|
|
738
|
+
`{"f_1": "contact.name", "f_2": "custom.cidade"}` no `_update`. Destinos: `contact.name`, `contact.email`,
|
|
739
|
+
`contact.cadastral.<cpf|rg|cnpj|passport|profession|marital_status|gender|date_of_birth>`,
|
|
740
|
+
`contact.address.<cep|street|number|complement|neighborhood|city|state|country>`, `custom.<chave do contato>`,
|
|
741
|
+
`conversation_custom.<chave da conversa>`. O atributo precisa existir na conta (`lionchat_custom_attributes_list`)
|
|
742
|
+
e não ser protegido; destino inválido = 422 (inclusive código de pergunta de foto/arquivo, ou que não existe no
|
|
743
|
+
rascunho nem na última publicação). Telefone nunca. Vale na hora (não precisa publicar). Grava quando o cliente
|
|
744
|
+
envia: dado novo vence, resposta em branco não apaga, valor que não cabe no tipo do atributo não grava. Pergunta
|
|
745
|
+
tirada do rascunho mantém o destino até publicar de novo (a versão no ar ainda pergunta). Foto e arquivo não têm
|
|
746
|
+
destino: chegam como anexo da própria mensagem de resposta.
|
|
747
|
+
|
|
748
|
+
### Como a resposta chega (para ler depois)
|
|
749
|
+
- Mensagem ENTRANTE na conversa do cliente, texto fixo "Formulário respondido", `content_type: form`, com
|
|
750
|
+
`content_attributes.items` (`[{name: 'f_1', label: 'Seu nome'}]`) e `content_attributes.submitted_values`
|
|
751
|
+
(`[{name: 'f_1', value: 'Maria'}]`) — leia por `lionchat_conversations_messages_list`.
|
|
752
|
+
- Os valores já vêm legíveis: opção pelo nome, data DD/MM/AAAA, intervalo "DD/MM/AAAA a DD/MM/AAAA", aceite Sim/Não,
|
|
753
|
+
foto/arquivo "N arquivos: nomes" (os arquivos vêm como anexos da mesma mensagem; arquivo acima do limite de
|
|
754
|
+
recebimento fica de fora).
|
|
755
|
+
- `content_attributes.whatsapp_form`: `form_id`, `publication_number`, `flow_token` e `raw` (as respostas cruas).
|
|
756
|
+
Sem nenhuma resposta: "Formulário respondido (nenhuma resposta preenchida)"; ilegível: "Formulário recebido (não
|
|
757
|
+
foi possível ler as respostas)" com `whatsapp_form.unreadable = true`.
|
|
758
|
+
- A IA de atendimento lê as respostas; a resposta reabre a conversa como qualquer mensagem do cliente. Fluxo parado
|
|
759
|
+
em "Aguardar resposta" só segue depois do "Salvar em" gravar.
|
|
760
|
+
|
|
761
|
+
### Armadilhas
|
|
762
|
+
- **Aposentar (`_deprecate`) é irreversível** e derruba todo modelo que abre o formulário. Confirme com o usuário.
|
|
763
|
+
- `_destroy` só apaga rascunho ou aposentado (publicado = `deprecate_first`).
|
|
764
|
+
- `version_outdated: true` no `_show` = publicado numa versão que a Meta não aceita mais: publicar de novo.
|
|
765
|
+
- `flow_id` do botão é o `meta_flow_id` (número da Meta), não o `id` nosso; o gatilho do fluxo usa o `id` nosso.
|
|
766
|
+
- Imagem: só por LINK de imagem pública (página da web, endereço interno ou arquivo que não é imagem = 422
|
|
767
|
+
`fetch_failed`/`invalid_image`; acima de 10 MB = `file_too_large`).
|
|
@@ -214,6 +214,13 @@ comportamento intencional.
|
|
|
214
214
|
- `funnel_stage`: nome da etapa atual (string)
|
|
215
215
|
- `position`: ordem dentro da etapa (inteiro)
|
|
216
216
|
- `stage_entered_at`: timestamp de quando entrou na etapa atual
|
|
217
|
+
- Situação (11/10/2026): `item_details.status` guarda `open`/`won`/`lost`; a resposta traz também `effective_status`
|
|
218
|
+
(`open`, **`snoozed`** = adiado, `won`, `lost`) e `snoozed_until`. **Card adiado** = card aberto que sai da coluna até
|
|
219
|
+
uma data e volta sozinho nela ("Adiar até" na tela). Ferramentas `lionchat_kanban_items_snooze`/`_unsnooze`; regras
|
|
220
|
+
em kanban-deep-dive, seção "Card adiado".
|
|
221
|
+
- Venda (13/10/2026): `item_details.attributed_to` = **vendedor** do ganho ("Atribuir ganho a");
|
|
222
|
+
`item_details.co_attributed_to` = **co-participante da venda** (ex.: o SDR), só em card ganho. Regras em
|
|
223
|
+
kanban-deep-dive, seção "Co-participante da venda".
|
|
217
224
|
|
|
218
225
|
### `item_details` (jsonb)
|
|
219
226
|
```json
|
|
@@ -529,6 +536,22 @@ A plataforma opera com 6 idiomas: `en`, `es`, `fr`, `it`, `pt`, `pt_BR` (default
|
|
|
529
536
|
brasileiras: pt_BR). Conta com idioma antigo/descontinuado cai em inglês. Notas internas geradas
|
|
530
537
|
pela IA saem no idioma da conta.
|
|
531
538
|
|
|
539
|
+
## Formulário do WhatsApp (WhatsappForm) — 17/10/2026
|
|
540
|
+
|
|
541
|
+
Formulário NATIVO da Meta (WhatsApp Flows), preenchido DENTRO do WhatsApp e aberto por um botão FLOW num modelo
|
|
542
|
+
de mensagem. Só caixa do WhatsApp Oficial. Montado no LionChat (2º tipo da área Formulários) e publicado na conta
|
|
543
|
+
do WhatsApp do cliente. Ferramentas `lionchat_whatsapp_forms_*`; regras completas no resource
|
|
544
|
+
`lionchat://docs/formularios-publicos`, seção "Formulário do WhatsApp". Três formulários que NÃO são a mesma coisa:
|
|
545
|
+
**Formulário público** (LeadForm, página com link próprio), **Formulário do WhatsApp** (este) e **formulário de
|
|
546
|
+
anúncio da Meta** (MetaLeadForm, Lead Ads).
|
|
547
|
+
|
|
548
|
+
| Status | Significado |
|
|
549
|
+
|---|---|
|
|
550
|
+
| `draft` | rascunho, nunca publicado (pode excluir) |
|
|
551
|
+
| `publishing` | publicação em andamento |
|
|
552
|
+
| `published` | no ar; `unpublished_changes: true` = o rascunho mudou depois da última publicação |
|
|
553
|
+
| `deprecated` | aposentado na Meta (irreversível); pode excluir |
|
|
554
|
+
|
|
532
555
|
## LeadForm (Formulário público de captação)
|
|
533
556
|
|
|
534
557
|
Formulário de captura próprio da conta, com página pública (link `/forms/<conta>/<slug>`), montado
|