# Webhook de entrada

> Como outro sistema (CRM, formulário, ERP, n8n, Zapier) inicia um workflow da comunidade chamando um endereço da Memberfy. Gerar, girar e revogar o endereço, o token no cabeçalho, a assinatura HMAC com exemplos em curl e Node, como a pessoa é encontrada, as variáveis do gatilho, as respostas e as entregas.

O **webhook de entrada** é o caminho contrário dos [webhooks](/api/webhooks): em vez de a Memberfy avisar outro sistema, outro sistema (um CRM, um formulário, um ERP, uma automação no n8n ou no Zapier) chama um endereço da Memberfy e inicia um [workflow](/notificacoes/workflows) para uma pessoa da comunidade. Por exemplo: o CRM fecha uma venda e a pessoa recebe a régua de boas-vindas do cliente.

## Gerar o endereço

*Papel: proprietário ou administrador.*

1. Em **Administração › Workflows**, abra o workflow e arraste o bloco de gatilho **Webhook** (*Webhook recebido*) para o desenho. Cada workflow tem um gatilho só.
2. Em **Quem é a pessoa**, diga onde está a pessoa no JSON da chamada: **Pelo e-mail** ou **Pelo memberId**, e o **Caminho no JSON** (campos separados por ponto, como `contact.email`, sem índices de lista).
3. Em **Valores para usar nos passos**, se quiser, mapeie até 20 valores do JSON (**Nome** e caminho).
4. **Salvar** o workflow e, no painel do gatilho, **Gerar endereço**.

A janela mostra o **Endereço**, o **Token** e o **Segredo da assinatura (HMAC)** uma vez só: *"Guarde agora: o token e o segredo aparecem só desta vez."* Depois, o painel mostra só o fim do token e do segredo.

- **Girar** cria um token e um segredo novos, que valem na hora; o sistema que chama o endereço atual para de funcionar até receber os novos.
- **Revogar** desliga o endereço na hora: as chamadas passam a ser recusadas.

## Chamar o endereço

Faça um `POST` com o corpo em JSON (`Content-Type: application/json`, até 64 KB) para `https://api.memberfy.net/api/workflow-hooks`, com:

| Cabeçalho | O que é |
|---|---|
| `X-Memberfy-Hook-Token` | O token do gatilho. Mande sempre no cabeçalho: no endereço (`/api/workflow-hooks/{token}`) ele também funciona, mas fica em logs |
| `X-Memberfy-Signature` | A assinatura, `t=<unix>,v1=<hex>` (ver abaixo) |
| `X-Memberfy-Delivery-Id` | Um identificador único da chamada (até 64 letras, dígitos, `-` e `_`). Repetido em 10 minutos, a chamada é recusada |

### A assinatura (HMAC)

Com **Exigir assinatura (HMAC)** ligado (o padrão), só quem tem o segredo inicia o workflow. A assinatura é obrigatória quando o caminho do gatilho envia conteúdo (e-mail, mensagem, comentário, reação ou Slack): sem ela, o workflow não liga.

Para assinar:

1. `t` é o horário atual em segundos (Unix). Ele vale por **5 minutos** para mais ou para menos.
2. Calcule o HMAC-SHA256, em hexadecimal, com o segredo, sobre `t`, um ponto e o **corpo cru**, exatamente os bytes que vão na chamada: `"<t>.<corpo>"`.
3. Mande `X-Memberfy-Signature: t=<t>,v1=<hmac>`.

**curl:**

```bash
SECRET='o-segredo-do-gatilho'
TOKEN='o-token-do-gatilho'
BODY='{"customer":{"email":"maria@memberfy.net"},"plan":{"name":"Anual"}}'
T=$(date +%s)
SIG=$(printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')

curl -X POST https://api.memberfy.net/api/workflow-hooks \
  -H 'Content-Type: application/json' \
  -H "X-Memberfy-Hook-Token: $TOKEN" \
  -H "X-Memberfy-Signature: t=$T,v1=$SIG" \
  -H "X-Memberfy-Delivery-Id: crm-$(date +%s%N)" \
  --data "$BODY"
```

**Node:**

```js
const crypto = require('crypto');

async function startWorkflow(payload) {
  const body = JSON.stringify(payload); // assine exatamente o que vai na chamada
  const t = Math.floor(Date.now() / 1000);
  const v1 = crypto
    .createHmac('sha256', process.env.MEMBERFY_HOOK_SECRET)
    .update(`${t}.${body}`)
    .digest('hex');

  const res = await fetch('https://api.memberfy.net/api/workflow-hooks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Memberfy-Hook-Token': process.env.MEMBERFY_HOOK_TOKEN,
      'X-Memberfy-Signature': `t=${t},v1=${v1}`,
      'X-Memberfy-Delivery-Id': crypto.randomUUID(),
    },
    body,
  });
  return res.status; // 202 quando aceito
}

startWorkflow({ customer: { email: 'maria@memberfy.net' }, plan: { name: 'Anual' } });
```

## A pessoa e as variáveis

- A Memberfy procura a pessoa **depois** de responder, pelo e-mail ou pelo `memberId` no caminho configurado. Ela precisa ser membro da comunidade; senão, a entrega fica como *Pessoa não encontrada*.
- Só os valores mapeados são guardados, na execução da pessoa; o resto do corpo é descartado.
- Cada valor vira a variável `{{gatilho_<nome>}}`, por exemplo `{{gatilho_plano}}`. Ela vale no texto das mensagens, dos comentários e do Slack e **no corpo** dos e-mails, nunca no assunto nem dentro de links.
- **Quantas vezes a pessoa entra** vale como em qualquer gatilho, e cada pessoa entra no máximo **5 vezes por dia** pelo webhook de cada workflow.
- Uma chamada que traz o cabeçalho `X-Memberfy-Run-Id` de uma execução do próprio workflow (um sistema de fora devolvendo a chamada que o workflow fez) é ignorada, para não criar um laço. Os posts no Slack de um workflow levam esse cabeçalho.

## Respostas

| Status | Quando |
|---|---|
| `202` | Token e assinatura valem. A resposta é a mesma achando ou não a pessoa; o resultado aparece nas entregas |
| `401` | Assinatura ausente, errada ou fora dos 5 minutos |
| `404` | Token desconhecido, revogado ou de um workflow excluído |
| `409` | `X-Memberfy-Delivery-Id` repetido em 10 minutos |
| `413` | Corpo acima de 64 KB |
| `429` | Mais de 60 chamadas por minuto ou 5 mil por dia no mesmo endereço; espere o `Retry-After` |
| `503` | A verificação de repetição está indisponível no momento; tente de novo |

## Entregas

No painel do gatilho, **Entregas** lista cada chamada recebida, com o resultado: **Iniciou**, **Na fila**, **Pessoa não encontrada**, **Workflow desligado**, **Já tinha entrado**, **Limite diário da pessoa**, **Sem assinatura** ou **Chamada repetida (loop)**.

## Pelo assistente (MCP)

O proprietário e o administrador geram (`create_workflow_webhook`: o token e o segredo aparecem uma vez), giram e revogam (`rotate_workflow_webhook` e `revoke_workflow_webhook`, com confirmação); a equipe consulta o endereço (`get_workflow_webhook`, nunca o token) e as entregas (`list_workflow_webhook_deliveries`). Ver [Ferramentas · Comunidade](/mcp/ferramentas-comunidade#workflows).

## Relacionados

- [Workflows](/notificacoes/workflows)
- [Webhooks](/api/webhooks)
- [Zapier, Make e n8n](/integracoes/zapier-make-n8n)
