Skip to main content

Visão Geral

O webhook de Mudança de Etapa é disparado pela Morada.ai sempre que um deal avança ou retrocede no funil de vendas. O payload inclui dados completos do deal, contato, produto, origem e um resumo da conversa gerado por IA.
Se a opção shouldSendOnlyOnDealTransfer estiver ativada, o webhook será enviado apenas quando o deal for transferido para atendimento humano — ignorando mudanças intermediárias de etapa.

Payload

{
  "deal": {
    "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "status": "active",
    "stageCode": "deal_transferred",
    "name": "João Silva - Apt 302 Torre A",
    "conversationId": "f1e2d3c4-5678-90ab-cdef-1234567890ab",
    "partnerId": "b2c3d4e5-6789-01ab-cdef-2345678901bc"
  },
  "person": {
    "id": "c3d4e5f6-7890-12ab-cdef-3456789012cd",
    "name": "João Silva",
    "email": "joao.silva@email.com",
    "phone": "5511999999999"
  },
  "product": {
    "id": "d4e5f6a7-8901-23ab-cdef-4567890123de",
    "name": "Edifício Aurora - Torre A"
  },
  "source": {
    "id": "e5f6a7b8-9012-34ab-cdef-5678901234ef",
    "code": "whatsapp",
    "name": "WhatsApp - Site"
  },
  "conversationReport": "O lead demonstrou interesse no apartamento de 2 quartos com suíte. Informou renda familiar de R$ 15.000 e tem aprovação de crédito prévia. Solicitou agendamento de visita para o final de semana.",
  "appointmentDate": "17-05-2026 14:30",
  "metadata": {
    "timestamp": "2026-05-13T18:30:00.000Z",
    "eventType": "deal_stage_change",
    "stageId": "f6a7b8c9-0123-45ab-cdef-6789012345f0"
  }
}

Campos

deal

CampoTipoDescrição
deal.idstringID único do deal
deal.statusstringStatus atual: active, won, lost
deal.stageCodestringCódigo da etapa atual no funil
deal.namestringNome do deal
deal.conversationIdstring | nullID da conversa associada
deal.partnerIdstringID do parceiro

person

CampoTipoDescrição
person.idstringID único do contato
person.namestring | nullNome completo
person.emailstring | nullE-mail
person.phonestring | nullTelefone com DDI (ex: 5511999999999)

product

O campo product só é enviado quando o deal possui um produto/empreendimento associado.
CampoTipoDescrição
product.idstringID do produto/empreendimento
product.namestringNome do produto/empreendimento

source

CampoTipoDescrição
source.idstringID da origem
source.codestringCódigo da origem (ex: whatsapp, instagram, web)
source.namestringNome descritivo da origem

Outros campos

CampoTipoDescrição
conversationReportstring | nullResumo da conversa gerado por IA — contém os principais pontos discutidos, dados coletados e intenções identificadas
appointmentDatestring | nullData do agendamento associado, se houver. Formato: dd-MM-yyyy HH:mm (horário de Brasília)
metadata.timestampstringData/hora do envio do webhook (ISO 8601)
metadata.eventTypestringSempre "deal_stage_change"
metadata.stageIdstringID da nova etapa no funil

Exemplo de uso

app.post("/webhook/morada", (req, res) => {
  const { deal, person, conversationReport, metadata } = req.body;

  console.log(`Deal ${deal.id} movido para etapa ${deal.stageCode}`);
  console.log(`Contato: ${person.name} (${person.phone})`);

  if (conversationReport) {
    // Salvar resumo da conversa no seu CRM
    console.log(`Resumo IA: ${conversationReport}`);
  }

  res.status(200).json({ received: true });
});

Resposta esperada

Retorne um status HTTP 200 para confirmar o recebimento:
{
  "received": true
}
Se o seu endpoint retornar um status diferente de 2xx ou não responder dentro do timeout, a Morada.ai poderá tentar reenviar o evento. Implemente idempotência para lidar com entregas duplicadas.