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

# Webhooks de entrada

> Como um sistema externo entrega dados pro Whatix: URL com hash, fieldMapping e o que acontece com o payload.

Um webhook de entrada é o caminho inverso da API: em vez de você chamar o Whatix, um sistema externo (formulário, CRM, planilha) manda dados **pra** o Whatix, que vira card, contato ou dispara um flow — sem você escrever código de integração.

<Note>Isso é diferente da API pública (`/wapi`): não usa `Authorization: Bearer`, não tem escopo, e não é você quem chama — é o seu sistema externo que recebe a URL e faz o `POST`.</Note>

## Como criar

<Steps>
  <Step title="Crie o webhook no painel">
    Vá em **API** (menu lateral) → aba **Webhooks** e crie um novo. Escolha a ação: **criar card** (`create_opportunity`), **disparar flow** (`trigger_flow`) ou **sincronizar contato** (`upsert_contact`). O painel gera uma URL pública com um hash não-adivinhável — copie a URL exibida ali, não monte ela manualmente.
  </Step>

  <Step title="Configure o fieldMapping">
    O `fieldMapping` traduz os caminhos do JSON que o sistema externo manda pros campos que o Whatix entende. Cada valor é um dot-path dentro do payload recebido:

    | Campo do Whatix | Uso |
    | - | - |
    | `phone` | Telefone do contato — **obrigatório** em todas as ações. |
    | `contactName` | Nome usado se o contato for criado agora. |
    | `title` | Título do card (só `create_opportunity`). |
    | `value` | Valor do card (só `create_opportunity`). |
    | `notes` | Observações do card. |
    | `email`, `document` | Só `upsert_contact` — atualiza se vierem preenchidos; campo vazio/ausente não apaga o que já existe. |
    | `custom.<nome-do-campo>` | Campos personalizados do pipeline (só `create_opportunity`) — a chave é o nome técnico do campo, não o ID. |

    Se o formulário externo manda:

    ```json theme={null}
    { "lead": { "telefone": "5534999990000", "nome": "Ana Lima" }, "interesse": "Plano Premium" }
    ```

    O mapeamento configurado no painel seria `phone → lead.telefone`, `contactName → lead.nome`, `title → interesse`.
  </Step>

  <Step title="Teste com cURL">
    Use a URL copiada do painel no passo 1:

    ```bash theme={null}
    curl -X POST <URL copiada do painel> \
      -H "Content-Type: application/json" \
      -d '{ "lead": { "telefone": "5534999990000", "nome": "Ana Lima" }, "interesse": "Plano Premium" }'
    ```

    A resposta é imediata (`202`), antes de qualquer processamento:

    ```json theme={null}
    { "received": true }
    ```
  </Step>
</Steps>

## O que acontece depois do 202

O `202` só confirma que o Whatix recebeu o payload — o processamento roda em background logo em seguida:

* **`create_opportunity`**: resolve o contato pelo `phone` (reaproveita se o número já existe, cria se não), cria o card no pipeline/etapa/origem configurados no webhook e aplica os campos personalizados de `custom`, se houver.
* **`trigger_flow`**: resolve o contato, abre um ticket na conexão configurada no webhook e roda o flow. As variáveis nativas do flow ficam disponíveis normalmente (`{{nome}}`, `{{telefone}}`, `{{protocolo}}`, `{{data}}`, `{{hora}}`, resolvidas do contato/ticket) — mas **o payload bruto recebido no webhook não vira variável do flow**.
* **`upsert_contact`**: cria ou atualiza o contato com `name`/`email`/`document`, sem criar card nem disparar flow.

<Warning>O payload recebido não é exposto como `{{variables.*}}` dentro do flow — hoje ele só é usado internamente para resolver o contato (`fieldMapping.phone`/`contactName`). Se o flow precisa de um dado específico do payload (ex.: o interesse do lead), leve-o pro contato via `fieldMapping` (inclusive `custom.<nome-do-campo>` em `create_opportunity`) antes de disparar o flow, ou trate o dado direto no seu sistema de origem.</Warning>

<Warning>Se `fieldMapping.phone` não resolver um telefone válido no payload recebido, o processamento falha silenciosamente do ponto de vista de quem chamou — a resposta já foi `202`. Use o histórico da tela do webhook no painel (que registra corpo cru e resultado de cada chamada) para depurar um mapeamento incorreto.</Warning>

## Autenticação opcional e limites

* Por padrão o webhook não exige nada além do hash (`authMode: none`). Você pode configurar um token no painel e exigi-lo no header `X-Whatix-Token`.
* Um hash inativo ou inexistente responde `404`.
* Rate limit próprio de **120 requisições por minuto por hash** (independente do rate limit de token da API `/wapi`) — passou disso, `429`.
* Para evitar duplicar o card/contato em caso de reenvio (retry do sistema externo), mande uma chave de idempotência: os headers `Idempotency-Key` ou `X-Idempotency-Key`, ou os campos `idempotency_key`, `event_id`/`eventId` no corpo (o primeiro valor encontrado, nessa ordem, é usado) — chamadas repetidas com a mesma chave dentro de 1 hora são ignoradas, e a resposta vem com `duplicate: true` (em vez de reprocessar) pra você identificar isso do seu lado.

## Erros comuns

| Situação | HTTP | O que fazer |
| - | - | - |
| Hash inexistente ou webhook desativado | 404 | Confira a URL no painel; um webhook pausado também responde 404, por segurança. |
| Token errado (quando `authMode: token` está ativo) | 401 | Confira o header `X-Whatix-Token`. |
| Corpo maior que 1MB | 413 | Reduza o payload — webhooks de entrada não são pensados para anexar arquivos grandes. |
| Mais de 120 chamadas/min no mesmo hash | 429 | Distribua os disparos no tempo. |

Para consumir dados do Whatix pela API tradicional (com token e escopos), veja [Autenticação](/pt/autenticacao) e os demais guias.
