Como mover um negócio de funil pela API do Bitrix24 e extrair a conversa do Open Lines?

crm.deal.update não troca o funil do Bitrix24 e responde sucesso. Use crm.item.update. E a conversa do Open Lines só aparece com ACTIVE_ONLY=N.

Pedro Henrique Quadroatualizado em 4 min de leitura

No Bitrix24, crm.deal.update não troca o negócio de funil: a documentação manda usar crm.item.update para isso, e no meu teste a chamada com a troca respondeu result: true e o funil continuou o mesmo. Para mover, use crm.item.update com entityTypeId=2, categoryId e stageId. Para ler a conversa de WhatsApp (canal aberto, o Open Lines) ligada a um negócio, chame imopenlines.crm.chat.get com ACTIVE_ONLY=N e depois im.dialog.messages.get. Sem esse parâmetro, o retorno vem vazio e parece que o negócio não tem conversa.

O que a documentação diz

Conferi o repositório oficial da documentação REST do Bitrix24 em 10 de outubro de 2026.

  • crm.item.update aceita entityTypeId (para negócio, o valor é 2), categoryId (o funil, que a documentação chama de direção) e stageId. Para a etapa, a página manda consultar crm.status.list com o filtro DEAL_STAGE no funil geral ou DEAL_STAGE_{categoryId} nos demais.
  • Na página de crm.deal.update, a etapa é STAGE_ID, com o mesmo critério de consulta. A página não lista CATEGORY_ID entre os campos e diz: para trocar o funil do negócio, use crm.item.update com entityTypeId igual a 2. Que ele aceite o campo e o ignore com result: true não está documentado; é o que medi.
  • imopenlines.crm.chat.get recebe CRM_ENTITY_TYPE (lead, deal, company ou contact), CRM_ENTITY e ACTIVE_ONLY. O padrão de ACTIVE_ONLY é Y, que devolve só chats ativos. Com N, devolve todos.
  • im.dialog.messages.get recebe DIALOG_ID no formato chatXXX, LIMIT (padrão 20, máximo 50), LAST_ID (mensagens mais antigas) e FIRST_ID (mais novas). A página diz que o método devolve mensagens, inclusive as do sistema, e que quem executa precisa ser participante do chat. Para canal aberto sem participar, a página aponta imopenlines.session.history.get.

O que vi em produção

Mover de funil. Um agente de IA de atendimento qualificava leads e devia passá-los ao funil dos representantes. Os leads nunca chegavam lá. O nó chamava crm.deal.update com a troca de funil, a API respondia sucesso e o negócio ficava onde estava. No meu teste, o campo do funil não pode ser alterado depois da criação do negócio por esse método: só crm.deal.add o define. O crm.deal.update só muda a etapa dentro do funil atual. Migrei o nó para crm.item.update em 15 de junho de 2026 e os leads passaram a chegar.

POST crm.item.update
entityTypeId=2
id=<id do negócio>
fields[categoryId]=<id do funil de destino>
fields[stageId]=C<id do funil>:<ETAPA>

Em funil que não é o geral, o identificador da etapa leva o prefixo C e o número do funil, por exemplo C4:PREPARATION. Na documentação, as etapas saem de crm.status.list com ENTITY_ID igual a DEAL_STAGE_{categoryId}; eu usava crm.dealcategory.stage.list, que não conferi na documentação atual.

Extrair a conversa. Fiz isso para auditar dezenas de atendimentos de um agente de IA, em 21 de julho de 2026. O primeiro passo, imopenlines.crm.chat.get sem ACTIVE_ONLY, devolvia lista vazia para negócios com conversa, e eu cheguei a concluir que não dava para ler o histórico. O parâmetro ACTIVE_ONLY=N resolveu. Com o CHAT_ID, chamei im.dialog.messages.get com DIALOG_ID=chat<CHAT_ID> e LIMIT=200, por um webhook de entrada, e não recebi erro. A documentação fixa o máximo em 50, então prefira LIMIT=50 e pagine com LAST_ID. A documentação exige participação no chat, e no meu uso por webhook retornou as mensagens do mesmo jeito. A alternativa documentada é imopenlines.session.history.get; o identificador da sessão eu tirei de crm.activity.list com PROVIDER_ID=IMOPENLINES_SESSION, o que é do meu teste.

Para saber quem falou, não funcionou user.get: pelo webhook voltou zerado, por falta de escopo. Usei os campos de users[] que vêm junto das mensagens. A documentação lista bot, connector e external_auth_id entre os campos de users; o significado dos valores é do meu teste: external_auth_id igual a bot marcava o agente, imconnector marcava o lead, e author_id igual a 0 é evento de canal, que não é fala de ninguém. Esses eventos eram 40% das mensagens.

Por que a memória do agente não serve de fonte

O agente guardava o histórico no próprio banco, e a primeira ideia foi usar isso. Não serve: só grava o que passou pelo agente. Ficam de fora a mensagem de boas-vindas, os eventos de canal e tudo o que um atendente humano escreveu. No mesmo recorte, o banco do agente tinha menos de um quarto das mensagens que o Open Lines e cobria bem menos conversas.

O que fazer

  1. Para trocar de funil, use crm.item.update, com categoryId em camelCase e a etapa com o prefixo do funil. Depois da chamada, releia o negócio e confira o funil. Não confie no result: true.
  2. Para ler conversas, passe ACTIVE_ONLY=N e trate lista vazia como "não sei", não como "sem conversa".
  3. Para auditar atendimento de IA, use o Open Lines como fonte, nunca a memória do agente.
  4. Ao classificar as mensagens, separe lead, agente, atendente e evento de canal antes de contar.

Se você precisa ligar o CRM a atendimento e a anúncios, veja vendas e CRM com IA.

Fontes

  1. Bitrix24 REST: crm.item.update (categoryId, stageId e entityTypeId)
  2. Bitrix24 REST: crm.deal.update (STAGE_ID e o filtro de etapas por funil)
  3. Bitrix24 REST: imopenlines.crm.chat.get (ACTIVE_ONLY, padrão Y)
  4. Bitrix24 REST: im.dialog.messages.get (DIALOG_ID chatXXX, LIMIT, FIRST_ID)
Pedro Henrique QuadroEngenheiro de software e IA. Constrói aplicativos, sistemas, painéis e agentes de IA em produção, e tem código aceito no Supabase, no Kestra e no QuestDB.

Continue lendo