📄 Documento técnico

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 — POST JSON → tu endpoint / CRM se crea el lead

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

1. Tu equipo técnico prepara un endpoint HTTP que reciba un POST application/json (puede ser un endpoint propio, una función serverless, o el webhook de entrada de tu CRM/automatización).
2. Esa URL se pega en Cerralo → Integración → Webhook y se guarda. Desde ahí, cada lead nuevo se envía solo a esa URL.

El payload (qué manda Cerralo)

Campos del JSON

CampoTipoDescripción
eventstring"new_lead" (primera entrega) · "lead_updated" (opcional, ver sección propia).
tenantIdstringId de la cuenta de Cerralo que originó el lead.
leadIdstringId único del lead. Útil como clave para evitar duplicados en tu CRM.
brandstringNombre de la marca/negocio.
namestringNombre del prospecto.
companystringEmpresa del prospecto (puede venir vacío).
emailstringEmail (puede venir vacío).
phonestringTeléfono/WhatsApp (puede venir vacío).
contactstringEl teléfono si existe, si no el email (contacto principal).
summarystringResumen que arma la IA de qué busca el prospecto. Acá viajan datos específicos (ej: localidad, medidas).
scorenumberPuntaje 0-100 (probabilidad de cierre por intención).
temperaturestring"caliente" (≥80) · "tibio" (40-79) · "frio" (<40).
sourcestring"landing" o "widget" (dónde entró).
utm_sourcestringFuente de la campaña (ej: google, meta).
utm_mediumstringMedio (ej: cpc, paid).
utm_campaignstringCampaña (vacío si es orgánico).
pagestringPágina/contexto donde se capturó.
assignedTostringVendedor 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.

Meta Ads (parámetros de URL del anuncio)
utm_source=meta&utm_medium=paid&utm_campaign={{campaign.name}}&utm_content={{ad.name}}
Google Ads (sufijo final de URL)
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 que new_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-Delivery propio (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

Duplicados
Deduplicá en tu CRM por teléfono/email (o usá leadId). Cerralo no controla la unicidad de tu base.
Asignación
Cerralo puede mandar el lead sin asignar (assignedTo vacío) para que la asignación la manejes vos desde el CRM.
Tiempo real
El webhook dispara apenas se captura el lead. El traspaso es inmediato.
Si tu sistema se cae
Cerralo hace un intento (sin reintento propio). Recomendado: un middleware/cola con reintentos del lado receptor. Además, el lead SIEMPRE queda guardado en Cerralo como respaldo — no se pierde, se puede re-sincronizar.
Piloto
Arrancá con una campaña/landing puntual y pocos leads, validá que el dato llega bien, y escalá.

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-Signaturesha256=<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 al leadId). Sirve para descartar duplicados.
  • X-Cerralo-Eventnew_lead o lead_updated (coincide con el campo event del 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 constante

Reintentos: 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.