# Webhook de entrada

> Como outro sistema (CRM, formulário, ERP, n8n, Zapier) inicia um workflow da comunidade chamando um endereço da Memberfy. Gerar, rodar 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 acionador, as respostas e as entregas.

O **webhook de entrada** é o caminho inverso dos [webhooks](/api/webhooks): em vez de a Memberfy avisar outro sistema, é outro sistema (um CRM, um formulário, um ERP, uma automatização no n8n ou no Zapier) que 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 acionador **Webhook** (*Webhook recebido*) para o desenho. Cada workflow tem um só acionador.
2. Em **Quem é a pessoa**, indique 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. **Guarde** o workflow e, no painel do acionador, clique em **Gerar endereço**.

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

- **Rodar** cria um token e um segredo novos, que valem de imediato; o sistema que chama o endereço atual deixa de funcionar até receber os novos.
- **Revogar** desativa o endereço de imediato: 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 acionador. Envie-o sempre no cabeçalho: no endereço (`/api/workflow-hooks/{token}`) também funciona, mas fica nos registos |
| `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 `_`). Se se repetir em 10 minutos, a chamada é recusada |

### A assinatura (HMAC)

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

Para assinar:

1. `t` é a hora atual em segundos (Unix). Vale durante **5 minutos** para mais ou para menos.
2. Calcule o HMAC-SHA256, em hexadecimal, com o segredo, sobre `t`, um ponto e o **corpo em bruto**, exatamente os bytes que seguem na chamada: `"<t>.<corpo>"`.
3. Envie `X-Memberfy-Signature: t=<t>,v1=<hmac>`.

**curl:**

```bash
SECRET='o-segredo-do-acionador'
TOKEN='o-token-do-acionador'
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 segue 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 aceite
}

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. Tem de ser membro da comunidade; caso contrário, 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 passa a ser a variável `{{gatilho_<nome>}}`, por exemplo `{{gatilho_plano}}`. Vale no texto das mensagens, dos comentários e do Slack e **no corpo** dos e-mails, nunca no assunto nem dentro de ligações.
- **Quantas vezes a pessoa entra** vale como em qualquer acionador, e cada pessoa entra no máximo **5 vezes por dia** pelo webhook de cada workflow.
- Uma chamada que traga o cabeçalho `X-Memberfy-Run-Id` de uma execução do próprio workflow (um sistema externo a devolver a chamada que o workflow fez) é ignorada, para não criar um ciclo. As publicações no Slack de um workflow levam esse cabeçalho.

## Respostas

| Status | Quando |
|---|---|
| `202` | O token e a assinatura são válidos. A resposta é a mesma quer a pessoa seja encontrada quer não; o resultado aparece nas entregas |
| `401` | Assinatura em falta, errada ou fora dos 5 minutos |
| `404` | Token desconhecido, revogado ou de um workflow eliminado |
| `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; aguarde o `Retry-After` |
| `503` | A verificação de repetição está indisponível de momento; tente novamente |

## Entregas

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

## Pelo assistente (MCP)

O proprietário e o administrador geram o endereço (`create_workflow_webhook`: o token e o segredo aparecem uma vez), rodam-no e revogam-no (`rotate_workflow_webhook` e `revoke_workflow_webhook`, com confirmação); a equipa 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)
