# Referência dos webhooks

Os quatro eventos, os cabeçalhos de cada entrega e todos os campos do corpo.

## Eventos

Os quatro acontecimentos que podem disparar uma chamada. O valor ao lado de cada nome é o que chega no campo `event`.

### Novo lead

`POST new_lead`

Um lead entrou na sua base, por qualquer canal, e recebeu o primeiro status do funil.

`status.previous` vem `null`, porque não havia etapa anterior. Se o lead acabou de ser criado por um formulário, `formSubmissions` traz esse envio e o evento [Submissão de formulário](https://leaper.com.br/desenvolvedores/webhooks-referencia/#submissao-de-formulario) também é disparado.

Corpo: [Corpo da entrega](https://leaper.com.br/desenvolvedores/webhooks-referencia/#corpo-da-entrega) — a mesma estrutura em todos os eventos.

#### O que responder

- `200` Qualquer resposta `2xx` encerra a entrega. O corpo da sua resposta é ignorado.

**Entrega**

```json
{
  "event": "new_lead",
  "event_id": "7c1f9a40-6b2e-4d58-9f03-85ad1c2e4b71",
  "timestamp": "2026-09-02T09:14:52Z",
  "company": {
    "id": "6201138c-fc0a-4478-820f-8907907e7f00",
    "whatsapp_phone": null
  },
  "lead": {
    "id": "b7d4e1a2-8f3c-4a19-9c62-1e5f0a7d3b84",
    "name": "Marina Alves",
    "phone": "5511987654321",
    "email": null,
    "source": "METAADS_MSG",
    "tags": null,
    "created_at": "2026-09-02 09:14:50",
    "created_from": null,
    "lead_value": null
  },
  "status": {
    "current": {
      "code": "LEAD_START",
      "name": "Novo Lead",
      "changed_at": "2026-09-02 09:14:50"
    },
    "previous": null
  },
  "tracking": {
    "source": "METAADS_MSG",
    "sourceApp": "instagram",
    "sourceUrl": "https://www.instagram.com/",
    "sourceType": "ad",
    "utmSource": null,
    "utmMedium": null,
    "utmCampaign": null,
    "utmContent": null,
    "utmTerm": null,
    "referer": null,
    "pageUrl": null,
    "device": null,
    "browser": null,
    "os": null,
    "ipAddress": null,
    "userAgent": null,
    "country": null,
    "clickId": "ARAaZv8x1QpKm3nLd0TbYq",
    "clickIdType": "ctwa_clid",
    "clickDate": null,
    "campaignData": {
      "campaign": {
        "id": "120212847391740123",
        "name": "Institucional | Setembro"
      },
      "ad": {
        "id": "120212847391750456",
        "name": "Carrossel — Depoimentos"
      }
    },
    "formData": null,
    "journey": null
  },
  "formSubmissions": []
}
```

### Mudança de status

`POST status_change`

Um lead mudou de etapa no funil. Vale para qualquer transição, inclusive as finais.

`status.previous` traz a etapa de onde ele saiu: comparar os dois `code` diz exatamente qual foi a transição. Uma conversão também é uma mudança de status, então quem assina este evento e [Lead convertido](https://leaper.com.br/desenvolvedores/webhooks-referencia/#lead-convertido) recebe duas chamadas.

Corpo: [Corpo da entrega](https://leaper.com.br/desenvolvedores/webhooks-referencia/#corpo-da-entrega) — a mesma estrutura em todos os eventos.

#### O que responder

- `200` Qualquer resposta `2xx` encerra a entrega. O corpo da sua resposta é ignorado.

**Entrega**

```json
{
  "event": "status_change",
  "event_id": "2f84c7d1-90ab-4e36-bc5f-1d70e9a3c852",
  "timestamp": "2026-09-02T15:41:07Z",
  "company": {
    "id": "6201138c-fc0a-4478-820f-8907907e7f00",
    "whatsapp_phone": null
  },
  "lead": {
    "id": "b7d4e1a2-8f3c-4a19-9c62-1e5f0a7d3b84",
    "name": "Marina Alves",
    "phone": "5511987654321",
    "email": "marina.alves@exemplo.com.br",
    "source": "METAADS_MSG",
    "tags": "prioridade-alta",
    "created_at": "2026-09-02 09:14:50",
    "created_from": null,
    "lead_value": "3200"
  },
  "status": {
    "current": {
      "code": "NEGOCIACAO",
      "name": "Negociação",
      "changed_at": "2026-09-02 15:41:05"
    },
    "previous": {
      "code": "PROPOSTA_ENVIADA",
      "name": "Proposta Enviada",
      "changed_at": "2026-09-02 11:22:18"
    }
  },
  "tracking": {
    "source": "METAADS_MSG",
    "sourceApp": "instagram",
    "sourceUrl": "https://www.instagram.com/",
    "sourceType": "ad",
    "utmSource": null,
    "utmMedium": null,
    "utmCampaign": null,
    "utmContent": null,
    "utmTerm": null,
    "referer": null,
    "pageUrl": null,
    "device": null,
    "browser": null,
    "os": null,
    "ipAddress": null,
    "userAgent": null,
    "country": null,
    "clickId": "ARAaZv8x1QpKm3nLd0TbYq",
    "clickIdType": "ctwa_clid",
    "clickDate": null,
    "campaignData": {
      "campaign": {
        "id": "120212847391740123",
        "name": "Institucional | Setembro"
      },
      "ad": {
        "id": "120212847391750456",
        "name": "Carrossel — Depoimentos"
      }
    },
    "formData": null,
    "journey": null
  },
  "formSubmissions": []
}
```

### Lead convertido

`POST lead_converted`

Um lead chegou à etapa de conversão, `END_WON`. É a venda ganha isolada das outras transições, para tratar conversão sem inspecionar código de etapa.

A estrutura é a de uma mudança de status. Marca a **entrada** em `END_WON`: um lead que já estava convertido e é salvo de novo no mesmo status não dispara o evento outra vez.

Corpo: [Corpo da entrega](https://leaper.com.br/desenvolvedores/webhooks-referencia/#corpo-da-entrega) — a mesma estrutura em todos os eventos.

#### O que responder

- `200` Qualquer resposta `2xx` encerra a entrega. O corpo da sua resposta é ignorado.

**Entrega**

```json
{
  "event": "lead_converted",
  "event_id": "9b35e0c7-4a1d-4f82-b6e9-3c08d7152fa4",
  "timestamp": "2026-09-03T10:08:33Z",
  "company": {
    "id": "6201138c-fc0a-4478-820f-8907907e7f00",
    "whatsapp_phone": null
  },
  "lead": {
    "id": "b7d4e1a2-8f3c-4a19-9c62-1e5f0a7d3b84",
    "name": "Marina Alves",
    "phone": "5511987654321",
    "email": "marina.alves@exemplo.com.br",
    "source": "METAADS_MSG",
    "tags": "prioridade-alta",
    "created_at": "2026-09-02 09:14:50",
    "created_from": null,
    "lead_value": "3200"
  },
  "status": {
    "current": {
      "code": "END_WON",
      "name": "Finalizado - Convertido",
      "changed_at": "2026-09-03 10:08:31"
    },
    "previous": {
      "code": "NEGOCIACAO",
      "name": "Negociação",
      "changed_at": "2026-09-02 15:41:05"
    }
  },
  "tracking": {
    "source": "METAADS_MSG",
    "sourceApp": "instagram",
    "sourceUrl": "https://www.instagram.com/",
    "sourceType": "ad",
    "utmSource": null,
    "utmMedium": null,
    "utmCampaign": null,
    "utmContent": null,
    "utmTerm": null,
    "referer": null,
    "pageUrl": null,
    "device": null,
    "browser": null,
    "os": null,
    "ipAddress": null,
    "userAgent": null,
    "country": null,
    "clickId": "ARAaZv8x1QpKm3nLd0TbYq",
    "clickIdType": "ctwa_clid",
    "clickDate": null,
    "campaignData": null,
    "formData": null,
    "journey": null
  },
  "formSubmissions": []
}
```

### Submissão de formulário

`POST form_submission`

Um formulário foi enviado, seja por um contato novo ou por alguém que já estava na base.

`formSubmissions` traz **todos** os envios daquele lead, do mais recente para o mais antigo — o primeiro item é sempre o que gerou a chamada. Aqui o bloco `status` é só contexto: diz em que etapa o lead está agora, e `previous` vem `null` mesmo que ele já tenha mudado de etapa antes. Quando o envio cria o lead, `status.current` é a primeira etapa do funil e o evento [Novo lead](https://leaper.com.br/desenvolvedores/webhooks-referencia/#novo-lead) também é disparado.

Corpo: [Corpo da entrega](https://leaper.com.br/desenvolvedores/webhooks-referencia/#corpo-da-entrega) — a mesma estrutura em todos os eventos.

#### O que responder

- `200` Qualquer resposta `2xx` encerra a entrega. O corpo da sua resposta é ignorado.

**Entrega**

```json
{
  "event": "form_submission",
  "event_id": "4d7a2b85-1ce6-49f0-83b7-62ca0fd91e37",
  "timestamp": "2026-09-02T14:23:11Z",
  "company": {
    "id": "6201138c-fc0a-4478-820f-8907907e7f00",
    "whatsapp_phone": null
  },
  "lead": {
    "id": "3c81f60d-92a4-4e77-b0d3-6a7e2f10c948",
    "name": "Rafael Nogueira",
    "phone": "5511912345678",
    "email": "rafael.nogueira@exemplo.com.br",
    "source": "GOOGLE_SITE",
    "tags": null,
    "created_at": "2026-08-26 10:12:38",
    "created_from": "forms",
    "lead_value": "1800"
  },
  "status": {
    "current": {
      "code": "NEGOCIACAO",
      "name": "Negociação",
      "changed_at": "2026-08-31 16:05:22"
    },
    "previous": null
  },
  "tracking": {
    "source": "GOOGLE_SITE",
    "sourceApp": null,
    "sourceUrl": null,
    "sourceType": null,
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "23937613327",
    "utmContent": null,
    "utmTerm": "clinica odontologica sp",
    "referer": "https://www.google.com/",
    "pageUrl": "https://exemplo.com.br/unidades",
    "device": "mobile",
    "browser": "Chrome",
    "os": "Android",
    "ipAddress": "177.45.200.13",
    "userAgent": "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 Chrome/128 Mobile Safari/537.36",
    "country": "BR",
    "clickId": "Cj0KCQjwtM3HBhDCARIsAIsw0",
    "clickIdType": "gclid",
    "clickDate": "2026-08-26 10:09:51",
    "campaignData": null,
    "formData": {
      "formId": "a15d3c92-77b8-4f01-9e64-2d8b5c0af731",
      "formName": "Agendamento — Landing Setembro",
      "formSessionId": "ls_8f21c47b90e3",
      "submittedAt": "2026-09-02 14:23:09"
    },
    "journey": null
  },
  "formSubmissions": [
    {
      "form_name": "Agendamento — Landing Setembro",
      "answers": [
        {
          "field": "nome",
          "label": "Nome completo",
          "value": "Rafael Nogueira"
        },
        {
          "field": "telefone",
          "label": "WhatsApp",
          "value": "11912345678"
        },
        {
          "field": "unidade",
          "label": "Unidade preferida",
          "value": "Pinheiros"
        }
      ],
      "tracking": {
        "utm_source": "google",
        "utm_medium": "cpc",
        "utm_campaign": "23937613327",
        "gclid": "Cj0KCQjwtM3HBhDCARIsAIsw0",
        "page_url": "https://exemplo.com.br/unidades"
      },
      "submitted_at": "2026-09-02 14:23:09"
    }
  ]
}
```

## Cabeçalhos

Acompanham toda entrega. Cabeçalhos extras cadastrados no painel vêm junto, e estes três não podem ser sobrescritos.

| Campo | Tipo | Descrição |
|---|---|---|
| `Content-Type` | texto | Sempre `application/json`. |
| `X-Webhook-Event` | texto | Nome do evento que gerou a chamada. Permite rotear sem abrir o corpo. |
| `X-Webhook-Signature` | texto | `sha256=` seguido do HMAC-SHA256 do corpo, em hexadecimal, calculado com o secret do webhook. Ausente apenas se o webhook não tiver secret. |

## Objetos

Formato dos blocos do corpo. Qualquer campo pode vir `null` quando o dado não existe para aquele lead.

### Corpo da entrega

Mesma estrutura em todos os eventos. O que muda é o valor de `event` e quais blocos vêm preenchidos.

| Campo | Tipo | Descrição |
|---|---|---|
| `event` | texto | Nome do evento que gerou a chamada. Valores: `new_lead`, `status_change`, `lead_converted`, `form_submission`. |
| `event_id` | texto (uuid) | Identificador desta entrega. Repete nas retentativas da mesma entrega, então é por ele que se descarta o que já foi processado. |
| `timestamp` | texto | Momento em que o corpo foi montado, em UTC. |
| `company` | objeto ([Empresa](https://leaper.com.br/desenvolvedores/webhooks-referencia/#empresa)) |  |
| `lead` | objeto ([Lead](https://leaper.com.br/desenvolvedores/webhooks-referencia/#lead)) | Dados de contato e origem do lead, no estado em que ele está no momento do envio. |
| `status` | objeto ([Status](https://leaper.com.br/desenvolvedores/webhooks-referencia/#status)) | A etapa que o lead ocupa e de onde veio. Os códigos das etapas intermediárias são configuráveis por empresa; `END_WON` e `END_LOST` existem em todas. |
| `tracking` | objeto ([Atribuição](https://leaper.com.br/desenvolvedores/webhooks-referencia/#atribuicao)) | Origem consolidada do lead: campanha, UTMs, dispositivo e página. Qualquer campo vem `null` quando o dado não foi capturado. |
| `formSubmissions` | lista de objetos ([Envio de formulário](https://leaper.com.br/desenvolvedores/webhooks-referencia/#envio-de-formulario)) | Formulários que este lead já enviou, do mais recente para o mais antigo. Lista vazia quando não houver. |

### Empresa

| Campo | Tipo | Descrição |
|---|---|---|
| `id` | texto (uuid) | Identificador da empresa dona do lead. |
| `whatsapp_phone` | texto ou null | Reservado para uso futuro. Hoje chega sempre `null`. |

### Lead

Dados de contato e origem do lead, no estado em que ele está no momento do envio.

| Campo | Tipo | Descrição |
|---|---|---|
| `id` | texto (uuid) | Identificador do lead na Leaper. Não muda; use como chave no seu sistema. |
| `name` | texto ou null | Nome do contato. |
| `phone` | texto ou null | Telefone com código do país, só dígitos. |
| `email` | texto ou null | E-mail do contato. |
| `source` | texto ([Origem do lead](https://leaper.com.br/desenvolvedores/webhooks-referencia/#origem-do-lead)) | Valores possíveis de `source`. Leads antigos podem ter valores fora desta lista. |
| `tags` | texto ou null | Tags do lead, em texto. |
| `created_at` | texto ou null | Quando o lead entrou na Leaper. |
| `created_from` | texto ou null | Canal de entrada, como `whatsapp`, `forms`, `external_api` ou `manual`. |
| `lead_value` | texto ou número ou null | Valor do lead, como foi informado. Costuma chegar como texto. |

### Status

A etapa que o lead ocupa e de onde veio. Os códigos das etapas intermediárias são configuráveis por empresa; `END_WON` e `END_LOST` existem em todas.

| Campo | Tipo | Descrição |
|---|---|---|
| `current` | objeto ([Etapa do funil](https://leaper.com.br/desenvolvedores/webhooks-referencia/#etapa-do-funil)) |  |
| `previous` | objeto ([Etapa do funil](https://leaper.com.br/desenvolvedores/webhooks-referencia/#etapa-do-funil)) ou null | Mesma estrutura, referente à etapa anterior. `null` quando não havia etapa anterior ou quando o evento não descreve uma transição. |

### Etapa do funil

| Campo | Tipo | Descrição |
|---|---|---|
| `code` | texto ou null | Código da etapa. É o campo estável para lógica no seu sistema, mas muda se a etapa for renomeada no painel — exceto `END_WON` e `END_LOST`. |
| `name` | texto ou null | Nome da etapa como aparece no painel. |
| `changed_at` | texto ou null | Quando o lead entrou nesta etapa, no horário de Brasília. |

### Atribuição

Origem consolidada do lead: campanha, UTMs, dispositivo e página. Qualquer campo vem `null` quando o dado não foi capturado.

| Campo | Tipo | Descrição |
|---|---|---|
| `source` | texto ([Origem do lead](https://leaper.com.br/desenvolvedores/webhooks-referencia/#origem-do-lead)) | Valores possíveis de `source`. Leads antigos podem ter valores fora desta lista. |
| `sourceApp` | texto ou null | Aplicativo de onde a conversa nasceu, quando veio de anúncio. Ex.: `instagram`, `facebook`. |
| `sourceUrl` | texto ou null | Endereço de onde o clique partiu. |
| `sourceType` | texto ou null | Natureza da origem, quando identificada. Ex.: `ad`. |
| `utmSource` | texto ou null | UTM `source` consolidado do clique que originou o lead. |
| `utmMedium` | texto ou null | UTM `medium`. |
| `utmCampaign` | texto ou null | UTM `campaign`. Em Google Ads costuma ser o id numérico da campanha. |
| `utmContent` | texto ou null | UTM `content`. |
| `utmTerm` | texto ou null | UTM `term`. |
| `referer` | texto ou null | Página que encaminhou o visitante. |
| `pageUrl` | texto ou null | Página em que o clique ou o envio aconteceu. |
| `device` | texto ou null | Tipo de dispositivo. Ex.: `mobile`, `desktop`. |
| `browser` | texto ou null | Navegador do visitante. |
| `os` | texto ou null | Sistema operacional do visitante. |
| `ipAddress` | texto ou null | IP do visitante no momento da captura. |
| `userAgent` | texto ou null | User agent do visitante no momento da captura. |
| `country` | texto ou null | País do visitante, em duas letras. |
| `clickId` | texto ou null | Identificador do clique fornecido pela plataforma de anúncio. |
| `clickIdType` | texto ou null | Qual identificador é esse. Ex.: `gclid`, `ctwa_clid`, `gbraid`. |
| `clickDate` | texto ou null | Momento do clique. |
| `campaignData` | objeto ou null | Campanha, conjunto e anúncio de origem, quando identificados. O conteúdo varia conforme a plataforma, então leia por chave em vez de assumir um formato fixo. |
| `formData` | objeto ([Formulário de origem](https://leaper.com.br/desenvolvedores/webhooks-referencia/#formulario-de-origem)) ou null | Resumo do formulário que originou o lead. |
| `journey` | lista de textos ou null | Páginas percorridas antes da conversão, quando o rastreamento do site está ativo. |

### Formulário de origem

| Campo | Tipo | Descrição |
|---|---|---|
| `formId` | texto ou null | Identificador do formulário. |
| `formName` | texto ou null | Nome do formulário. |
| `formSessionId` | texto ou null | Identificador da sessão de preenchimento. |
| `submittedAt` | texto ou null | Quando o formulário foi enviado. |

### Envio de formulário

| Campo | Tipo | Descrição |
|---|---|---|
| `form_name` | texto ou null | Nome do formulário. |
| `answers` | lista de objetos | Respostas enviadas. Cada item traz o campo, o rótulo exibido e o valor. |
| `answers[].field` | texto ou null | Nome técnico do campo. |
| `answers[].label` | texto ou null | Rótulo exibido no formulário. |
| `answers[].value` | texto ou número ou booleano ou null | Valor preenchido. |
| `tracking` | objeto ou null | Parâmetros capturados na página no momento do envio, com os nomes como vieram da URL. Ex.: `utm_source`, `gclid`, `page_url`. |
| `submitted_at` | texto ou null | Quando o formulário foi enviado. |

### Origem do lead

Valores possíveis de `source`. Leads antigos podem ter valores fora desta lista.

| Valor | Descrição |
|---|---|
| `PHONE` | Contato por telefone. |
| `EMAIL` | Contato por e-mail. |
| `WEBSITE` | Visita ao site sem campanha identificada. |
| `WHATSAPP` | Conversa de WhatsApp sem anúncio na origem. |
| `WHATSAPPBOT` | Conversa iniciada por bot de WhatsApp. |
| `METAADS_MSG` | Anúncio do Meta que abre conversa no WhatsApp ou Instagram. |
| `METAADS_SITE` | Anúncio do Meta que leva ao site. |
| `GOOGLE_SITE` | Anúncio do Google que leva ao site. |
| `TIKTOK_ADS` | Anúncio do TikTok. |
| `GOOGLE_ORGANIC` | Busca orgânica no Google. |
| `INSTAGRAM_ORGANIC` | Tráfego orgânico do Instagram. |
| `TIKTOK_ORGANIC` | Tráfego orgânico do TikTok. |
| `FACEBOOK_ORGANIC` | Tráfego orgânico do Facebook. |
| `YOUTUBE_ORGANIC` | Tráfego orgânico do YouTube. |
| `NO_TRACKING` | Sem dados de rastreamento. |
