# Webhook de entrada

> Cómo otro sistema (CRM, formulario, ERP, n8n, Zapier) inicia un workflow de la comunidad llamando a una dirección de Memberfy. Generar, rotar y revocar la dirección, el token en la cabecera, la firma HMAC con ejemplos en curl y Node, cómo se encuentra a la persona, las variables del disparador, las respuestas y las entregas.

El **webhook de entrada** es el camino inverso de los [webhooks](/api/webhooks): en lugar de que Memberfy avise a otro sistema, otro sistema (un CRM, un formulario, un ERP, una automatización en n8n o en Zapier) llama a una dirección de Memberfy e inicia un [workflow](/notificacoes/workflows) para una persona de la comunidad. Por ejemplo: el CRM cierra una venta y la persona recibe la serie de bienvenida del cliente.

## Generar la dirección

*Rol: propietario o administrador.*

1. En **Administración › Workflows**, abre el workflow y arrastra el bloque de disparador **Webhook** (*Webhook recibido*) al diseño. Cada workflow tiene un solo disparador.
2. En **Quién es la persona**, indica dónde está la persona en el JSON de la llamada: **Por el correo** o **Por el memberId**, y la **Ruta en el JSON** (campos separados por puntos, como `contact.email`, sin índices de lista).
3. En **Valores para usar en los pasos**, si quieres, asigna hasta 20 valores del JSON (**Nombre** y ruta).
4. **Guardar** el workflow y, en el panel del disparador, **Generar dirección**.

La ventana muestra la **Dirección**, el **Token** y el **Secreto de firma (HMAC)** una sola vez: *"Guárdalos ahora: el token y el secreto se muestran solo esta vez."* Después, el panel muestra solo el final del token y del secreto.

- **Rotar** crea un token y un secreto nuevos, que valen al momento; el sistema que llama a la dirección actual deja de funcionar hasta recibir los nuevos.
- **Revocar** desactiva la dirección al momento: las llamadas pasan a rechazarse.

## Llamar a la dirección

Haz un `POST` con el cuerpo en JSON (`Content-Type: application/json`, hasta 64 KB) a `https://api.memberfy.net/api/workflow-hooks`, con:

| Cabecera | Qué es |
|---|---|
| `X-Memberfy-Hook-Token` | El token del disparador. Envíalo siempre en la cabecera: en la dirección (`/api/workflow-hooks/{token}`) también funciona, pero queda en los logs |
| `X-Memberfy-Signature` | La firma, `t=<unix>,v1=<hex>` (ver abajo) |
| `X-Memberfy-Delivery-Id` | Un identificador único de la llamada (hasta 64 letras, dígitos, `-` y `_`). Si se repite en 10 minutos, la llamada se rechaza |

### La firma (HMAC)

Con **Exigir firma (HMAC)** activado (por defecto), solo quien tiene el secreto inicia el workflow. La firma es obligatoria cuando el camino del disparador envía contenido (correo, mensaje, comentario, reacción o Slack): sin ella, el workflow no se activa.

Para firmar:

1. `t` es la hora actual en segundos (Unix). Vale **5 minutos** arriba o abajo.
2. Calcula el HMAC-SHA256, en hexadecimal, con el secreto, sobre `t`, un punto y el **cuerpo en bruto**, exactamente los bytes que van en la llamada: `"<t>.<cuerpo>"`.
3. Envía `X-Memberfy-Signature: t=<t>,v1=<hmac>`.

**curl:**

```bash
SECRET='el-secreto-del-disparador'
TOKEN='el-token-del-disparador'
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); // firma exactamente lo que va en la llamada
  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 cuando se acepta
}

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

## La persona y las variables

- Memberfy busca a la persona **después** de responder, por el correo o por el `memberId` en la ruta configurada. Tiene que ser miembro de la comunidad; si no, la entrega queda como *Persona no encontrada*.
- Solo se guardan los valores asignados, en la ejecución de la persona; el resto del cuerpo se descarta.
- Cada valor se convierte en la variable `{{gatilho_<nome>}}`, por ejemplo `{{gatilho_plano}}`. Vale en el texto de los mensajes, de los comentarios y de Slack y **en el cuerpo** de los correos, nunca en el asunto ni dentro de enlaces.
- **Cuántas veces entra la persona** vale como en cualquier disparador, y cada persona entra como máximo **5 veces al día** por el webhook de cada workflow.
- Una llamada que trae la cabecera `X-Memberfy-Run-Id` de una ejecución del propio workflow (un sistema externo que devuelve la llamada que hizo el workflow) se ignora, para no crear un bucle. Las publicaciones en Slack de un workflow llevan esa cabecera.

## Respuestas

| Estado | Cuándo |
|---|---|
| `202` | El token y la firma son válidos. La respuesta es la misma se encuentre o no a la persona; el resultado aparece en las entregas |
| `401` | Firma ausente, incorrecta o fuera de los 5 minutos |
| `404` | Token desconocido, revocado o de un workflow eliminado |
| `409` | `X-Memberfy-Delivery-Id` repetido en 10 minutos |
| `413` | Cuerpo de más de 64 KB |
| `429` | Más de 60 llamadas por minuto o 5 mil al día en la misma dirección; espera el `Retry-After` |
| `503` | La comprobación de repetición no está disponible en este momento; inténtalo de nuevo |

## Entregas

En el panel del disparador, **Entregas** lista cada llamada recibida, con el resultado: **Iniciado**, **En cola**, **Persona no encontrada**, **Workflow desactivado**, **Ya había entrado**, **Límite diario de la persona**, **Sin firma** o **Llamada repetida (bucle)**.

## Por el asistente (MCP)

El propietario y el administrador generan (`create_workflow_webhook`: el token y el secreto se muestran una vez), rotan y revocan (`rotate_workflow_webhook` y `revoke_workflow_webhook`, con confirmación); el equipo consulta la dirección (`get_workflow_webhook`, nunca el token) y las entregas (`list_workflow_webhook_deliveries`). Ver [Herramientas · Comunidad y estructura](/mcp/ferramentas-comunidade#workflows).

## Relacionados

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