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

# Webhook de entrada

> Criar um contato a partir de qualquer sistema. Formatos aceitos, respostas e exemplos.

## Criar um contato

<ParamField path="token" type="string" required>
  O token de 48 caracteres do webhook, no caminho da URL.
</ParamField>

```
POST /api/webhooks/receive/{token}
```

### Cabeçalhos aceitos

| `Content-Type`                      | Uso                                                    |
| ----------------------------------- | ------------------------------------------------------ |
| `application/json`                  | Recomendado                                            |
| `application/x-www-form-urlencoded` | Formulário HTML tradicional                            |
| `multipart/form-data`               | Formulário com upload; só os campos de texto são lidos |

Sem `Content-Type` reconhecido, o corpo é tentado como JSON.

### Corpo

Os nomes de campo são reconhecidos em português e em inglês, com as variações mais
comuns. A lista completa está em [Campos aceitos](/api/campos).

<ParamField body="email" type="string" required>
  Precisa conter `@`. É o único campo obrigatório.
</ParamField>

<ParamField body="nome" type="string">
  Sem ele, o contato entra como "Lead sem nome".
</ParamField>

<ParamField body="telefone" type="string">
  Qualquer formatação é aceita.
</ParamField>

<ParamField body="empresa" type="string" />

<ParamField body="valor" type="number | string">
  Convertido para número. O que não converte vira zero.
</ParamField>

<ParamField body="mensagem" type="string">
  Vai para a observação do contato.
</ParamField>

<ParamField body="origem" type="string">
  Se o texto corresponder a uma origem cadastrada na organização, sem diferenciar
  maiúscula de minúscula, o contato é ligado a ela. Quando o webhook já tem origem fixa
  configurada, ela vence e este campo é ignorado.
</ParamField>

### Exemplos

<CodeGroup>
  ```bash curl theme={"theme":{"light":"min-light","dark":"min-dark"}}
  curl -X POST https://crm.suaempresa.com/api/webhooks/receive/SEU_TOKEN \
    -H "Content-Type: application/json" \
    -d '{
      "nome": "Joana Ribeiro",
      "email": "joana@empresa.com.br",
      "telefone": "(11) 99999-9999",
      "empresa": "Empresa ABC",
      "mensagem": "Quer entender a implantação"
    }'
  ```

  ```javascript JavaScript theme={"theme":{"light":"min-light","dark":"min-dark"}}
  await fetch("https://crm.suaempresa.com/api/webhooks/receive/SEU_TOKEN", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      nome: "Joana Ribeiro",
      email: "joana@empresa.com.br",
      telefone: "11999999999",
      mensagem: "Quer entender a implantação",
    }),
  });
  ```

  ```python Python theme={"theme":{"light":"min-light","dark":"min-dark"}}
  import requests

  requests.post(
      "https://crm.suaempresa.com/api/webhooks/receive/SEU_TOKEN",
      json={
          "nome": "Joana Ribeiro",
          "email": "joana@empresa.com.br",
          "telefone": "11999999999",
          "mensagem": "Quer entender a implantação",
      },
      timeout=30,
  )
  ```

  ```php PHP theme={"theme":{"light":"min-light","dark":"min-dark"}}
  <?php
  $ch = curl_init('https://crm.suaempresa.com/api/webhooks/receive/SEU_TOKEN');
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      'nome' => 'Joana Ribeiro',
      'email' => 'joana@empresa.com.br',
      'telefone' => '11999999999',
  ]));
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $response = curl_exec($ch);
  curl_close($ch);
  ```

  ```html HTML theme={"theme":{"light":"min-light","dark":"min-dark"}}
  <form action="https://crm.suaempresa.com/api/webhooks/receive/SEU_TOKEN" method="POST">
    <input type="text" name="nome" placeholder="Nome" required />
    <input type="email" name="email" placeholder="Email" required />
    <input type="tel" name="telefone" placeholder="Telefone" />
    <textarea name="mensagem" placeholder="Mensagem"></textarea>
    <button type="submit">Enviar</button>
  </form>
  ```
</CodeGroup>

### Resposta

<ResponseField name="success" type="boolean" />

<ResponseField name="leadId" type="string">
  O identificador do contato criado.
</ResponseField>

<ResponseField name="message" type="string" />

```json 200 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "success": true,
  "leadId": "clx1234567890abcdef",
  "message": "Lead created successfully"
}
```

Os códigos de erro estão em [Erros](/api/erros).

## Verificar o webhook

```
GET /api/webhooks/receive/{token}
```

Diz se o webhook existe e está ativo, sem criar nada. Use para testar a conexão depois
de configurar.

<CodeGroup>
  ```bash curl theme={"theme":{"light":"min-light","dark":"min-dark"}}
  curl https://crm.suaempresa.com/api/webhooks/receive/SEU_TOKEN
  ```

  ```json 200 theme={"theme":{"light":"min-light","dark":"min-dark"}}
  {
    "status": "ok",
    "name": "Formulário do site",
    "type": "generic",
    "enabled": true
  }
  ```
</CodeGroup>

<Note>
  A verificação responde mesmo com o webhook desligado, dizendo `enabled: false`. É o
  `POST` que recusa nesse caso.
</Note>

## Tipos de webhook

<Tabs>
  <Tab title="generic">
    Aceita qualquer JSON ou formulário. Os campos são reconhecidos pelos nomes
    documentados em [Campos aceitos](/api/campos).
  </Tab>

  <Tab title="typeform">
    Entende o formato que o Typeform envia, mapeando as respostas por tipo de campo:
    email, telefone, número, texto e escolha.

    O que não tem destino conhecido é acumulado na observação do contato, com o título
    da pergunta ao lado, em vez de ser jogado fora. Quando não há nome, a parte do email
    antes do arroba é usada.
  </Tab>
</Tabs>

## O que acontece do lado de cá

<Steps>
  <Step title="Validação">
    O email é conferido. Sem `@`, a requisição é recusada e nada é criado.
  </Step>

  <Step title="Criação">
    O contato entra na etapa de entrada do funil padrão da organização.
  </Step>

  <Step title="Atribuição">
    Fica com o primeiro membro ativo da organização, preferindo dono, depois
    administrador, depois o mais antigo.
  </Step>

  <Step title="Origem">
    A origem fixa do webhook vence; na ausência dela, o texto enviado é comparado com as
    origens cadastradas.
  </Step>

  <Step title="Rastro">
    Uma notificação vai para a equipe, uma entrada é criada no histórico do contato
    nomeando o webhook, e o contador de recebidos do webhook sobe.
  </Step>

  <Step title="Automações">
    As automações de contato criado disparam. Veja [Automações](/funil/automacoes).
  </Step>
</Steps>

## Limites

<Warning>
  Não há limite de requisições por padrão. Isso é conveniente e é também o motivo de o
  token merecer cuidado: acompanhe o contador de recebidos e regere o token ao primeiro
  sinal de abuso.
</Warning>

Requisições devem completar em até trinta segundos. Uploads em `multipart/form-data` são
aceitos, mas o arquivo é ignorado: só os campos de texto entram.
