Ir al contenido

Webhooks

Los webhooks permiten que Overtaker notifique a tu plataforma cuando ocurren eventos en los tenants de tus clientes — sin necesidad de polling.

El webhook se cuelga de una API key activa: primero generá tu key en Canal API, luego registrá la URL de destino.

Ventana de terminal
curl -X POST https://api.overtaker.online/api/v1/partner/webhooks \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://tuplataforma.com/webhooks/overtaker",
"events": ["message.received", "lead.created", "lead.stage_changed", "tenant.limit_warning"]
}'

La respuesta incluye tu webhook_secret — guardalo, lo necesitás para verificar la firma de cada evento.

EventoDescripción
message.receivedEl usuario envió un mensaje al bot
message.sentEl bot respondió al usuario
lead.createdSe capturó un nuevo lead
lead.stage_changedEl lead avanzó en el funnel
tenant.limit_warningEl tenant cruzó un umbral de aviso de su límite mensual (90% y 95%)
tenant.limit_reachedEl tenant llegó al 100% de su límite mensual

Todos los eventos comparten la misma envoltura {event, tenant_id, timestamp, data}. El campo data varía según el evento.

{
"event": "lead.created",
"tenant_id": "tenant_abc123",
"timestamp": "2026-05-21T10:30:00Z",
"data": {
"lead_id": "lead_xyz",
"phone": "+56912345678",
"funnel_stage": "NEW"
}
}

Ejemplos de data por evento:

Eventodata
message.received{ "conversation_id": "...", "message_preview": "Hola...", "channel": "API" }
message.sent{ "conversation_id": "...", "response_preview": "Hola, en qué ayudo..." }
lead.created{ "lead_id": "...", "phone": "+56912345678", "funnel_stage": "NEW" }
lead.stage_changed{ "lead_id": "...", "from_stage": "NEW", "to_stage": "QUALIFYING" }
tenant.limit_warning{ "usage_percent": 90, "tenant_name": "..." }
tenant.limit_reached{ "usage_percent": 100, "tenant_name": "..." }
HeaderDescripción
X-Overtaker-EventNombre del evento (ej. lead.created)
X-Overtaker-SignatureFirma HMAC-SHA256 del body (ver abajo)
X-Overtaker-DeliveryUUID de la entrega. Estable entre reintentos — usalo como clave de idempotencia
X-Overtaker-VersionVersión del formato de webhook (actualmente 1)

El header X-Overtaker-Signature contiene un HMAC-SHA256 del cuerpo crudo de la request, con el formato sha256=<hex>. Verificá sobre los bytes recibidos tal cual — no re-serialices el JSON, o la firma no coincidirá.

Durante una rotación de secret, el header puede traer dos firmas separadas por coma (sha256=<a>,sha256=<b>): la del secret actual y la del nuevo. Aceptá el evento si tu secret coincide con cualquiera de las dos.

import hmac
import hashlib
def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
"""raw_body: bytes exactos de la request (no el dict parseado).
signature_header: valor de X-Overtaker-Signature."""
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
# El header puede traer 1 o 2 firmas: "sha256=a" o "sha256=a,sha256=b"
for part in signature_header.split(","):
candidate = part.strip().removeprefix("sha256=")
if hmac.compare_digest(expected, candidate):
return True
return False

Si tu endpoint no responde con 2xx, Overtaker reintenta hasta 4 veces con backoff exponencial: 10s, 30s, 2min, 10min. Cada reintento conserva el mismo X-Overtaker-Delivery, así que tu handler debe ser idempotente. Tras agotar los intentos, el evento se mueve a un dead-letter log.