> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vistum.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Eventos

> Lista de todos os eventos que o Vistum pode enviar para o seu webhook.

## Eventos disponíveis

| Evento                | Disparado quando                                                  |
| --------------------- | ----------------------------------------------------------------- |
| `lead.created`        | Um novo lead é criado via API (`POST /api/v1/leads`)              |
| `contact.created`     | Um novo contato chega pelo WhatsApp                               |
| `contact.updated`     | Dados de um contato são atualizados (nome, email, telefone, etc.) |
| `message.received`    | Uma mensagem é recebida de um contato                             |
| `contact.tag_added`   | Uma tag é adicionada a um contato                                 |
| `contact.tag_removed` | Uma tag é removida de um contato                                  |
| `card.created`        | Um card (negócio) é criado em um pipeline                         |
| `card.moved`          | Um card é movido entre etapas do pipeline                         |
| `card.won`            | Um card é marcado como ganho                                      |
| `card.lost`           | Um card é marcado como perdido                                    |

<Note>
  O evento `test.ping` é enviado pelo botão **Ping** nas configurações. Não aparece no histórico de deliveries como evento de negócio.
</Note>

***

## Estrutura do payload

Toda requisição de webhook tem a seguinte estrutura base. Os campos do evento são incluídos **diretamente no objeto raiz** — não há um envelope `"data"` separado.

```json theme={null}
{
  "event": "lead.created",
  "workspace_id": "wks_abc123",
  "timestamp": "2025-05-07T14:30:00.000Z",
  "contact_id": "cnt_def456",
  "name": "João Ferreira",
  "phone": "5511999887766",
  "email": "joao@empresa.com"
}
```

Os headers incluem:

```http theme={null}
X-Vistum-Event: lead.created
X-Vistum-Delivery: whk_xyz789
X-Vistum-Signature: t=1746666000,v1=a1b2c3d4e5f6...
Content-Type: application/json
User-Agent: Vistum-Webhooks/1.0
```

<Note>
  O campo de identificação do workspace é `workspace_id` (snake\_case), não `workspaceId`.
</Note>

***

## Detalhes por evento

### lead.created

Disparado quando um novo contato é criado via `POST /api/v1/leads`.

```json theme={null}
{
  "event": "lead.created",
  "workspace_id": "wks_abc123",
  "timestamp": "2025-05-07T14:30:00.000Z",
  "contact_id": "cnt_def456",
  "name": "João Ferreira",
  "phone": "5511999887766",
  "email": "joao@empresa.com"
}
```

***

### contact.created

Disparado quando um contato novo é criado manualmente no CRM.

```json theme={null}
{
  "event": "contact.created",
  "workspace_id": "wks_abc123",
  "timestamp": "2025-05-07T14:30:00.000Z",
  "contact_id": "cnt_ghi789",
  "name": "Maria Costa",
  "phone": "5521988776655",
  "email": null
}
```

***

### contact.updated

Disparado quando os dados de um contato são atualizados via painel do CRM (nome, email, telefone, observações, etc.).

```json theme={null}
{
  "event": "contact.updated",
  "workspace_id": "wks_abc123",
  "timestamp": "2026-05-08T15:30:00.000Z",
  "contact_id": "cnt_ghi789",
  "contact_name": "João Silva",
  "phone": "5511999887766",
  "email": "joao@empresa.com"
}
```

<Note>
  O webhook só é emitido em uma atualização **humana** da ficha do contato (`PUT /chat/contacts/[id]`). A ação de automação *atualizar contato* escreve direto no banco (`prisma.update`) e **não** passa pelo emissor — portanto não dispara `contact.updated`. Isso evita loops entre automações.
</Note>

<Note>
  **`changedFields` e o gatilho de automação.** O *payload do webhook outbound* acima **não** inclui a lista de campos alterados. No entanto, o **gatilho de automação** equivalente ("Contato atualizado" / `contact_updated`) recebe internamente a variável `changedFields` — uma lista separada por vírgula com os campos que realmente mudaram, dentre: `name`, `email`, `phone`, `notes`, `tags`. O gatilho só dispara quando `changedFields.length > 0` (mudança real; PUT no-op é ignorado) e aceita um filtro opcional `fields` que só deixa passar quando um dos campos escolhidos mudou. Se você precisar dos campos alterados em um fluxo externo, use o gatilho de automação + ação *Enviar webhook* com o body customizado, não o webhook outbound padrão.
</Note>

***

### message.received

Disparado quando uma mensagem inbound é recebida de um contato — via WhatsApp Evolution API ou WhatsApp Cloud API.

<Note>
  Apenas mensagens recebidas de contatos reais (não grupos, não mensagens enviadas pelo agente). O payload não inclui o conteúdo da mensagem por privacidade — use o `message_id` para buscá-la via API se necessário.
</Note>

```json theme={null}
{
  "event": "message.received",
  "workspace_id": "wks_abc123",
  "timestamp": "2026-05-08T12:00:00.000Z",
  "contact_id": "cnt_ghi789",
  "contact_name": "João Silva",
  "phone": "5511999887766",
  "message_id": "3EB0123456789ABCDEF0",
  "type": "text",
  "instance_id": "inst_xyz123",
  "conversation_id": "conv_abc456"
}
```

O campo `type` indica o tipo da mensagem:

