Guía de integración
Conectá Cerralo con tu CRM
Cerralo envía cada lead calificado a tu sistema en tiempo real por webhook. Vos (o tu equipo técnico) recibís ese dato y creás el lead en tu CRM. Esta guía tiene todo lo necesario.
Cómo funciona
Un webhook, en tiempo real
Cada vez que el bot de Cerralo captura un lead, hace un POST HTTP con un JSON (el lead completo) a una URL que definís vos. Esa URL es el punto de entrada a tu sistema:
Cerralo no necesita un conector nativo de tu CRM: expone el webhook estándar y tu equipo lo mapea a tu instancia (Odoo u otro).
Configuración (2 pasos)
Dónde se pega la URL
application/json (puede ser un endpoint propio, una función serverless, o el webhook de entrada de tu CRM/automatización).El payload (qué manda Cerralo)
Campos del JSON
| Campo | Tipo | Descripción |
|---|---|---|
| event | string | "new_lead" (primera entrega) · "lead_updated" (opcional, ver sección propia). |
| tenantId | string | Id de la cuenta de Cerralo que originó el lead. |
| leadId | string | Id único del lead. Útil como clave para evitar duplicados en tu CRM. |
| brand | string | Nombre de la marca/negocio. |
| name | string | Nombre del prospecto. |
| company | string | Empresa del prospecto (puede venir vacío). |
| string | Email (puede venir vacío). | |
| phone | string | Teléfono/WhatsApp (puede venir vacío). |
| contact | string | El teléfono si existe, si no el email (contacto principal). |
| summary | string | Resumen que arma la IA de qué busca el prospecto. Acá viajan datos específicos (ej: localidad, medidas). |
| score | number | Puntaje 0-100 (probabilidad de cierre por intención). |
| temperature | string | "caliente" (≥80) · "tibio" (40-79) · "frio" (<40). |
| source | string | "landing" o "widget" (dónde entró). |
| utm_source | string | Fuente de la campaña (ej: google, meta). |
| utm_medium | string | Medio (ej: cpc, paid). |
| utm_campaign | string | Campaña (vacío si es orgánico). |
| page | string | Página/contexto donde se capturó. |
| assignedTo | string | Vendedor asignado. Vacío = sin asignar (asignás vos en el CRM). |
Nota: los datos específicos del rubro que el bot capture en la conversación (por ejemplo: medidas, color, tamaño, modelo, zona, presupuesto, tipo de servicio, etc., según el negocio) no vienen como campos sueltos — viajan dentro de summary. Los campos estructurados fijos son los de la tabla de arriba.
Importante para el mapeo: los nombres de campo son exactamente los de la tabla, en minúscula (email, phone — no Email, telefono ni mail) y viajan en el primer nivel del JSON. Un mapeo que lee otra clave no falla con error: simplemente recibe vacío. Si un campo te llega vacío en tu CRM, revisá primero la clave que estás leyendo — el envío nunca sale con email y teléfono vacíos a la vez.
Ejemplo real
Un lead como te va a llegar
{
"event": "new_lead",
"tenantId": "…",
"leadId": "abc123",
"brand": "Tu Negocio",
"name": "Juan Perez",
"company": "",
"email": "juan.perez@correo.com",
"phone": "+5491122334455",
"contact": "+5491122334455",
"summary": "Interesado en tu producto/servicio. Dio los detalles de lo que busca (los específicos del rubro van acá) y quiere avanzar esta semana.",
"score": 90,
"temperature": "caliente",
"source": "landing",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "tu-campana",
"page": "…",
"assignedTo": ""
}Origen del lead
Etiquetá tus campañas para saber de dónde viene cada lead
Cerralo lee las etiquetas utm_* de la URL de la página donde el visitante conversa (también reconoce los click-ids fbclid y gclid que Meta y Google agregan solos). Esas etiquetas viajan en los campos utm_source / utm_medium / utm_campaign del payload. Si no llegan, el lead entra igual, pero figura como directo/orgánico — y no podés medir qué campaña lo trajo.
utm_source=meta&utm_medium=paid&utm_campaign={{campaign.name}}&utm_content={{ad.name}}utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_term={keyword}La trampa del salto entre páginas: si tu anuncio aterriza en una página tuya y desde ahí un botón lleva a la landing conversacional de Cerralo, las etiquetas se quedan en la primera URL y el lead pierde el origen. Solución simple: que ese botón lleve etiquetas fijas, por ejemplo …?utm_source=meta&utm_campaign=mi-campania. Con el widget embebido en tu propio sitio esto no hace falta: toma las etiquetas de tu página solo.
Evento opcional
lead_updated: cuando el contacto se completa después
El webhook new_lead dispara una sola vez, con el primer dato de contacto. Si el prospecto deja el email y recién después el teléfono (o al revés), ese segundo dato llegaba solo al panel de Cerralo. Activando Integración → “Avisar también cuando el contacto se completa”, Cerralo envía un segundo POST con:
- ▸
event: "lead_updated"— mismo JSON y mismos campos quenew_lead, con el contacto ya completo. - ▸ El mismo
leadId— usalo para hacer upsert: buscá el lead y actualizalo, no crees uno nuevo. - ▸ Un
X-Cerralo-Deliverypropio (con sufijo-upd-…): si deduplicás entregas, no lo confundís con la original.
Viene apagado por defecto: si tu receptor trata todo POST como lead nuevo, no lo actives hasta implementar el upsert por leadId — si no, cada actualización se te crearía como un duplicado.
Buenas prácticas
Recomendaciones para la recepción
Seguridad
Recomendaciones
- ▸ Usá una URL de webhook secreta/difícil de adivinar (no la publiques).
- ▸ Validá en tu endpoint que el payload tenga la forma esperada antes de crear el lead.
- ▸ Serví el endpoint por HTTPS.
- ▸ Verificá la firma HMAC (abajo) si cargaste una clave: es la forma de asegurarte de que el lead salió de Cerralo.
Autenticación
Verificar que el lead salió de Cerralo
Si cargás una Clave de firma en Cerralo → Integración, cada envío viaja firmado. Así tu sistema distingue un lead real de alguien que descubrió la URL de tu webhook. Sin clave cargada el envío sale igual, sin firmar.
Cabeceras que enviamos
- ▸
X-Cerralo-Signature—sha256=<hmac>del contenido. - ▸
X-Cerralo-Timestamp— segundos Unix del envío. Rechazá lo que tenga más de 5 minutos. - ▸
X-Cerralo-Delivery— id de la entrega (igual alleadId). Sirve para descartar duplicados. - ▸
X-Cerralo-Event—new_leadolead_updated(coincide con el campoeventdel cuerpo).
Cómo se calcula
HMAC-SHA256 sobre timestamp + "." + cuerpo crudo, usando tu clave. Importante: el cuerpo tal cual llegó, sin volver a serializar el JSON.
# Python (Odoo)
import hmac, hashlib, time
def verificar(cuerpo_crudo: bytes, firma: str, ts: str, clave: str) -> bool:
if abs(time.time() - int(ts)) > 300: # más de 5 min: lo rechazamos
return False
esperado = "sha256=" + hmac.new(
clave.encode(),
f"{ts}.".encode() + cuerpo_crudo,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(esperado, firma) # comparación en tiempo constanteReintentos: si tu endpoint responde 5xx o no responde, reintentamos una vez. Un 4xx lo tomamos como rechazo a propósito y no reintentamos.
¿Dudas sobre la integración? Escribinos a hola@cerralo.online y lo vemos con tu equipo técnico.