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

# Webhooks de salida

> Suscríbase a eventos de mensaje, conversación, exclusión y plantilla. Verifique las firmas HMAC, gestione los reintentos y evite el procesamiento duplicado.

Los webhooks salientes permiten a sus sistemas reaccionar a eventos en Flowella casi en tiempo real, sin sondear la API. Se configura una URL y una lista de tipos de eventos, y Flowella envía una carga JSON firmada a esa URL cada vez que se produce uno de esos eventos.

## Configuración de un webhook

Necesitas el rol **Owner** o **Admin**.

<Steps>
  <Step title="Abra Ajustes → Webhooks">
    En la aplicación Flowella, ve a **Configuración → Webhooks**.
  </Step>

  <Step title="Añadir un webhook">
    Haz clic en **Añadir webhook**, pega la URL HTTPS pública de tu endpoint y elige los tipos de eventos que quieres recibir.
  </Step>

  <Step title="Guardar el secreto de firma">
    Flowella genera un secreto de firma único para el webhook. Cópialo: lo utilizarás para verificar las solicitudes entrantes.
  </Step>

  <Step title="Enviar una prueba">
    Haz clic en **Enviar prueba** para enviar inmediatamente una carga útil `webhook.test`. Comprueba que tu endpoint lo ha recibido y ha respondido con un 2xx.
  </Step>
</Steps>

## Tipos de eventos

Puede suscribirse a cualquiera de estos eventos de producto:

## Evento ## Cuando se dispara

\| --- | --- |
\| `message.received` | Ha llegado un mensaje entrante WhatsApp de un contacto | | `message.sent` | Flowella ha aceptado su mensaje saliente.
\| `message.sent` | Flowella ha aceptado su mensaje saliente y lo ha enviado a Meta | Meta
\| `message.delivered` | Meta ha confirmado la entrega del mensaje al dispositivo del destinatario | `message.read`
\| `message.read` El destinatario abrió el mensaje | `message.failed`
\| `message.failed` | Meta devolvió un fallo para el mensaje | `conversation.opened`
\| `conversation.opened` | Una conversación ha pasado al estado abierto | `conversation.closed`
\| `conversation.closed` | Se ha cerrado una conversación | `optout.created`
\| `optout.created` | Un contacto se ha dado de baja en un canal específico | `template.status_updated`
\| `template.status_updated` | Meta ha cambiado el estado de una plantilla (aprobada, rechazada, en pausa, desactivada) | `optout.created`

`webhook.test` sólo se envía cuando haces clic en **Enviar prueba** - no te suscribes a él explícitamente.

## Formato de solicitud

Flowella envía un cuerpo JSON a tu URL con estas cabeceras:

```http theme={null}
POST https://your-endpoint.example.com/flowella
Content-Type: application/json
User-Agent: Flowella-Webhooks/1
X-Flowella-Signature: <hex digest>
```

Las cargas útiles tienen un límite de **256 KB**. Los objetos de mayor tamaño se resumen: utilice la API para obtener el registro completo por ID si lo necesita.

La forma del cuerpo varía según el evento, pero siempre incluye:

```json theme={null}
{
  "event": "message.delivered",
  "timestamp": "2025-01-15T14:30:00.000Z",
  "organizationId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
  "data": { "...event-specific fields..." }
}
```

## Verificación de firmas

Cada petición incluye una cabecera `X-Flowella-Signature`. El valor es el **HMAC-SHA256 hex digest** del **raw UTF-8 request body** cifrado con el secreto de firma de tu webhook.

Verificar antes de procesar:

```js theme={null}
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(signatureHeader, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}
```

```python theme={null}
import hmac, hashlib

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header)
```

<Warning>
  Firma siempre sobre los **bytes del cuerpo en bruto** antes de que cualquier parseo JSON o middleware reformatee la carga útil. Si tu framework reserializa JSON, la firma no coincidirá.
</Warning>

## Respuestas, reintentos y tiempos de espera

* Tiempo de espera\*\*: Flowella espera hasta **10 segundos** a que su endpoint responda.
* **Success**: cualquier respuesta de `2xx` se considera una entrega correcta.
* Reintentos\*\*: las entregas fallidas se reintentan hasta **3 intentos** con backoff.
* Desactivación automática\*\*: si un webhook acumula **10 fallos consecutivos**, Flowella lo desactiva. Tendrás que volver a activarlo desde **Configuración → Webhooks** después de arreglar tu endpoint.

Su punto final debe volver lo más rápido posible - aplazar cualquier procesamiento pesado a una cola de fondo de su lado.

## Idempotencia

Los webhooks pueden ser reintentados, por lo que el mismo evento lógico puede llegar más de una vez. Para procesar con seguridad:

* Utilice el `data.id` del evento (o una clave derivada como `event + data.messageId`) como clave de idempotencia.
* Mantén una caché de corta duración de las claves procesadas (unas horas son suficientes para reintentos).
* Tratar los duplicados como no-ops.

## Listado y gestión de entregas

**Configuración → Webhooks** muestra los intentos de entrega recientes por webhook, incluyendo:

* Marca de tiempo
* Tipo de evento
* Estado de la respuesta
* Un cuerpo de respuesta truncado (hasta \~1 KB) para depuración

Si un webhook se desactiva debido a fallos repetidos, la misma página le permite volver a activarlo.

## Desarrollo local

La forma más sencilla de desarrollar con webhooks localmente es enviar un túnel público (por ejemplo, ngrok o Cloudflare Tunnel) a tu servidor de desarrollo y apuntar la URL del webhook al host del túnel. Utiliza **Send test** para disparar payloads bajo demanda sin esperar a la actividad real de WhatsApp.

<Tip>
  ¿Necesitas reaccionar a eventos que no están en la lista? Dínoslo en [support](https://flowella.io/support) - añadimos eventos a medida que los clientes nos los piden.
</Tip>

## Relacionados

<CardGroup cols={2}>
  <Card title="Configuración → Webhooks" icon="webhook" href="/es/settings/webhooks">
    Configurar puntos finales, secretos de firma y reintentos en la aplicación.
  </Card>

  <Card title="Introducción a la API" icon="code" href="/es/api-reference/introduction">
    Autenticación, errores, paginación y límites de velocidad para la API REST.
  </Card>

  <Card title="Claves API" icon="key" href="/es/settings/api-keys">
    Crea y rota los tokens portadores que tu endpoint pueda necesitar.
  </Card>

  <Card title="Eventos de notificación" icon="bell" href="/es/app/notification-events">
    Los mismos eventos entregados en el feed in-app y el correo electrónico.
  </Card>
</CardGroup>
