Webhooks y Eventos

Configura webhooks para recibir notificaciones en tiempo real

Webhooks y Eventos

Los webhooks te permiten recibir notificaciones HTTP automáticas cuando ocurren eventos específicos en nuestra plataforma.

¿Qué son los Webhooks?

Los webhooks son callbacks HTTP que envían datos a tu aplicación cuando suceden eventos. Esto te permite mantener tus sistemas sincronizados en tiempo real.

Configuración de Webhooks

Crear un Webhook

  1. Ve a Configuración > Integraciones > Webhooks
  2. Haz clic en "Crear Webhook"
  3. Configura los parámetros necesarios:
    • URL de destino: La URL donde enviaremos los datos
    • Eventos: Selecciona qué eventos quieres escuchar
    • Secreto: (Opcional) Para verificar la autenticidad

Eventos Disponibles

Eventos de Usuario

  • user.created - Usuario creado
  • user.updated - Usuario actualizado
  • user.deleted - Usuario eliminado

Eventos de Proyecto

  • project.created - Proyecto creado
  • project.updated - Proyecto actualizado
  • project.completed - Proyecto completado
  • project.deleted - Proyecto eliminado

Eventos de Tarea

  • task.created - Tarea creada
  • task.assigned - Tarea asignada
  • task.completed - Tarea completada
  • task.deleted - Tarea eliminada

Estructura del Payload

Todos los webhooks envían un payload JSON con la siguiente estructura:

{
  "event": "user.created",
  "timestamp": "2024-12-10T10:30:00Z",
  "data": {
    "id": "123",
    "name": "Juan Pérez",
    "email": "juan@ejemplo.com"
  },
  "webhook_id": "webhook_456"
}

Verificación de Seguridad

Usando Secretos

Si configuras un secreto, incluiremos una firma en el header X-Webhook-Signature:

const crypto = require("crypto");

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");

  return signature === `sha256=${expectedSignature}`;
}

Manejo de Errores

Reintentos

Si tu endpoint retorna un código de error (4xx o 5xx), reintentaremos el webhook:

  • 1er reintento: Después de 5 segundos
  • 2do reintento: Después de 25 segundos
  • 3er reintento: Después de 125 segundos

Códigos de Respuesta

Tu endpoint debe responder con:

  • 200-299: Webhook procesado exitosamente
  • 410: No reintentes este webhook
  • Otros códigos: Reintentaremos según la política

Mejores Prácticas

Idempotencia

Maneja webhooks duplicados verificando el ID del evento:

const processedEvents = new Set();

function handleWebhook(payload) {
  const eventId = `${payload.event}_${payload.timestamp}_${payload.data.id}`;

  if (processedEvents.has(eventId)) {
    return; // Ya procesado
  }

  processedEvents.add(eventId);
  // Procesar webhook...
}

Respuesta Rápida

Responde rápidamente al webhook y procesa los datos de forma asíncrona:

app.post("/webhook", (req, res) => {
  // Responder inmediatamente
  res.status(200).send("OK");

  // Procesar de forma asíncrona
  processWebhookAsync(req.body);
});

Ejemplo de Implementación

Node.js + Express

const express = require("express");
const crypto = require("crypto");
const app = express();

app.use(express.raw({ type: "application/json" }));

app.post("/webhook", (req, res) => {
  const signature = req.headers["x-webhook-signature"];
  const payload = req.body;

  // Verificar firma
  if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send("Unauthorized");
  }

  const event = JSON.parse(payload);

  // Procesar evento
  switch (event.event) {
    case "user.created":
      handleUserCreated(event.data);
      break;
    case "project.completed":
      handleProjectCompleted(event.data);
      break;
    default:
      console.log(`Evento no manejado: ${event.event}`);
  }

  res.status(200).send("OK");
});

Python + Flask

import hashlib
import hmac
import json
from flask import Flask, request

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Webhook-Signature')
    payload = request.data

    # Verificar firma
    if not verify_webhook(payload, signature, SECRET):
        return 'Unauthorized', 401

    event = json.loads(payload)

    # Procesar evento
    if event['event'] == 'user.created':
        handle_user_created(event['data'])
    elif event['event'] == 'project.completed':
        handle_project_completed(event['data'])

    return 'OK', 200

def verify_webhook(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    return signature == f'sha256={expected}'

Monitoreo y Debugging

Panel de Webhooks

En tu panel de control puedes:

  • Ver el historial de webhooks enviados
  • Revisar respuestas y errores
  • Reenviar webhooks manualmente
  • Pausar/activar webhooks

Logs de Webhooks

Cada webhook enviado se registra con:

  • Timestamp del envío
  • Código de respuesta
  • Tiempo de respuesta
  • Payload enviado

Solución de Problemas

Webhook No Recibido

  1. Verifica que la URL esté correcta
  2. Asegúrate de que tu servidor esté ejecutándose
  3. Revisa las reglas de firewall
  4. Verifica que no haya filtros de proxy

Errores de Firma

  1. Verifica que el secreto esté configurado correctamente
  2. Asegúrate de usar el payload raw para el cálculo
  3. Verifica el algoritmo de hash (SHA-256)

Timeouts

Los webhooks tienen un timeout de 30 segundos. Si tu procesamiento toma más tiempo:

  1. Responde inmediatamente (200 OK)
  2. Procesa los datos de forma asíncrona
  3. Considera usar una cola de trabajos

Última actualización: Diciembre 2024