C
Cotizera Docs

Webhooks

Descripción General

Los webhooks te permiten recibir notificaciones HTTP POST en tiempo real cuando ocurren eventos en Cotizera. En lugar de consultar la API periódicamente, registra una URL y Cotizera enviará los datos del evento automáticamente.

Los webhooks son una funcionalidad del plan PRO.

Eventos Disponibles

Evento Descripción
quote.created Se creó una nueva cotización
quote.status_changed El estado de una cotización cambió (ej: Generada → Enviada → Ganada)
quote.revised Se creó una nueva versión de una cotización (PRO)
client.created Se agregó un nuevo cliente
product.created Se agregó un nuevo producto
webhook.test Evento de prueba enviado con el botón "Probar"

Formato del Payload

Cada entrega de webhook es un POST con formato JSON con esta estructura:

{
  "event": "quote.created",
  "timestamp": "2026-03-31T14:30:00.000Z",
  "data": {
    "id": "clx1abc123",
    "quoteNumber": "COT-0042",
    "status": "GENERATED",
    "total": 15000.00,
    "clientId": "clx2def456",
    "createdAt": "2026-03-31T14:30:00.000Z"
  }
}

El campo data contiene el objeto completo del recurso que generó el evento.

Headers HTTP

Cada entrega incluye estos headers:

Header Descripción
Content-Type application/json
X-Cotizera-Signature Firma HMAC-SHA256 del cuerpo de la solicitud
X-Cotizera-Event Tipo de evento (ej: quote.created)

Crear un Webhook

Mediante la API

curl -X POST https://cotizera.com/api/webhooks \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "url": "https://your-server.com/webhook",
    "events": ["quote.created", "quote.status_changed"]
  }'

La respuesta incluye un campo secret — guárdalo para la verificación de firma.

Mediante la Interfaz

  1. Ve a Configuración → Webhooks
  2. Haz clic en "Nuevo webhook"
  3. Ingresa la URL de tu endpoint
  4. Selecciona los eventos a los que quieres suscribirte
  5. Guarda — toma nota del secreto del webhook que se muestra

Verificación de Firma

Cada entrega de webhook está firmada con el secreto de tu webhook usando HMAC-SHA256. Siempre verifica las firmas para asegurarte de que la solicitud proviene de Cotizera.

La firma se encuentra en el header X-Cotizera-Signature y se calcula sobre el cuerpo crudo de la solicitud.

Node.js

const crypto = require("crypto");
 
function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
 
// Express example
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.headers["x-cotizera-signature"];
  if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send("Invalid signature");
  }
 
  const event = JSON.parse(req.body);
  console.log(`Received ${event.event}:`, event.data);
  res.status(200).send("OK");
});

Python

import hmac
import hashlib
 
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)
 
# Flask example
@app.route("/webhook", methods=["POST"])
def handle_webhook():
    signature = request.headers.get("X-Cotizera-Signature")
    if not verify_webhook(request.data, signature, WEBHOOK_SECRET):
        return "Invalid signature", 401
 
    event = request.json
    print(f"Received {event['event']}: {event['data']}")
    return "OK", 200

Lógica de Reintentos

Si tu endpoint no responde con un código de estado 2xx (o se agota el tiempo después de 5 segundos), Cotizera reintenta con retroceso exponencial:

Intento Demora
1 Inmediato
2 1 minuto
3 5 minutos
4 30 minutos
5 2 horas

Después de 5 intentos fallidos, la entrega se marca como fallida permanentemente y el propietario del tenant recibe una notificación dentro de la aplicación.

Probar Webhooks

Envía un evento de prueba a cualquier webhook registrado:

curl -X POST https://cotizera.com/api/webhooks/{id}/test \
  -b cookies.txt

Esto envía un evento webhook.test con un payload de ejemplo a tu endpoint. La respuesta incluye:

{
  "success": true,
  "statusCode": 200
}

También puedes hacer clic en "Probar" en cualquier webhook dentro de la interfaz de Cotizera.

Logs de Entrega

Consulta el historial de entregas de un webhook:

curl https://cotizera.com/api/webhooks/{id}/deliveries \
  -b cookies.txt

Cada registro de entrega incluye el evento, el payload, el código de estado HTTP, el cuerpo de la respuesta y la marca de tiempo.

Mejores Prácticas

  1. Responde rápido — Devuelve un 200 en menos de 5 segundos. Procesa el evento de forma asíncrona si es necesario.
  2. Verifica las firmas — Siempre valida X-Cotizera-Signature para prevenir solicitudes falsificadas.
  3. Maneja duplicados — En casos excepcionales, los eventos pueden entregarse más de una vez. Usa el timestamp del evento y el id del recurso para garantizar idempotencia.
  4. Usa HTTPS — Siempre usa un endpoint HTTPS para proteger los datos del payload en tránsito.
  5. Monitorea los logs de entrega — Revisa los logs de entrega de webhooks en la interfaz de Cotizera para diagnosticar fallos.
© 2026 Cotizera. All rights reserved.