Webhooks
Recibe una solicitud HTTP en el momento en que se crea, confirma, reprograma, cancela o completa una cita, y conecta BookifyLabs con tus propios sistemas.
Añadir un punto de enlace (endpoint)
- Como propietario, abre Ajustes en el ámbito de empresa y busca la tarjeta de Webhooks.
- Haz clic en Añadir endpoint e introduce una URL pública que empiece por https://. Las direcciones de redes privadas y localhost serán rechazadas.
- Copia el secreto de firma que se muestra tras la creación. Empieza por
whsec_y solo se mostrará una vez. - Envía un evento de prueba creando una cita y, a continuación, revisa la lista de Entregas.
Puedes tener hasta 5 endpoints por empresa. Cada uno se puede pausar y reanudar, modificar su URL, volver a generar su secreto o eliminarlo junto con su historial de entregas.
Eventos
| Evento | Se envía cuando |
|---|---|
appointment.created | Se realiza una reserva, ya sea en línea, mediante Booky o por tu equipo. |
appointment.confirmed | Se confirma una cita pendiente. |
appointment.rescheduled | Cambia el horario o el profesional asignado. |
appointment.cancelled | Tú o el cliente canceláis la cita. |
appointment.completed | La cita se marca como completada a través de la pantalla de finalización. |
Formato de la solicitud
Cada entrega es una solicitud POST con un cuerpo JSON. El objeto data es una instantánea de la cita en el momento exacto en que ocurrió el evento; los reintentos reenvían el mismo cuerpo de datos.
POST https://example.com/hooks/bookify
Content-Type: application/json
User-Agent: BookifyLabs-Webhooks/1.0 (+https://bookifylabs.com)
X-Bookify-Event-ID: evt_3f6c…
X-Bookify-Timestamp: 1757145600
X-Bookify-Signature: 4b1d…
{
"id": "evt_3f6c…",
"type": "appointment.created",
"created_at": 1757145600,
"data": {
"appointment": { "id": 1234, "status": "booked", "start_at": "…", "…": "…" }
}
}Verificar la firma
La firma es un código hexadecimal HMAC-SHA256 generado sobre la cadena <timestamp>.<raw body>, utilizando como clave el secreto de tu endpoint. Calcúlala a partir del cuerpo sin procesar (raw) de la solicitud, antes de realizar cualquier análisis JSON, y compárala mediante una función de tiempo constante.
import crypto from "node:crypto";
function verify(rawBody, headers, secret) {
const ts = headers["x-bookify-timestamp"];
const sig = headers["x-bookify-signature"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // más de 5 minutos de antigüedad
const expected = crypto
.createHmac("sha256", secret)
.update(`${ts}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}- Rechaza marcas de tiempo de más de 5 minutos para evitar ataques de repetición.
- Elimina duplicados basándote en X-Bookify-Event-ID: los reintentos incluyen el mismo id.
- Responde con cualquier código 2xx en menos de 10 segundos. Realiza los procesos pesados después de responder.
Reintentos e historial de entregas
Si una entrega expira o recibe una respuesta 408, 425, 429 o cualquier código 5xx, se reintentará cada 12 horas hasta un máximo de 30 intentos. No se siguen redirecciones y las demás respuestas 4xx se consideran definitivas. La tabla de Entregas muestra el estado de cada evento (pendiente, enviando, reintentando, entregado, fallido), los intentos realizados, la respuesta almacenada (hasta 4 KB) y la hora del próximo intento. Las entregas fallidas o en proceso de reintento se pueden forzar con la opción Reintentar ahora. El historial se conserva durante 30 días.