Webhook de leads
Notifica a Levely cada vez que un lead se crea o cambia de etapa en tu CRM. El endpoint es idempotente: puedes reintentar el mismo evento sin duplicar historial.
Endpoint
POST https://ads-library.levely.digital/api/webhooks/leads/{slug}/{secret}Levely te asigna un {slug} y un {secret} por cliente. Usa la URL completa tal cual — no modifiques ningún segmento. La autenticación es el secret; no se requieren headers adicionales.
Headers
Content-Type: application/json
Ejemplo con cURL
curl -X POST "https://ads-library.levely.digital/api/webhooks/leads/{slug}/{secret}" \
-H "Content-Type: application/json" \
-d '{
"lead_id": "crm-12345",
"status": "CREATED",
"created_at": "2026-06-04T15:30:00Z",
"utm_source": "facebook",
"utm_campaign": "verano-2026"
}'Payload de ejemplo
{
"lead_id": "crm-12345",
"status": "QUALIFIED",
"created_at": "2026-06-04T15:30:00Z",
"previous_status": "CONTACTED",
"raw_crm_status": "Prospecto calificado",
"utm_source": "facebook",
"utm_medium": "cpc",
"utm_campaign": "verano-2026",
"utm_content": "video-1",
"utm_term": "keyword",
"channel": "facebook",
"platform": "meta",
"contact_info": { "email": "maria@ejemplo.com", "phone": "+52..." },
"form_responses": { "presupuesto": "50000" },
"additional_params": { "vendedor": "ana" }
}| Campo | Tipo | Req. | Descripción |
|---|---|---|---|
| lead_id | string | Sí | Identificador único del lead en tu CRM. No puede estar vacío. |
| status | enum | Sí | Estado normalizado del lead. Valores: CREATED, CONTACTED, QUALIFIED, WON, LOST. |
| created_at | string | number | No | Fecha de creación del lead en tu CRM (ISO 8601 o Unix en segundos/milisegundos). Solo se usa al crear el lead por primera vez. |
| previous_status | enum | No | Estado anterior en tu CRM. Si no lo envías, Levely infiere el estado previo desde su base de datos. |
| raw_crm_status | string | No | Etiqueta original del CRM antes de mapear al enum de Levely. Se guarda en el historial para auditoría. |
| utm_source, utm_medium, utm_campaign, utm_content, utm_term | string | null | No | UTMs de atribución. Se guardan en la creación del lead y no se sobrescriben en actualizaciones. Si envías UTMs en eventos posteriores, se actualiza `latest_utms` sin perder los originales. |
| channel | string | No | Canal de adquisición (ej. facebook, google, organic). |
| platform | string | No | Plataforma publicitaria (ej. meta, google). |
| contact_info | object | No | Datos de contacto libres (email, teléfono, etc.). |
| form_responses | object | No | Respuestas de formulario u otros campos del CRM. |
| additional_params | object | No | Cualquier dato adicional que quieras conservar junto al lead. |
Estados del funnel
Tu CRM puede usar cualquier nomenclatura interna. Antes de llamar al webhook, mapea cada etapa al enum de Levely:
CREATEDLead creado en el CRMCONTACTEDPrimer contacto realizadoQUALIFIEDLead calificado / con intenciónWONVenta cerradaLOSTLead perdido o descartado
Se aceptan saltos de etapa (ej. CREATED → QUALIFIED) y LOST desde cualquier estado. Las transiciones hacia atrás también se registran tal como las envía tu CRM.
Comportamiento del sistema
- Lead nuevo: si
lead_idno existe, se crea el lead y se registra el primer evento de cambio de estado. - Cambio de estado: si el lead ya existe y el
statuses distinto, se actualiza y se agrega un evento al historial. - Idempotencia: si envías el mismo
lead_idcon el mismostatusque ya tiene, la respuesta es 200 sin crear eventos duplicados. - UTMs: los valores enviados en la creación se conservan como atribución original. En actualizaciones, solo se actualiza
latest_utmssi incluyes al menos un UTM no nulo. - Estado anterior: envía
previous_statuscuando tu CRM lo conozca. Si no, Levely lo infiere desde su registro.
Respuestas HTTP
| Código | Body | Cuándo ocurre |
|---|---|---|
| 200 | { "ok": true } | Evento procesado correctamente (incluye reintentos idempotentes). |
| 400 | { "error": "Invalid JSON body" } | El cuerpo no es JSON válido. |
| 401 | { "error": "Invalid webhook secret" } | El secret en la URL no existe o es incorrecto. |
| 422 | { "error": "lead_id is required" } | Falta `lead_id` o está vacío. |
| 422 | { "error": "status must be one of: CREATED, ..." } | El `status` no pertenece al enum permitido. |
| 422 | { "error": "created_at must be ISO 8601 or Unix timestamp" } | Se envió `created_at` pero con formato inválido. |
| 500 | { "error": "Failed to process lead" } | Error interno al persistir el evento. |
En integraciones con reintentos automáticos, un 200 con { "ok": true } confirma que el evento fue aceptado. Los errores 4xx no deben reintentarse sin corregir el payload.
¿Necesitas credenciales o ayuda con el mapeo de estados? Contacta al equipo de Levely.