Antes de empezar
- Base URL:
https://app.relevantleads.io - Formato: JSON en el cuerpo y en la respuesta. Envía
Content-Type: application/json. El cuerpo debe ser un objeto JSON (un arreglo o un valor suelto se rechaza). - Autenticación: encabezado
Authorization: Bearer <llave>. - Métodos:
POSTen leads y eventos,PATCHen contactos. No hay CORS: el navegador bloquea la llamada, así que llama desde tu servidor, no desde el navegador del usuario final. - Entorno: no existe sandbox ni llaves de prueba. Todas las llaves son
rk_live_y operan sobre la cuenta real. Para probar sin arriesgar datos, usa un embudo de pruebas y leads de prueba.
1. La llave
Una persona con rol Owner o Admin la crea en Ajustes, API, Nueva llave (grupo Admin Center). Al crearla define tres cosas que viven en la llave, no en cada envío:- El embudo y etapa destino por defecto de los leads que entren con ella (tu envío puede sobrescribirlos, ver abajo).
- El origen con el que se etiquetan esos leads en Contactos, Atribución y reportes (por ejemplo “Registro web”; si no se configura, “Registro externo”).
- Su nombre, que aparece en las notas de sistema del chat del lead: “Datos del registro (nombre)” en cada registro con
custom_dataque crea o reutiliza un lead, y “Evento recibido de (nombre)” en cada evento.
rk_live_ seguido de 43 caracteres, 51 en total. Se muestra completa una sola vez al crearla; Relevant solo guarda un hash. Guárdala en variables de entorno o en tu gestor de secretos. Si se pierde, el administrador la revoca y crea otra.
Cada petición autenticada actualiza el Último uso de la llave (aunque después falle por validación), así que quien administra puede ver desde Relevant que tu integración ya está llamando. Una llave revocada responde 401 de inmediato.
Errores de autenticación
2. Registrar un lead
POST /api/v1/leads
Crea el contacto y su lead en el embudo destino. Si la persona ya existe, la reutiliza (ver deduplicación). Es seguro reintentar el mismo envío.
Campos del cuerpo
Los campos de texto opcionales (
external_id, email, country_code, company, location, website, UTMs) que exceden su máximo se recortan en silencio, no se rechazan. Solo name rechaza por longitud. Envía valores dentro de los límites para que lo que guardes coincida con lo que mandaste.
Normalización del teléfono
Relevant quita espacios, guiones, paréntesis, puntos y el+, y aplica estas reglas:
- 10 dígitos: se antepone
country_code(o52)."5512345678"se guarda como525512345678. - Empieza con
521y tiene 13 dígitos: se quita el1(formato viejo de celulares mexicanos)."5215512345678"se guarda como525512345678. - Empieza con
00: se quitan los dos ceros. - De 11 a 15 dígitos (por ejemplo 12 con lada): se guarda tal cual; se asume que ya trae código de país.
- 8 o 9 dígitos: no se guarda. La petición responde
422confields.phoneexplicando el formato (“Debe tener 10 dígitos con lada (por ejemplo “8112345678”) o incluir el código de país (por ejemplo “+528112345678”, máximo 15 dígitos).”).
phone. En un contacto que ya existía, el teléfono guardado no se reemplaza.
Destino del lead
- Por defecto: el embudo y etapa de la llave. Si la llave tiene embudo pero no etapa, la primera etapa del embudo. Si la llave no tiene embudo y el cuerpo tampoco, se crea solo el contacto (
deal_id: null). funnel_iden el cuerpo: se valida que sea de tu cuenta (404si no). La etapa por defecto de la llave se descarta.stage_iden el cuerpo: se valida que sea de tu cuenta (404si no). Si viene sinfunnel_id, el embudo es el de esa etapa.
Respuesta
201 Created cuando se creó el contacto o el lead. 200 OK cuando ambos ya existían y se reutilizaron.
deal_idesnullcuando no hubo embudo destino: se creó solo el contacto.funnel_idystage_idson el embudo y la etapa donde quedó el lead al terminar la petición (Relevant los relee después de crear o reutilizar el lead). Si una automatización con disparador “Nuevo lead en etapa” lo movió al crearse, aquí ves la etapa final, no la de entrada.- Guarda
contact_idydeal_idjunto a tu usuario:deal_idsirve para enviar eventos con precisión, ycontact_idpara corregir el contacto aunque no tenga tuexternal_id(sección 4).
Deduplicación (idempotencia de registros)
- Si envías
external_idy ya existe un contacto con ese valor en tu cuenta, se reutiliza. - Si no envías
external_id, o no coincide con ningún contacto, se busca por los últimos 10 dígitos del teléfono dentro de tu cuenta. Si más de un contacto termina en esos dígitos, se reutiliza el más antiguo (el que tiene el historial). - En un contacto reutilizado se actualizan
nameyemailsi los mandas, y se rellenan los UTMs vacíos. Si el contacto no teníaexternal_idy ahora lo mandas, se le guarda; si ya tenía otro, conserva el que tenía (y un evento con el nuevoexternal_idno lo encontrará: usadeal_ido el teléfono). - Si el contacto ya tiene un lead abierto en el embudo destino, se reutiliza ese lead (
created_deal: false); no se tocan su título, monto ni etapa. Un segundo registro de la misma persona no es una oportunidad nueva. - Si su lead anterior ya se cerró (ganado o perdido), se crea uno nuevo.
custom_data
Se escribe en el chat del lead como una nota de sistema con el formato Datos del registro (nombre de la llave): clave: valor · clave: valor, visible para el equipo. Reglas:
- Se escribe cada vez que el registro tiene lead: cuando lo crea (
created_deal: true) y también cuando reutiliza uno abierto (created_deal: false). Por eso un reintento concustom_datadeja la nota otra vez (sección 7). Si no hay embudo destino (deal_id: null),custom_datase descarta sin error. - Máximo 20 claves (las primeras, en orden), 40 caracteres por clave, 120 por valor, 600 en total. Los valores vacíos o nulos se omiten. Un valor anidado se serializa como texto JSON y se recorta a 120.
- Un arreglo en
custom_datase rechaza con422.
Qué pasa en Relevant al registrar
- El contacto y el lead se crean con el origen de la llave. El lead nace con prioridad Media, estado abierto y título igual a
name. - Sobre un lead nuevo corren las reglas de auto-asignación de la cuenta (reglas, responsable de etapa, responsable de embudo). Si asigna a alguien, esa persona recibe la notificación de lead asignado.
- Automatizaciones al crear: un lead nuevo dispara, dentro de la misma petición, las automatizaciones cuyo disparador “Nuevo lead en etapa” vigile la etapa donde entra; por eso
stage_iden la respuesta puede ser distinto del destino. Un lead reutilizado no dispara nada al registrarse de nuevo, porque no cambia de etapa. Para actuar cuando pase algo después en tu sistema, usa eventos. - No se envía ningún mensaje de WhatsApp al lead.
3. Avisar de un evento del lead
POST /api/v1/events
Úsalo cuando en tu sistema pase algo con un lead ya registrado: un pago, una activación, una cancelación. Relevant registra el evento, lo deja como nota en el chat del lead, notifica a la persona responsable y ejecuta las automatizaciones que estén escuchando ese evento en ese embudo. Si con el evento cambió el precio, el mismo envío puede actualizar el monto del lead (amount).
Campos del cuerpo
Cómo se resuelve el evento
- Relevant localiza al lead: por
deal_idsi viene; si no, porexternal_id; si no coincide, por los últimos 10 dígitos dephone. - Toma sus leads abiertos (todos, o solo los del
funnel_idindicado). Los leads cerrados no se tocan. - Si mandaste
amount, lo escribe en el lead abierto antes de ejecutar nada (ver “Monto del lead” abajo). - Para cada lead abierto, ejecuta cada automatización activa que tenga un disparador Evento externo con ese nombre exacto y con el embudo del lead. En el editor, cada disparador de este tipo está ligado a un embudo; si la persona tiene leads abiertos en dos embudos y mandas el evento sin
funnel_id, ambos leads reciben la nota y la notificación, pero solo se ejecuta la automatización del embudo que coincide. - Deja rastro: registro del evento, nota de sistema
Evento recibido de <nombre de la llave>: <event> (<resumen del payload>)en el chat de cada lead abierto alcanzado (si el evento cambió el monto, la nota termina con· Monto: <anterior> → <nuevo>), y notificación dentro de la app a la persona asignada a cada uno. - Si la automatización tiene la acción Enviar plantilla, el lead recibe un Mensaje de WhatsApp aprobado en cuanto llega el evento, con sus variables tomadas del
payload(por ejemplo{{2}}= clavemonto), de los datos del contacto o del lead, o de texto fijo; si a una variable le falta el valor, no se envía y el chat lo dice. Cada mensaje entregado se cobra como difusión. Cómo se configura, en Automatizaciones.
Monto del lead (amount)
- El monto se escribe antes de ejecutar las automatizaciones: si una de ellas marca el lead como ganado o manda una plantilla con Monto del lead, ya ve el nuevo.
- Solo cambia leads abiertos. Si el evento no alcanza ninguno (
outcome: "no_open_deals"), el monto se ignora. - El monto es de un lead. Si el contacto tiene varios leads abiertos y el evento los alcanza a todos, la respuesta es
422 validation_errorconfields.amount(“El evento alcanza N leads abiertos de este contacto. Envía deal_id o funnel_id para indicar a cuál aplicar el monto.”) y no se registra ni se ejecuta nada: laidempotency_keyqueda libre. Reenvía condeal_id, o confunnel_idsi el contacto tiene un solo lead abierto en ese embudo. - Si el monto cambió, la nota del evento en el chat lo dice al final:
· Monto: $4,640 → $4,176.50(si el lead no tenía monto,sin monto → $4,176.50). Si era el mismo, no se escribe nada. - Un reintento con la misma
idempotency_keyno vuelve a escribir el monto: devuelve elamount_updatedel envío original. - Si la respuesta es
500, el lead se queda con el monto que tenía antes del envío (salvo que alguien lo haya cambiado mientras tanto) y la clave queda libre: el reintento con la mismaidempotency_keylo escribe.
Límites del payload
Relevant rechaza el evento completo (422 validation_error) cuando el payload:
- tiene más de 20 claves (“Máximo 20 claves.”);
- trae una clave vacía o de más de 40 caracteres (“Cada clave debe tener entre 1 y 40 caracteres.”);
- trae un valor que es objeto o lista (“La clave “x” debe ser texto, número, booleano o null, no un objeto ni una lista.”);
- trae un texto de más de 500 caracteres (“El valor de “x” supera 500 caracteres.”);
- pesa más de 4 KB en total (“El payload completo supera 4096 bytes.”).
Respuesta
200 OK siempre que el lead exista, aunque no tenga leads abiertos o ninguna automatización lo escuche.
amount_update es null cuando no mandaste amount o el evento no alcanzó ningún lead abierto. Si no, trae el lead (deal_id), el monto que tenía (previous, puede ser null), el que mandaste (amount) y si de verdad cambió (changed). changed: false significa que ya tenía ese monto o que el lead se cerró justo antes de escribirlo.
Si el lead no existe:
404 not_found, con field igual a deal_id, external_id o phone según lo que mandaste. Regístralo primero con POST /api/v1/leads.
Idempotencia de eventos
- La
idempotency_keyes única por cuenta y no caduca: la misma clave meses después sigue devolviendo el resultado original. - Un reintento con una clave ya recibida responde
200conduplicate: true, eloutcomey elamount_updateoriginales, y sin el arreglodeals. No se ejecuta nada ni se vuelve a escribir el monto. - Si dos envíos con la misma clave llegan al mismo tiempo, solo uno ejecuta: la clave se reserva antes de ejecutar las automatizaciones. El otro recibe el resultado del primero con
duplicate: true; si el primero sigue en proceso, Relevant espera hasta 2 segundos y, si aún no termina, responde conoutcome: "pending". - En el caso raro de que ese resultado original no se pueda leer, el segundo envío recibe
409 conflict. Reintenta una vez: obtendrás el resultado original conduplicate: true. - Un
422poramounto un500no gastan la clave: reenvía con la mismaidempotency_key.
4. Corregir un contacto
PATCH /api/v1/contacts
Úsalo cuando en tu sistema se corrija un dato de un contacto que ya registraste: el nombre, el teléfono, el correo, la empresa. Reenviar POST /api/v1/leads no sirve para eso: no cambia el teléfono, no borra datos y, si el lead ya se cerró, abre uno nuevo.
Cómo se identifica el contacto
Exactamente uno de estos dos:
Si mandas los dos, o ninguno:
422 validation_error. Solo se buscan contactos de tu cuenta: si no existe, 404 not_found con field igual a external_id o contact_id.
Campos que se pueden cambiar
Un campo que no mandas no se toca. Un campo connull o "" se borra, salvo name y phone, que no se pueden borrar (mandarlos vacíos o con null da 422).
A diferencia del registro, un texto que pasa del máximo se rechaza con
422 en vez de recortarse: es una corrección y tiene que quedar exactamente lo que mandaste. Cualquier otro campo también da 422 con el detalle en fields: los del registro que aquí no van (funnel_id, stage_id, amount, custom_data, UTMs y referrer_url) y uno mal escrito. Para cambiar el monto del lead, usa amount en eventos (sección 3).
Cambio de teléfono
- El mismo número en otro formato (
+52 81 1234 5678,5218112345678o los 10 dígitos) no cuenta como cambio. - Si el número está bloqueado en tu cuenta:
422 blockedconfield: "phone". - Si el número ya es de otro contacto de tu cuenta (se comparan los últimos 10 dígitos):
409 conflictconfield: "phone"yconflict_contact_id. Los contactos nunca se fusionan: corrige el otro contacto o usa otro número. - El historial de WhatsApp se queda en el contacto. Si la persona vuelve a escribir desde el número viejo, entra como un contacto nuevo.
- La ventana de 24 horas que contaba Relevant era del número viejo: Relevant la da por cerrada en los leads abiertos del contacto. Limitación conocida: en el chat la ventana todavía puede verse abierta por los mensajes del número viejo. Si un mensaje de texto libre al número nuevo falla, manda una plantilla aprobada.
Lo que no hace
No crea, mueve, cierra ni reabre leads, y no cambia su título, monto ni etapa. No asigna ni cambia elexternal_id del contacto: solo sirve para encontrarlo. No dispara automatizaciones, reglas de asignación ni notificaciones, no escribe en el chat y no manda WhatsApp.
Respuesta
200 OK, también cuando no cambió nada: repetir el mismo cuerpo devuelve changed: [].
changed lista solo los campos que de verdad cambiaron. contact es cómo quedó el contacto; phone es el teléfono guardado (dígitos con lada, sin +).
5. Errores
Todas las respuestas de error tienen esta forma:
Orden de evaluación en los tres endpoints: autenticación (401), cuerpo (413, 400), formato de los campos (422), existencia de identificadores (404), proceso (500). Después del
404 todavía pueden llegar estas respuestas: en leads, el 422 de stage_id que no pertenece al embudo y el 422 blocked; en eventos, el 422 por amount con varios leads abiertos; en contactos, el 422 blocked y el 409 conflict por el teléfono. Un evento con una idempotency_key ya recibida se contesta como duplicado justo después de revisar el formato, antes de validar funnel_id.
6. Límites y comportamiento
- Tamaño del cuerpo: 16 KB.
- Límite de tasa: no hay. La llave registra su último uso y puede revocarse al instante; ese es el mecanismo para detectar y cortar un abuso. Si vas a enviar volúmenes altos (miles por hora), avísanos antes a soporte@relevantleads.io.
- Recortes silenciosos (leads y eventos):
external_ideidempotency_keya 128,emaila 254, UTMs a 500,country_codea 4 caracteres. En contactos no se recorta nada: un texto más largo que su máximo da422. - Plan: el registro de leads, los eventos y la corrección de contactos funcionan en todos los planes. No hay validación de plan en estos endpoints.
- Sin sandbox. Métodos:
POSTen leads y eventos,PATCHen contactos. No hay CORS: el navegador bloquea la llamada, así que llama desde tu servidor, no desde el navegador del usuario final. - Edición de llaves: quien administra la cuenta (Owner o Admin) puede editar una llave sin revocarla: nombre, embudo destino, etapa destino, origen y color. La llave sigue siendo la misma, así que tu sistema no cambia nada. Los leads que ya entraron con ella conservan su origen y lo muestran con el nombre y el color nuevos. La revocación no borra el historial de los leads que entraron con ella.
7. Tiempos de respuesta, timeouts y reintentos
Tiempos medidos el 31 de octubre de 2026, con la API en Oregón (EE. UU.), desde que el cliente envía la petición hasta que recibe la respuesta, una petición a la vez:POST /api/v1/leads: ~0.9 s típico. La primera llamada en frío, después de un rato sin tráfico, puede tardar hasta ~2 s.POST /api/v1/events: ~0.75 s típico.
- En leads es seguro: el reintento no crea otro contacto ni otro lead (ver deduplicación en la sección 2). Si mandaste
custom_data, su nota puede aparecer dos veces en el chat del lead. - En eventos, reintenta con la misma
idempotency_key. Si el primer envío sí llegó, recibes su resultado conduplicate: truey las automatizaciones no se ejecutan otra vez. Sinidempotency_key, un reintento puede ejecutarlas dos veces. - En contactos es seguro: repetir el mismo cuerpo no cambia nada más (
changed: []).
409 conflict de eventos, ver la sección 5): revisa code y message. Si el reintento también falla, no lo repitas en bucle: guárdalo y vuelve a intentarlo más tarde desde tu sistema.
Conexión. Si mandas varias peticiones seguidas (por ejemplo, una carga de leads), reutiliza la conexión HTTP (keep-alive) en vez de abrir una nueva por petición: te ahorras establecer la conexión (TCP y TLS) en cada una. Los tiempos de arriba se midieron abriendo una conexión nueva por petición.
8. Buenas prácticas
- Manda siempre
external_id: hace seguros los reintentos y es lo que identifica al lead cuando envías eventos. - Guarda el
deal_idque te devuelve el registro y úsalo en los eventos: es la forma más precisa, evita ambigüedades si la persona tiene varios leads y, si mandasamount, evita el422por varios leads abiertos. - Guarda también el
contact_id: con él puedes corregir el contacto aunque no tenga tuexternal_id. - En eventos, manda siempre
idempotency_key; construye la clave con algo que identifique la acción de negocio (por ejemplopago-<id de tu pago>), no con la fecha y hora del envío. - Configura un timeout de 15 s y un solo reintento (sección 7).
- Manda
country_codeexplícito si tus usuarios no son solo de México, y el teléfono con exactamente 10 dígitos o ya con lada. - Usa una llave por sistema. Si necesitas que dos sistemas cuenten como el mismo origen en reportes, dales el mismo texto de origen al crearlas.
- Antes de conectar, pide a quien administra Relevant que pruebe la automatización con el botón Probar con un lead y que te pase el nombre exacto del evento.
¿Necesitas ayuda? Escríbenos a soporte@relevantleads.io y con gusto te apoyamos.