FlowEstate envía webhooks cuando los leads, proyectos o unidades cambian. Los suscriptores registran una URL destino y un tipo de evento; FlowEstate distribuye requests POST firmados con cuerpo JSON.
Para gestionar suscripciones programáticamente (crear, listar, eliminar), ver la Referencia API de webhooks. Esta página cubre lo que tu receptor necesita hacer una vez creada la suscripción.
Cada entrega incluye:
| Header | Descripción |
|---|
Content-Type | Siempre application/json. |
User-Agent | FlowEstate-Webhook/1.0 |
X-FlowEstate-Event | Tipo del evento, p.ej. lead.created. |
X-FlowEstate-Delivery | UUID de este intento de entrega. Úsalo para procesamiento idempotente. |
X-FlowEstate-Signature | sha256=<hex> HMAC-SHA256 del cuerpo crudo exacto usando el secret del endpoint. |
X-FlowEstate-Source | Origen del evento: ui, api o system. Úsalo para evitar bucles — ver más abajo. |
Body
{
"id": "evt_<uuid>",
"type": "lead.created",
"createdAt": "2026-04-29T18:04:15.000Z",
"organization": {
"id": "org_...",
"name": "Acme Realty",
"slug": "acme-realty"
},
"data": { /* payload específico del evento */ }
}
data depende del evento:
- Eventos
lead.* llevan data.lead.
- Eventos
project.* llevan data.project.
- Eventos
unit.* llevan data.unit y data.project.
lead.note_added lleva data.leadId y data.note.
lead.communication_logged lleva data.leadId y data.communication.
Para la lista completa de eventos ver Enums.
Verificar la firma
Verifica siempre la firma antes de confiar en un payload. Cualquiera que conozca tu URL puede pegarle; solo FlowEstate tiene el secret.
import crypto from "node:crypto";
function verify(rawBody, signatureHeader, secret) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
// Express
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
if (!verify(req.body, req.get("X-FlowEstate-Signature"), process.env.FLOWESTATE_SECRET)) {
return res.status(401).end();
}
const event = JSON.parse(req.body.toString("utf8"));
// ... maneja el evento ...
res.status(200).end();
});
Firma los bytes crudos del cuerpo. Re-serializar el JSON parseado va a producir una firma diferente porque el orden de las claves, los espacios y el formato de números pueden diferir.
El secret viene en la respuesta de POST /webhooks/subscriptions y se muestra solo una vez. Si lo pierdes, elimina la suscripción y crea una nueva.
Acuse de recibo
Devuelve cualquier status 2xx para acusar recibo. FlowEstate no lee el cuerpo de la respuesta — un 200 vacío está bien.
Si tu handler hace trabajo pesado (llama otros APIs, escribe a una BD lenta), acusa primero, procesa después:
app.post("/webhook", (req, res) => {
if (!verify(...)) return res.status(401).end();
res.status(200).end(); // ACK primero
enqueueForBackgroundProcessing(req.body); // procesa fuera de banda
});
El timeout de entrega es de unos pocos segundos — handlers lentos provocan reintentos innecesarios.
Política de reintentos
Las entregas fallidas (error de red, timeout, o HTTP ≥ 400) se reintentan con este backoff:
| Intento | Delay antes del retry |
|---|
| 1 | — (inicial) |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
| 6 | 12 horas |
Después de cinco intentos fallidos la entrega se marca como failed y no se reintenta más. El header X-FlowEstate-Delivery se mantiene constante a través de los reintentos — úsalo como tu clave de idempotencia al procesar.
Prevención de bucles
Cuando escribes a FlowEstate vía este API REST, el webhook resultante se distribuye con X-FlowEstate-Source: api. Si tu receptor también escribe de vuelta a FlowEstate, descarta los eventos con source api para evitar un bucle infinito.
if (req.headers["x-flowestate-source"] === "api") {
return res.status(200).end(); // ack e ignora
}
Los demás valores de source:
ui — cambio hecho por un usuario haciendo clic en el panel de FlowEstate.
system — cambio hecho por un worker interno (asignaciones, automatizaciones).
api — cambio hecho a través de este API REST (tus propias escrituras, plataformas partner).