@lionchat/mcp-server 1.10.2 → 1.10.3
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 +3 -0
- package/dist/docs/resources/api-conventions.md +23 -0
- package/dist/docs/resources/best-practices.md +40 -0
- package/dist/docs/resources/conversation-flows.md +58 -0
- package/dist/docs/resources/data-model.md +13 -2
- package/dist/docs/resources/kanban-deep-dive.md +2 -1
- package/dist/docs/resources/troubleshooting.md +55 -0
- package/endpoints.json +28121 -26065
- package/package.json +1 -1
|
@@ -374,6 +374,9 @@ Antes de escolher a ferramenta, cheque se a intenção bate com a coluna da dire
|
|
|
374
374
|
| **Definir supervisor** de caixa | `lionchat_inbox_members_create` / `_update` com `supervisor_ids[]` | Supervisor vê TUDO da caixa mas fica fora do rodízio (ver abaixo) |
|
|
375
375
|
| **Definir supervisor** de time | `lionchat_team_members_create` / `_update` com `supervisor_ids[]` | Contrato diferente do da caixa: `user_ids[]` é a lista COMPLETA e `supervisor_ids[]` um subconjunto dela. Omitir `supervisor_ids` não mexe em papel nenhum (seção 2) |
|
|
376
376
|
| **Mudar a fila do time** (teto por atendente, janela, online/offline) | `lionchat_teams_update` (`assignment_mode`, `fair_distribution_limit`, `fair_distribution_window`) | Time tem PREFERÊNCIA sobre a caixa na distribuição. Leia a config atual antes de mudar (ver `lionchat://docs/conversation-flows`) |
|
|
377
|
+
| **Criar/atualizar time** | `lionchat_teams_create` / `_update` | **Preencha `description`**: desde 03/08 é ela que o AI Agente lê pra decidir o roteamento por time. Descreva QUANDO mandar pra lá, não o que o time é |
|
|
378
|
+
| **Pausar a automação no meio** (esperar atribuição/card antes da próxima ação) | ação `wait` em `lionchat_automation_rules_create` / `_update` | Segundos, teto 300. Acima disso é caso de FlowBuilder. Ver `lionchat://docs/conversation-flows` |
|
|
379
|
+
| **Buscar contato/conversa/card** | `lionchat_search_*`, `lionchat_contacts_search` | **Termo com letra exige 3+ caracteres** (dígito é isento). Menos que isso volta VAZIO sem erro — não conclua que o registro não existe. Ver `lionchat://docs/api-conventions` |
|
|
377
380
|
| **Migrar conversas** de uma caixa WhatsApp pra outra (ex.: QR Code → Oficial) | `lionchat_inboxes_inbox_migration_list` (prévia) → `_execute` → acompanhar status | Admin-only e IRREVERSÍVEL: sempre mostre os números da prévia e confirme (seção 7a). Grupos não vão pro canal oficial — ficam na caixa de origem |
|
|
378
381
|
| Qualquer coisa de Ligação WP (Wavoip) | **NÃO HÁ TOOL** — removidas em 2026-07-16 por decisão do dono | Ligação WP é contratada e configurada **manualmente pelo cliente no painel**. O MCP não conecta, não desconecta, não entrega token de discagem nem muda config. Oriente o usuário a fazer pelo painel (Configurações da caixa → Ligação WP). |
|
|
379
382
|
| Restringir agendas que a IA oferece | `lionchat_captain_assistants_update` (`config.booking_event_type_ids: [Int]`) | binding de agenda por cenário NÃO é settable via API |
|
|
@@ -379,6 +379,29 @@ falha silenciosa, sem erro na tela. Conversa se altera por `fields` (+ `labels:
|
|
|
379
379
|
**Multi-termo com E:** `q` aceita String (espaços = AND implícito) ou Array (`q[]=joao&q[]=silva`),
|
|
380
380
|
cap de 5 termos — cada termo precisa bater (cada um mantém seu OR entre campos).
|
|
381
381
|
|
|
382
|
+
**PISO DE 3 LETRAS (novo 2026-08-04) — leia antes de concluir "não existe".**
|
|
383
|
+
|
|
384
|
+
Termo com LETRA precisa de **3 caracteres ou mais**. Termo **só de dígitos** é isento (é assim
|
|
385
|
+
que se busca pelo número da conversa ou do card, e conta nova tem todos com 1-2 dígitos).
|
|
386
|
+
|
|
387
|
+
| Busca | O que acontece |
|
|
388
|
+
|---|---|
|
|
389
|
+
| `q=Bo` | Devolve **vazio**. Não é erro, não é 422 — vem `payload: []` |
|
|
390
|
+
| `q=Bor` | Busca normal |
|
|
391
|
+
| `q=42` | Busca normal (só dígitos, isento) |
|
|
392
|
+
| `q=jo silva` | Vale: basta **um** termo utilizável na frase |
|
|
393
|
+
| `q=zq` + `contact_filters=[...]` | Vazio. O termo curto **invalida a busca inteira**, mesmo com filtro junto |
|
|
394
|
+
|
|
395
|
+
Vale nas CINCO buscas (contato, conversa, mensagem, card e artigo).
|
|
396
|
+
|
|
397
|
+
**Consequência prática:** resultado vazio com termo de 1-2 letras **não significa que o registro
|
|
398
|
+
não existe** — significa que a busca não rodou. Nunca responda "não encontrei esse contato" nessa
|
|
399
|
+
situação. Ou complete o termo, ou pergunte o nome inteiro, ou use `/contacts/filter` com
|
|
400
|
+
`filter_operator: "contains"`, que não tem esse piso.
|
|
401
|
+
|
|
402
|
+
Sem `q` e só com filtros estruturados continua funcionando normalmente (contrato antigo, busca só
|
|
403
|
+
por condições) — o piso só descarta termo de texto curto, não o pedido inteiro.
|
|
404
|
+
|
|
382
405
|
**Busca cadastral:** CPF/CNPJ/RG/endereço/profissão entram na busca de contatos e conversas, com
|
|
383
406
|
match por dígitos que ignora pontuação (`31.104.475/0001-51` == `31104475000151`; mín 3 dígitos).
|
|
384
407
|
Telefone idem. Cards do Kanban são achados pelo contato/conversa vinculados.
|
|
@@ -131,6 +131,32 @@ Pra reativar: `paused=false`. Toggle é auditado (`audited only: [:paused]`).
|
|
|
131
131
|
|
|
132
132
|
O `config` DEVE ser enviado como **objeto** (ex.: `config: { disabled_tools: [...] }`), NUNCA como string/texto. Se vier em formato errado, o backend retorna **422** (não salva ignorando em silêncio). O update do `config` é **merge parcial** — mandar só o subset que muda (ex.: só `disabled_tools`) preserva os demais campos.
|
|
133
133
|
|
|
134
|
+
## AI Agente roteando por TIME (novo 2026-08-03)
|
|
135
|
+
|
|
136
|
+
O AI Agente ganhou 3 ferramentas de time: **Listar Times**, **Mover para Time** e **Tirar do Time**.
|
|
137
|
+
Antes ele só conseguia atribuir uma PESSOA; trocar de time exigia automação ou bloco de fluxo, com
|
|
138
|
+
o time escolhido de antemão por quem montou a regra.
|
|
139
|
+
|
|
140
|
+
**A descrição do time virou peça funcional.** É lendo `teams.description` que a IA decide para onde
|
|
141
|
+
mandar a conversa. Time sem descrição obriga a chumbar o nome no cenário — que é justamente o que
|
|
142
|
+
essas ferramentas vieram resolver.
|
|
143
|
+
|
|
144
|
+
> **Ao criar ou atualizar time (`lionchat_teams_create` / `_update`), preencha `description`
|
|
145
|
+
> dizendo QUANDO mandar para lá.** Ex.: `"Financeiro — cobrança, boleto, nota fiscal, reembolso,
|
|
146
|
+
> segunda via"`. Não é enfeite de tela: é o que a IA lê.
|
|
147
|
+
|
|
148
|
+
Travas que valem conhecer (não dá pra desligar):
|
|
149
|
+
|
|
150
|
+
| Trava | Efeito |
|
|
151
|
+
|---|---|
|
|
152
|
+
| Conta sem nenhum time | As 3 ferramentas nem aparecem para o agente |
|
|
153
|
+
| Alguém está atendendo (`assignee_id` preenchido) | Mover e Tirar **não agem**. Evita a IA arrancar a conversa da mão do atendente |
|
|
154
|
+
| Nome do time no cenário | Resolve por nome exato; não achando, tenta CONTÉM. Se der mais de um candidato, devolve a lista e **não adivinha** |
|
|
155
|
+
| Mover de time | **Não** faz handoff sozinho. Se a intenção é o humano assumir, o cenário precisa mandar chamar o handoff no mesmo turno |
|
|
156
|
+
|
|
157
|
+
`list_teams` é ferramenta de descoberta: fica escondida da tela de ferramentas e só carrega se
|
|
158
|
+
"Mover para Time" estiver ativa. Não tente ligá-la ou desligá-la sozinha em `config.disabled_tools`.
|
|
159
|
+
|
|
134
160
|
## Limite do prompt e cache OpenAI (2026-05-22)
|
|
135
161
|
|
|
136
162
|
- `config.instructions` (system prompt do agente) aceita até **20.000 caracteres** (antes 10k). Acima de 15k, o frontend mostra aviso "lost in the middle" — prefira colocar instruções críticas no início ou final.
|
|
@@ -502,6 +528,20 @@ opcional `variable_mapping` junto.
|
|
|
502
528
|
- Só entram no mapping as que devem auto-preencher; as demais `{{N}}` continuam manuais.
|
|
503
529
|
- O `variable_mapping` é salvo localmente (NÃO vai pra Meta) e usado no momento do envio.
|
|
504
530
|
|
|
531
|
+
**Variável sem mapping tem preço (2026-08-04).** Placeholder que ninguém disse como preencher:
|
|
532
|
+
|
|
533
|
+
1. **Tira o modelo do alcance do AI Agente.** Basta UMA variável sem mapping para o modelo inteiro
|
|
534
|
+
deixar de ser oferecido no follow-up automático fora da janela de 24h.
|
|
535
|
+
2. **Faz o envio manual falhar** com o erro `#132000` da Meta (número de parâmetros não bate).
|
|
536
|
+
|
|
537
|
+
Vale para os dois formatos de marcador: posicional (`{{1}}`) e nomeado (`{{nome_cliente}}`).
|
|
538
|
+
|
|
539
|
+
> Ao registrar modelo por API, **mapeie todas as variáveis do corpo** — ou preencha na hora do envio
|
|
540
|
+
> via `processed_params`. Modelo com variável órfã é modelo que a IA não usa e que o disparo derruba.
|
|
541
|
+
|
|
542
|
+
Confira o que ficou de fora lendo o modelo com `lionchat_inboxes_whatsapp_templates_list` e
|
|
543
|
+
comparando os `{{...}}` do texto do BODY com as chaves do `variable_mapping`.
|
|
544
|
+
|
|
505
545
|
Exemplo — `{{1}}` vira o primeiro nome do contato:
|
|
506
546
|
|
|
507
547
|
```json
|
|
@@ -255,6 +255,33 @@ Conversa resolvida que recebe nova mensagem do cliente:
|
|
|
255
255
|
- Default: cria NOVA conversa (mantém histórico)
|
|
256
256
|
- Se locked: reabre a mesma conversa (`status` volta a 0)
|
|
257
257
|
|
|
258
|
+
### 10. Criar conversa por API — REGRA NOVA (2026-08-04)
|
|
259
|
+
|
|
260
|
+
**Nunca nasce conversa nova se o contato já tem uma ABERTA naquela caixa.** Vale para todo caminho
|
|
261
|
+
iniciado por nós: `lionchat_conversations_create`, campanha, flow, booking, integração.
|
|
262
|
+
|
|
263
|
+
| Situação do contato naquela caixa | O que `conversations_create` devolve |
|
|
264
|
+
|---|---|
|
|
265
|
+
| Tem conversa **aberta / pendente / adiada / silenciada** | A **conversa existente**, com o mesmo `id`. Não cria |
|
|
266
|
+
| Só tem conversa **resolvida** | Cria conversa NOVA (invariante do produto: "fechou = abre nova") |
|
|
267
|
+
| Caixa com `lock_to_single_conversation` LIGADO | **Sempre** a existente, mesmo resolvida — reabre |
|
|
268
|
+
| Caixa de **e-mail** | Sempre cria nova (o assunto da thread vem da conversa; reusar mandaria o e-mail com o assunto velho) |
|
|
269
|
+
|
|
270
|
+
**Como saber se reusou:** compare o `id` devolvido com o que você esperava. Vem HTTP 200 nos dois
|
|
271
|
+
casos, sem aviso. Se precisa garantir conversa nova, feche a anterior antes
|
|
272
|
+
(`conversations_toggle_status` para `resolved`).
|
|
273
|
+
|
|
274
|
+
**O que é DESCARTADO no reuso** (a conversa já existe; o disparo não reescreve o estado dela):
|
|
275
|
+
`status`, `snoozed_until`, `additional_attributes` e `assignee_id`. Se você precisa trocar o
|
|
276
|
+
responsável, chame `conversations_update` depois — não adianta mandar junto na criação.
|
|
277
|
+
|
|
278
|
+
**O que É aproveitado:** `custom_attributes` entram por merge, **sem sobrescrever chave que já tem
|
|
279
|
+
valor**. A conversa mantém a origem com que nasceu e só ganha o que ainda não tinha.
|
|
280
|
+
|
|
281
|
+
**Reuso não dispara `conversation_created`** — automação, gatilho de flow, webhook de saída,
|
|
282
|
+
notificação e a Agenda não rodam. Se o seu fluxo depende de um desses, ele não vai acontecer
|
|
283
|
+
quando houver reuso.
|
|
284
|
+
|
|
258
285
|
## Estado relacional
|
|
259
286
|
|
|
260
287
|
```
|
|
@@ -634,10 +661,41 @@ Todos os formatos abaixo foram conferidos linha a linha em `app/services/action_
|
|
|
634
661
|
| `add_note_to_kanban_item` | `[{"funnel_id": 31, "text": "texto da nota"}]` — a chave e **`text`**, nao `note` |
|
|
635
662
|
| `set_kanban_item_status` | `[{"funnel_id": 31, "status": "won"}]` — `won`, `lost` ou `open`. Status fora disso e ignorado |
|
|
636
663
|
| `start_kanban_item_timer` / `stop_kanban_item_timer` | `[{"funnel_id": 31}]` |
|
|
664
|
+
| `wait` | `[30]` — segundos. Ver "Acao Aguardar" abaixo |
|
|
637
665
|
|
|
638
666
|
**Acoes de Kanban:** todas precisam que a conversa ja tenha um card no funil informado. Sem card,
|
|
639
667
|
a acao e pulada (fica so no log do servidor). Use `create_kanban_item` antes, na mesma regra.
|
|
640
668
|
|
|
669
|
+
### Acao `wait` (Aguardar) — novo 2026-08-04
|
|
670
|
+
|
|
671
|
+
Pausa a regra: as acoes **seguintes** so rodam depois do tempo passar. As anteriores ja rodaram.
|
|
672
|
+
|
|
673
|
+
```json
|
|
674
|
+
{ "action_name": "wait", "action_params": [30] }
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
| Regra | Detalhe |
|
|
678
|
+
|---|---|
|
|
679
|
+
| Unidade | **segundos** |
|
|
680
|
+
| Teto | **300** (5 minutos). Valor maior e limitado a 300 em silencio, sem erro |
|
|
681
|
+
| Formatos aceitos | `[30]`, `30`, `"30"` e `{"seconds": 30}` — todos funcionam |
|
|
682
|
+
| Tempo invalido | `[]`, `[0]`, `[""]` ou ausente = **nao pausa**, a regra segue direto. Nao da erro |
|
|
683
|
+
| Ultima acao da regra | Nao agenda nada (nao ha o que retomar depois) |
|
|
684
|
+
| Pilula "Automacao X disparou" | So aparece na 1a rodada, nao se repete na volta |
|
|
685
|
+
|
|
686
|
+
**Para que serve.** O caso que originou: a regra mandava a mensagem **antes** da politica de
|
|
687
|
+
atribuicao carimbar o responsavel, entao a variavel com o nome do atendente saia vazia. Meio
|
|
688
|
+
segundo de espera resolve. Use quando a acao seguinte depende de algo que outro processo ainda
|
|
689
|
+
esta gravando (atribuicao, card recem-criado, atributo que outra regra vai escrever).
|
|
690
|
+
|
|
691
|
+
**Precisa de mais de 5 minutos?** O lugar certo e o FlowBuilder, que tem espera em horas e sessao
|
|
692
|
+
propria pra sustentar o estado. A automacao nao foi feita pra isso.
|
|
693
|
+
|
|
694
|
+
**A regra nao "dorme":** ao encontrar a espera ela encerra a rodada e agenda a retomada. Varias
|
|
695
|
+
conversas esperam ao mesmo tempo sem travar o atendimento. Na volta, o sistema confere se a regra
|
|
696
|
+
ainda existe e esta ligada, se a conversa ainda existe e se a caixa nao foi excluida — se algo
|
|
697
|
+
disso mudou, ele simplesmente nao retoma.
|
|
698
|
+
|
|
641
699
|
Lista autoritativa de nomes validos: `AutomationRule#actions_attributes` no backend. Nome de acao
|
|
642
700
|
fora dessa lista e recusado com 422 ao salvar — isso a API valida. O que ela **nao** valida e o
|
|
643
701
|
conteudo do `action_params`. `apply_kanban_checklist_template` existe no motor mas **nao** e uma
|
|
@@ -412,14 +412,25 @@ Atributos de sistema no CONTATO (prefixo `eclinica_`, protegidos, usáveis como
|
|
|
412
412
|
| `eclinica_idagenda` | text | ID do último agendamento |
|
|
413
413
|
| `eclinica_data_consulta` | date | Data da consulta, ISO |
|
|
414
414
|
| `eclinica_hora_consulta` | **time** | Hora da consulta 24h `"HH:MM"` (novo 2026-07-06) |
|
|
415
|
+
| `eclinica_hora_final` | **time** | Hora final da consulta (novo 2026-07-27) |
|
|
415
416
|
| `eclinica_status_agendamento` | text | agendado / no_show / atendido / desmarcado |
|
|
416
|
-
| `
|
|
417
|
+
| `eclinica_situacao` | text | Situação crua da agenda (age_situacao do webhook) |
|
|
418
|
+
| `eclinica_compromisso` | text | Tipo da consulta — TEXTO LIVRE da recepção (ex: Consulta, Retorno) |
|
|
419
|
+
| `eclinica_agendatipo` | text | Tipo de Agendamento — NOME da lista fixa do painel, resolvido por unidade (novo 2026-07-28). **Filtrar sempre pelo NOME, nunca pelo número: os números colidem entre filiais** |
|
|
420
|
+
| `eclinica_agendatipo_id` | text | Tipo de Agendamento — número cru (não comparável entre filiais) |
|
|
421
|
+
| `eclinica_profissional` | text | NOME do profissional, resolvido por unidade (novo 2026-07-10) |
|
|
422
|
+
| `eclinica_profissional_id` | text | Número do profissional (não comparável entre filiais) |
|
|
423
|
+
| `eclinica_convenio_id` | text | Convênio (número) |
|
|
424
|
+
| `eclinica_ultimo_evento` | text | Tipo do último webhook recebido (ex: falta, agendamento_novo) |
|
|
417
425
|
| `eclinica_ultimo_pagamento` | text | Valor do último pagamento |
|
|
418
426
|
| `eclinica_ultimo_pagamento_data` | date | Data do último pagamento/baixa (novo 2026-07-06) |
|
|
419
427
|
| `eclinica_ultimo_pagamento_descricao` | text | Descrição da baixa (ex: CONSULTA INICIAL) |
|
|
420
428
|
| `eclinica_laboratorio_data_prevista` | date | Previsão de entrega da medicação (novo 2026-07-23) |
|
|
421
429
|
| `eclinica_laboratorio_data_moldagem` | date | Data do pedido da medicação |
|
|
422
|
-
| `eclinica_laboratorio_data_entrega` | date | Data
|
|
430
|
+
| `eclinica_laboratorio_data_entrega` | date | Data em que a medicação CHEGOU na unidade — é a data que dispara o aviso de retirada do flow |
|
|
431
|
+
| `eclinica_laboratorio_data_retirada` | date | Data em que o paciente RETIROU a medicação (coa_datainstalacao; novo 2026-08-03). NÃO confundir com a entrega. Vazia = peça atual não retirada |
|
|
432
|
+
| `eclinica_laboratorio_trabalho_id` | text | Trabalho/tipo da medicação — número cru (aparelho_id; novo 2026-08-03). Lista própria de cada unidade (COMPRIMIDO/POMADA/SPRAY...); número não comparável entre filiais |
|
|
433
|
+
| `eclinica_laboratorio_trabalho` | text | Trabalho/tipo da medicação — NOME resolvido na lista da própria unidade ("SPRAY", "POMADA"...; novo 2026-08-03). Best-effort: pode ficar vazio se a API da unidade estiver fora do ar. Para filtrar/personalizar flows, use SEMPRE este NOME, nunca o número |
|
|
423
434
|
| `eclinica_laboratorio_situacao` | text | Situação do pedido no laboratório |
|
|
424
435
|
| `eclinica_ultima_cobranca_valor` | text | Valor da última cobrança/carnê gerado |
|
|
425
436
|
| `eclinica_ultima_cobranca_vencimento` | date | Vencimento da última cobrança |
|
|
@@ -115,7 +115,8 @@ Um card individual dentro de uma etapa.
|
|
|
115
115
|
| `funnel_stage` | Chave da etapa (ex: `"novo_lead"`) |
|
|
116
116
|
| `position` | Ordem dentro da etapa |
|
|
117
117
|
| `stage_entered_at` | Quando entrou na etapa atual (pra métrica de tempo) |
|
|
118
|
-
| `conversation_display_id` | Conversa principal vinculada |
|
|
118
|
+
| `conversation_display_id` | Conversa principal vinculada. **O sistema move este ponteiro sozinho (desde 04/08/2026)**: quando nasce uma conversa nova do mesmo contato naquela caixa, o card passa a apontar pra ela. O card é da PESSOA, não do atendimento. **NÃO trate este valor como estável** — releia antes de usar. Enviar `conversation_display_id` num UPDATE de card é ignorado de propósito (senão o reenvio do formulário regravaria o número antigo por cima). |
|
|
119
|
+
| `origin_conversation_display_id` | Conversa em que o card NASCEU (só preenchida se o vínculo já foi movido). É o que o relatório de origem de lead usa, pra uma venda não mudar de mês nem de anúncio quando o card anda. |
|
|
119
120
|
| `linked_conversations` | jsonb array `[{display_id: 123}, {display_id: 456}]` — múltiplas conversas |
|
|
120
121
|
| `item_details` | jsonb (ver abaixo) |
|
|
121
122
|
| `custom_attributes` | jsonb — campos custom (igual contatos) |
|
|
@@ -179,6 +179,61 @@ Feature flag específica (ex: `feature_kanban`, `feature_captain`) está OFF.
|
|
|
179
179
|
|
|
180
180
|
## Cenários problemáticos
|
|
181
181
|
|
|
182
|
+
### "A busca não acha o contato, mas ele existe" (novo 2026-08-04)
|
|
183
|
+
|
|
184
|
+
Primeira coisa a conferir: **o termo tem menos de 3 letras?** Desde 04/08 termo com letra precisa
|
|
185
|
+
de 3 caracteres; abaixo disso a busca é recusada e volta **vazia, sem erro**. Termo só de dígitos
|
|
186
|
+
é isento.
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
q=Bo -> payload: [] (recusado, NÃO significa que não existe)
|
|
190
|
+
q=Bor -> busca normal
|
|
191
|
+
q=42 -> busca normal (dígito é isento)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Vale nas cinco buscas: contato, conversa, mensagem, card e artigo. Um termo curto **invalida a
|
|
195
|
+
busca inteira**, mesmo com filtro estruturado junto.
|
|
196
|
+
|
|
197
|
+
O que fazer: complete o termo, peça o nome inteiro, ou use `lionchat_contacts_filter` com
|
|
198
|
+
`filter_operator: "contains"` — o `/filter` não tem esse piso.
|
|
199
|
+
|
|
200
|
+
**Nunca responda "esse contato não existe" a partir de uma busca de 1-2 letras.**
|
|
201
|
+
|
|
202
|
+
### "Criei uma conversa e voltou o id de uma que já existia" (novo 2026-08-04)
|
|
203
|
+
|
|
204
|
+
É o comportamento novo, não é defeito. Desde 04/08 não nasce conversa nova se o contato já tem uma
|
|
205
|
+
**aberta** naquela caixa — o sistema devolve a existente, com HTTP 200 e sem aviso.
|
|
206
|
+
|
|
207
|
+
- Contato com conversa aberta/pendente/adiada/silenciada → devolve a existente
|
|
208
|
+
- Só conversa resolvida → cria nova
|
|
209
|
+
- Caixa com "conversa única" ligada → sempre a existente, mesmo resolvida
|
|
210
|
+
- Caixa de e-mail → sempre cria nova
|
|
211
|
+
|
|
212
|
+
Se você PRECISA de conversa nova, feche a anterior antes (`conversations_toggle_status` para
|
|
213
|
+
`resolved`). E lembre: no reuso, `assignee_id` e `status` mandados na criação são **descartados** —
|
|
214
|
+
troque depois com `conversations_update`.
|
|
215
|
+
|
|
216
|
+
### "Token de cargo restrito passou a receber 403 em conversa que antes abria" (novo 2026-08-04)
|
|
217
|
+
|
|
218
|
+
Mudança de segurança, não é defeito. Até 04/08 as ações de conversa autorizavam a **CAIXA**, não a
|
|
219
|
+
**conversa** — então qualquer membro da caixa conseguia agir numa conversa que nem consegue abrir.
|
|
220
|
+
As 19 ações do controller de conversa agora conferem a conversa.
|
|
221
|
+
|
|
222
|
+
Na prática, com token de cargo restrito:
|
|
223
|
+
|
|
224
|
+
| Ação | Antes | Agora |
|
|
225
|
+
|---|---|---|
|
|
226
|
+
| `conversations_transcript` (mandar a conversa por e-mail) | Passava em qualquer conversa da caixa | Só nas que o cargo enxerga |
|
|
227
|
+
| Anexos e download do áudio | Idem | Idem |
|
|
228
|
+
| Resolver/reabrir, prioridade, silenciar, marcar não-lida, atributos | Idem | Idem |
|
|
229
|
+
| `conversations_scheduled_messages_list` / `_create` | **Sem autorização nenhuma** | Confere a conversa |
|
|
230
|
+
|
|
231
|
+
Dois acessos continuam valendo de propósito: conversa **órfã** (cuja caixa foi apagada) é de toda a
|
|
232
|
+
conta, e quem tem o **card do Kanban** enxerga a conversa vinculada mesmo sem ser membro da caixa.
|
|
233
|
+
|
|
234
|
+
Se o seu fluxo dependia do comportamento antigo, o caminho é dar acesso à caixa/time certo ao cargo
|
|
235
|
+
— não existe como pedir exceção pela API.
|
|
236
|
+
|
|
182
237
|
### "Estou recebendo 401 mesmo com token correto"
|
|
183
238
|
Possíveis causas:
|
|
184
239
|
- Token foi revogado
|