| Valor             | Descrição                 |
| ----------------- | ------------------------- |
| `text`            | Mensagem de texto simples |
| `imageMessage`    | Imagem                    |
| `audioMessage`    | Áudio                     |
| `videoMessage`    | Vídeo                     |
| `documentMessage` | Documento                 |
| `stickerMessage`  | Sticker                   |

***

### contact.tag\_added

Disparado quando uma tag é adicionada a um contato — via painel, automação, API ou middleware.

```json theme={null}
{
  "event": "contact.tag_added",
  "workspace_id": "wks_abc123",
  "timestamp": "2026-05-08T00:20:19.000Z",
  "contact_id": "cnt_xyz789",
  "contact_name": "João Silva",
  "phone": "5511999887766",
  "tag": {
    "id": "tag_abc123",
    "name": "Lead Qualificado"
  },
  "source": "manual"
}
```

O campo `source` indica a origem da adição:

| Valor        | Origem                                      |
| ------------ | ------------------------------------------- |
| `manual`     | Painel do CRM (ContactPanel)                |
| `automation` | Nó add\_tag em automação                    |
| `api`        | API externa (`/api/v1/leads` ou middleware) |
| `import`     | Importação em lote                          |

***

### contact.tag\_removed

Disparado quando uma tag é removida de um contato — via painel, automação ou API.

```json theme={null}
{
  "event": "contact.tag_removed",
  "workspace_id": "wks_abc123",
  "timestamp": "2026-05-08T15:30:00.000Z",
  "contact_id": "cnt_xyz789",
  "contact_name": "João Silva",
  "phone": "5511999887766",
  "tag": {
    "id": "tag_abc123",
    "name": "Lead Qualificado"
  },
  "source": "manual"
}
```

O campo `source` tem os mesmos valores de `contact.tag_added` (`manual`, `automation`, `api`, `import`).

***

### card.created

Disparado quando um card (negócio) é adicionado a um pipeline — pelo Kanban, pela ficha do contato, por formulário ou pela API.

```json theme={null}
{
  "event": "card.created",
  "workspace_id": "wks_abc123",
  "timestamp": "2025-05-07T14:30:00.000Z",
  "card_id": "card_mno345",
  "stage_id": "stage_stu901",
  "pipeline_id": "pipe_pqr678",
  "contact_id": "cnt_ghi789",
  "name": "João Ferreira"
}
```

<Note>
  O gatilho de automação equivalente (`card_created`, "Negócio criado") aceita um filtro opcional por `pipelineId` — em branco, dispara para qualquer pipeline. O `pipelineId` do card também chega como variável da automação.
</Note>

***

### card.moved

Disparado quando um card é movido para outra etapa do pipeline.

```json theme={null}
{
  "event": "card.moved",
  "workspace_id": "wks_abc123",
  "timestamp": "2025-05-07T14:30:00.000Z",
  "card_id": "card_mno345",
  "from_stage_id": "stage_stu901",
  "to_stage_id": "stage_vwx234",
  "contact_id": "cnt_ghi789",
  "name": "João Ferreira"
}
```

***

### card.won

Disparado quando um card é marcado como **ganho** no pipeline.

```json theme={null}
{
  "event": "card.won",
  "workspace_id": "wks_abc123",
  "timestamp": "2026-05-08T15:30:00.000Z",
  "card_id": "card_mno345",
  "stage_id": "stage_stu901",
  "pipeline_id": "pipe_pqr678",
  "contact_id": "cnt_ghi789",
  "name": "João Ferreira",
  "value": 1500.00,
  "closed_at": "2026-05-08T15:30:00.000Z"
}
```

***

### card.lost

Disparado quando um card é marcado como **perdido** no pipeline.

```json theme={null}
{
  "event": "card.lost",
  "workspace_id": "wks_abc123",
  "timestamp": "2026-05-08T15:30:00.000Z",
  "card_id": "card_mno345",
  "stage_id": "stage_stu901",
  "pipeline_id": "pipe_pqr678",
  "contact_id": "cnt_ghi789",
  "name": "João Ferreira",
  "lost_reason": "Preço fora do orçamento",
  "closed_at": "2026-05-08T15:30:00.000Z"
}
```

<Note>
  `lost_reason` é `null` quando o motivo de perda não foi preenchido.
</Note>

***

## Reembolso e cancelamento (webhook inbound + eventFilter)

O Vistum ainda não emite um evento dedicado de reembolso. Para reagir a reembolso/cancelamento de checkout (Hotmart, Kiwify, etc.), use o gatilho de automação **`webhook_received`** com um **`eventFilter`** no campo de status do payload do checkout.

O endpoint inbound (`POST /api/automations/webhook-in/[token]`) extrai o campo configurado em `eventFilter.path` e compara com o valor esperado. Eventos que não batem ficam registrados com status `filtered` e não disparam o fluxo:

```json theme={null}
{
  "eventFilter": {
    "path": "event",
    "op": "equals",
    "value": "REFUNDED"
  }
}
```

Todos os campos escalares do body recebido ficam disponíveis nas ações como variáveis `webhook.<campo>` (ex: `webhook.status`, `webhook.product`, `webhook.amount`, `webhook.eventType`). Cada chave é truncada e tem `{{`/`}}` neutralizados contra injeção. Há dedup por `externalId` (Redis) e rate limit por IP e por token.
