Introducción

La API de Leader permite gestionar todo el ciclo de ventas programáticamente: contactos, empresas, deals, cotizaciones, facturas, contratos y pagos. Diseñada para integraciones con agentes de IA, aplicaciones externas y automatizaciones.

Los IDs son UUID (texto). Los recursos REST devuelven los montos decimales como texto ("44000.00"); los endpoints de la app de asesores y del cotizador, como número. Todo se acota a la funeraria del usuario del token: un id de otra funeraria responde 404.

Recaudo es el único orquestador de cobros y mensajería: las ligas de pago, los WhatsApp y los flujos de automatización salen por la cuenta de Recaudo de cada funeraria.

Límites: auth/login 5 por minuto; auth/register 3 por hora; abonos/{id}/link-de-pago 30 por minuto. Al pasarlos, 429 con Retry-After.

Base URL

https://www.leaderapp.mx/api/v1
Content-Type: application/json
Accept: application/json
Authorization: Bearer {token}
Autenticación
Laravel Sanctum bearer tokens. Incluye el token en cada solicitud autenticada.
POST /api/v1/auth/login
Pública
Obtener token de autenticación.

Body

Campo Tipo Requerido Descripción
email string Sí Email del usuario
password string Sí Contraseña del usuario
curl -X POST https://www.leaderapp.mx/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "email": "andres.vega@example.com",
    "password": "secreto123"
  }'
Ver respuesta de ejemplo
{
  "token": "1|abc123def456ghi789jkl012mno345pqr678stu901",
  "user": {
    "id": "1e78680c-20f6-5707-89f5-878ef8dc9655",
    "name": "Andrés Vega",
    "email": "andres.vega@example.com",
    "role": "admin",
    "avatar_url": null
  },
  "tenant": {
    "id": "1e78680c-20f6-5707-89f5-878ef8dc9655",
    "name": "Funeraria San Ángel"
  }
}
POST /api/v1/auth/register
Pública
Registrar nuevo usuario y tenant.

Body

Campo Tipo Requerido Descripción
name string Sí Nombre completo (max 255)
email string Sí Email único
password string Sí Min 8 caracteres
password_confirmation string Sí Debe coincidir con password
tenant_name string Sí Nombre de la empresa (max 255)
curl -X POST https://www.leaderapp.mx/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Laura Ortiz",
    "email": "laura.ortiz@example.com",
    "password": "MiPassword2024!",
    "password_confirmation": "MiPassword2024!",
    "tenant_name": "Funeraria del Valle"
  }'
Ver respuesta de ejemplo
{
  "token": "2|xyz789abc123def456ghi789jkl012mno345pqr678",
  "user": {
    "id": "90d3e872-a1e6-522d-aa3b-cc9b53df2bb0",
    "name": "Laura Ortiz",
    "email": "laura.ortiz@example.com",
    "role": "admin",
    "avatar_url": null
  },
  "tenant": {
    "id": "90d3e872-a1e6-522d-aa3b-cc9b53df2bb0",
    "name": "Funeraria del Valle"
  }
}
POST /api/v1/auth/logout
Auth
Cerrar sesión e invalidar el token.
curl -X POST https://www.leaderapp.mx/api/v1/auth/logout \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{ "message": "Logged out successfully." }
GET /api/v1/auth/me
Auth
Obtener usuario y tenant actual.
curl https://www.leaderapp.mx/api/v1/auth/me \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": {
    "id": "1e78680c-20f6-5707-89f5-878ef8dc9655",
    "name": "Andrés Vega",
    "email": "andres.vega@example.com",
    "role": "admin",
    "avatar_url": null
  },
  "tenant": {
    "id": "1e78680c-20f6-5707-89f5-878ef8dc9655",
    "name": "Funeraria San Ángel"
  }
}
Formato de Respuesta
Todas las respuestas usan formato JSON estandar de Laravel.

Recurso individual

{
  "data": {
    "id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
    "first_name": "Andrés",
    "last_name": "Vega"
  }
}

Lista paginada

{
  "data": [ ... ],
  "links": { "first": "...", "next": "..." },
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total": 112
  }
}

Códigos de Error

Código Significado
200 Exito
201 Recurso creado
401 No autenticado -- token invalido o faltante
403 Prohibido -- permisos insuficientes
404 Recurso no encontrado
422 Error de validación -- revisar objeto errors
429 Rate limit -- revisar header Retry-After
500 Error interno del servidor
Contactos
Gestiona los contactos del CRM.
GET /api/v1/contacts
Auth
Listar todos los contactos con paginación y filtros.

Parámetros

Campo Tipo Requerido Descripción
search string No Buscar por nombre, email o teléfono
lifecycle_stage string No Etapa: subscriber, lead, mql, sql, opportunity, customer, evangelist
owner_id uuid No Filtrar por propietario asignado
company_id uuid No Filtrar por empresa
per_page integer No Resultados por página (default 25, max 100)
curl "https://www.leaderapp.mx/api/v1/contacts?search=garcia&lifecycle_stage=lead&per_page=10" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
      "full_name": "Elena Ruiz",
      "email": "elena.ruiz@example.com",
      "phone": "55 0000 1234",
      "lifecycle_stage": "lead",
      "lead_score": 45
    }
  ],
  "meta": { "current_page": 1, "per_page": 10, "total": 3 }
}
GET /api/v1/contacts/{id}
Auth
Obtener un contacto con todos sus datos.
curl https://www.leaderapp.mx/api/v1/contacts/9fd7866a-9330-576a-a943-9bf3657b7ada \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": {
    "id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
    "first_name": "Elena",
    "last_name": "Ruiz",
    "full_name": "Elena Ruiz",
    "emails": [{ "email": "elena.ruiz@example.com" }],
    "phones": [{ "number": "55 0000 1234", "type": "mobile", "country_code": "+52" }],
    "job_title": "Directora Comercial",
    "company": { "id": "53a90367-ec30-553f-93eb-81e507e0e461", "name": "Soluciones Integrales SA de CV" },
    "lifecycle_stage": "lead",
    "lead_score": 45,
    "owner": { "id": "1e78680c-20f6-5707-89f5-878ef8dc9655", "name": "Andrés Vega" },
    "source": "referral",
    "city": "Monterrey",
    "country": "México",
    "custom_fields": { "rfc": "GALM850101ABC" },
    "created_at": "2025-03-15T10:30:00.000000Z"
  }
}
POST /api/v1/contacts
Auth
Crear un nuevo contacto.

Body

Campo Tipo Requerido Descripción
first_name string Sí Nombre (max 255)
last_name string No Apellido (max 255)
emails array No [{"email": "a@b.com"}]
phones array No Array de telefonos
job_title string No Puesto (max 255)
company_id uuid No ID de empresa existente
lifecycle_stage string No subscriber, lead, mql, sql, opportunity, customer, evangelist
source string No Fuente del lead
city string No Ciudad
custom_fields object No Pares clave-valor personalizados
curl -X POST https://www.leaderapp.mx/api/v1/contacts \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "first_name": "Roberto",
    "last_name": "Hernandez Ruiz",
    "emails": [{"email": "roberto.hernandez@example.com"}],
    "phones": [{"number": "55 0000 4321", "type": "work"}],
    "job_title": "Gerente de Compras",
    "company_id": "53a90367-ec30-553f-93eb-81e507e0e461",
    "lifecycle_stage": "lead",
    "source": "website",
    "city": "Guadalajara"
  }'
Ver respuesta de ejemplo
{ "data": { "id": "a0991979-1dd1-5bad-ae49-e6a2746d6571", "first_name": "Roberto", "last_name": "Hernandez Ruiz", "..." } }
PUT /api/v1/contacts/{id}
Auth
Actualizar un contacto. Mismos campos que crear, todos opcionales.
curl -X PUT https://www.leaderapp.mx/api/v1/contacts/9fd7866a-9330-576a-a943-9bf3657b7ada \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "lifecycle_stage": "customer", "job_title": "Directora General" }'
DELETE /api/v1/contacts/{id}
Auth
Eliminar un contacto.
curl -X DELETE https://www.leaderapp.mx/api/v1/contacts/9fd7866a-9330-576a-a943-9bf3657b7ada \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
GET /api/v1/contacts/{contact_id}/notes
Auth
Listar notas de un contacto.
curl https://www.leaderapp.mx/api/v1/contacts/9fd7866a-9330-576a-a943-9bf3657b7ada/notes \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "4c0921ef-047b-5976-b855-f8b14ac194b6",
      "body": "Llamada de seguimiento: interesado en plan empresarial.",
      "user_name": "Andrés Vega",
      "created_at": "2025-04-01T09:15:00.000000Z"
    }
  ]
}
POST /api/v1/contacts/{contact_id}/notes
Auth
Agregar una nota a un contacto.

Body

Campo Tipo Requerido Descripción
body string Sí Texto de la nota
is_pinned boolean No Fijar al inicio (default: false)
curl -X POST https://www.leaderapp.mx/api/v1/contacts/9fd7866a-9330-576a-a943-9bf3657b7ada/notes \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "body": "Reunion programada para el viernes 18 a las 10am.", "is_pinned": true }'
Empresas
Gestiona las empresas del CRM.
GET /api/v1/companies
Auth
Listar empresas con búsqueda y paginación.

Parámetros

Campo Tipo Descripción
search string Buscar por nombre de empresa
per_page integer Resultados por página (default 25, max 100)
curl "https://www.leaderapp.mx/api/v1/companies?search=soluciones" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "53a90367-ec30-553f-93eb-81e507e0e461",
      "name": "Soluciones Integrales SA de CV",
      "industry": "Tecnologia",
      "contacts_count": 12
    }
  ]
}
GET /api/v1/companies/{id}
Auth
Obtener detalle de una empresa.
curl https://www.leaderapp.mx/api/v1/companies/53a90367-ec30-553f-93eb-81e507e0e461 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": {
    "id": "53a90367-ec30-553f-93eb-81e507e0e461",
    "name": "Soluciones Integrales SA de CV",
    "domain": "soluciones-integrales.mx",
    "industry": "Tecnologia",
    "employee_range": "51-200",
    "annual_revenue": 15000000,
    "phone": "55 0000 5555",
    "email": "contacto@soluciones-integrales.mx",
    "tax_id": "SIN850101ABC",
    "contacts_count": 12,
    "owner_id": "1e78680c-20f6-5707-89f5-878ef8dc9655"
  }
}
POST /api/v1/companies
Auth
Crear una nueva empresa.

Body

Campo Tipo Requerido Descripción
name string Sí Nombre de la empresa (max 255)
domain string No Dominio web
industry string No Industria
employee_range string No Ej. "1-10", "51-200"
annual_revenue numeric No Ingreso anual
tax_id string No RFC (max 100)
curl -X POST https://www.leaderapp.mx/api/v1/companies \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Distribuidora del Norte SA de CV",
    "domain": "distnorte.mx",
    "industry": "Distribucion",
    "employee_range": "11-50",
    "annual_revenue": 8500000,
    "phone": "55 0000 8888",
    "email": "contacto@example.com",
    "tax_id": "DNO900515XYZ"
  }'
PUT /api/v1/companies/{id}
Auth
Actualizar una empresa. Mismos campos, todos opcionales.
curl -X PUT https://www.leaderapp.mx/api/v1/companies/53a90367-ec30-553f-93eb-81e507e0e461 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "annual_revenue": 18000000 }'
DELETE /api/v1/companies/{id}
Auth
Eliminar una empresa.
curl -X DELETE https://www.leaderapp.mx/api/v1/companies/53a90367-ec30-553f-93eb-81e507e0e461 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Deals
Gestiona oportunidades de negocio en el pipeline.
GET /api/v1/deals
Auth
Listar deals con filtros por pipeline, etapa y propietario.

Parámetros

Campo Tipo Descripción
pipeline_id uuid Filtrar por pipeline
stage_id uuid Filtrar por etapa
owner_id uuid Filtrar por propietario
search string Buscar por nombre del deal
curl "https://www.leaderapp.mx/api/v1/deals?pipeline_id=10ff6166-58fc-50f3-9926-4ca5cef28080&owner_id=1e78680c-20f6-5707-89f5-878ef8dc9655" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e",
      "name": "Implementacion ERP - Distribuidora del Norte",
      "amount": 450000,
      "stage": { "id": "d3bc1dd2-de9d-5255-ad46-35dec602e1a0", "name": "Propuesta", "color": "#F59E0B", "type": "open" },
      "probability": 50,
      "owner": { "id": "5b0f63f5-3c5b-5d6e-9a43-4f0e0b9c2a11", "name": "Andrés Vega" }
    }
  ]
}
GET /api/v1/deals/{id}
Auth
Obtener detalle de un deal con contactos asociados.
curl https://www.leaderapp.mx/api/v1/deals/f9088753-fb0b-58d8-8892-93d2dc6f9e2e \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": {
    "id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e",
    "name": "Implementacion ERP - Distribuidora del Norte",
    "amount": 450000,
    "currency": "MXN",
    "probability": 50,
    "pipeline_id": "10ff6166-58fc-50f3-9926-4ca5cef28080",
    "stage_id": "d3bc1dd2-de9d-5255-ad46-35dec602e1a0",
    "stage": { "id": "1e78680c-20f6-5707-89f5-878ef8dc9655", "name": "Propuesta", "color": "#F59E0B", "type": "open" },
    "expected_close_date": "2025-06-30",
    "contacts": [
      { "id": "3faa006a-3bc7-59d5-879d-c6bc18e071b4", "full_name": "Elena Ruiz", "email": "elena.ruiz@example.com", "phone": "55 0000 1234" }
    ]
  }
}
POST /api/v1/deals
Auth
Crear un nuevo deal. Requiere pipeline_id y stage_id.

Body

Campo Tipo Requerido Descripción
name string Sí Nombre del deal (max 255)
pipeline_id uuid Sí ID del pipeline
stage_id uuid Sí ID de la etapa
amount numeric No Valor del deal
currency string No Ej. "MXN", "USD"
expected_close_date date No Fecha esperada de cierre (YYYY-MM-DD)
contact_ids array No IDs de contactos a asociar
curl -X POST https://www.leaderapp.mx/api/v1/deals \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Consultoria Fiscal Q3 - Funeraria del Valle",
    "amount": 180000,
    "currency": "MXN",
    "pipeline_id": "10ff6166-58fc-50f3-9926-4ca5cef28080",
    "stage_id": "938477ef-ab96-55e6-82e9-b72cecea54dd",
    "expected_close_date": "2025-07-15",
    "contact_ids": ["9fd7866a-9330-576a-a943-9bf3657b7ada", "f850a2cd-0bc9-5428-bf9f-a5103a64ca45"]
  }'
PUT /api/v1/deals/{id}
Auth
Actualizar un deal. Soporta contact_ids para sincronizar contactos.
curl -X PUT https://www.leaderapp.mx/api/v1/deals/f9088753-fb0b-58d8-8892-93d2dc6f9e2e \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "amount": 500000, "probability": 75 }'
DELETE /api/v1/deals/{id}
Auth
Eliminar un deal.
curl -X DELETE https://www.leaderapp.mx/api/v1/deals/f9088753-fb0b-58d8-8892-93d2dc6f9e2e \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/deals/{id}/move-stage
Auth
Mover un deal a otra etapa del pipeline.

Body

Campo Tipo Requerido Descripción
stage_id uuid Sí ID de la nueva etapa
curl -X POST https://www.leaderapp.mx/api/v1/deals/f9088753-fb0b-58d8-8892-93d2dc6f9e2e/move-stage \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"stage_id": "df306fe5-7c37-5b4e-86f0-ca0a30bf7528"}'
Actividades
Tareas, llamadas, reuniones y emails vinculados a contactos o deals.
GET /api/v1/activities
Auth
Listar actividades con filtros por usuario, estado y tipo.

Parámetros

Campo Tipo Descripción
user_id uuid Filtrar por usuario asignado
status string pending, completed, cancelled
type string call, email, meeting, task
activitable_type string Ej. App\Models\Contact
activitable_id string ID de la entidad relacionada
curl "https://www.leaderapp.mx/api/v1/activities?status=pending&type=call" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "e11ce6b9-65bc-5e27-8cca-fa66cb32ca43",
      "subject": "Llamada de seguimiento con Elena Ruiz",
      "type": "call",
      "status": "pending",
      "priority": "high",
      "due_at": "2025-04-15T10:00:00.000000Z",
      "completed_at": null,
      "user_id": "1e78680c-20f6-5707-89f5-878ef8dc9655",
      "notes": "Preguntar por la decision sobre la propuesta."
    }
  ]
}
POST /api/v1/activities
Auth
Crear una nueva actividad.

Body

Campo Tipo Requerido Descripción
subject string Sí Asunto de la actividad (max 255)
type string Sí call, email, meeting, task
priority string No low, medium, high
due_at date No Fecha de vencimiento
activitable_type string No App\Models\Contact, App\Models\Deal
activitable_id string No ID de la entidad relacionada
notes string No Notas adicionales
curl -X POST https://www.leaderapp.mx/api/v1/activities \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "subject": "Enviar propuesta a Roberto Hernandez",
    "type": "task",
    "priority": "high",
    "due_at": "2025-04-16T14:00:00Z",
    "activitable_type": "App\\Models\\Deal",
    "activitable_id": "5",
    "notes": "Incluir descuento del 10% por pronto pago."
  }'
PUT /api/v1/activities/{id}
Auth
Actualizar una actividad. Mismos campos, todos opcionales.
curl -X PUT https://www.leaderapp.mx/api/v1/activities/e11ce6b9-65bc-5e27-8cca-fa66cb32ca43 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "priority": "medium", "due_at": "2025-04-18T10:00:00Z" }'
DELETE /api/v1/activities/{id}
Auth
Eliminar una actividad.
curl -X DELETE https://www.leaderapp.mx/api/v1/activities/e11ce6b9-65bc-5e27-8cca-fa66cb32ca43 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/activities/{id}/complete
Auth
Marcar una actividad como completada. Sin body, solo la cierra. Con result (contacted, no_answer, voicemail, callback, converted, not_interested) y notes funciona como en la web: salvo converted y not_interested, pide next con type, subject y due_at posterior a ahora.
curl -X POST https://www.leaderapp.mx/api/v1/activities/e11ce6b9-65bc-5e27-8cca-fa66cb32ca43/complete \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
GET /api/v1/activities/{id}/launch
Auth
La liga para ejecutar la actividad desde el teléfono: wa.me para WhatsApp, tel: para llamada, mailto: para correo y la reunión o la ruta en Google Maps para visitas. Con with_draft=1, en WhatsApp y correo pide un borrador del mensaje a la IA.

Parámetros

Campo Tipo Requerido Descripción
with_draft boolean No Incluir borrador del mensaje
curl "https://www.leaderapp.mx/api/v1/activities/9d90c2b1-6f7e-4d0a-8c51-3e2f1a7b9d10/launch?with_draft=1" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "activity_id": "9d90c2b1-6f7e-4d0a-8c51-3e2f1a7b9d10",
  "type": "whatsapp",
  "url": "https://wa.me/525500001234?text=Hola%20Elena",
  "has_target": true,
  "draft": "Hola Elena, le escribo para confirmar la cita de mañana.",
  "contact": { "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "full_name": "Elena Ruiz", "phone": "55 0000 1234", "email": "elena.ruiz@example.com" }
}
POST /api/v1/activities/{id}/executed
Auth
Registra que la acción se ejecutó. Salvo reuniones y notas, completa la actividad.

Body

Campo Tipo Requerido Descripción
via string No De dónde se ejecutó. Por omisión launcher
Ver respuesta de ejemplo
{ "success": true, "completed": true }
POST /api/v1/activities/{id}/check-in
Auth
Llegada a una visita, con ubicación opcional.

Body

Campo Tipo Requerido Descripción
lat number No -90 a 90
lng number No -180 a 180
Ver respuesta de ejemplo
{ "success": true, "checked_in_at": "2026-10-13T11:02:00-06:00" }
POST /api/v1/activities/{id}/check-out
Auth
Salida de la visita. Completa la actividad.

Body

Campo Tipo Requerido Descripción
outcome string No Cómo terminó la visita (máx. 500)
Ver respuesta de ejemplo
{ "success": true, "checked_out_at": "2026-10-13T12:10:00-06:00", "completed": true }
Masivas, ficha de lead e IA
Operaciones sobre varios registros, la ficha unificada de un lead y borradores de mensajes.
POST /api/v1/bulk/{contacts|deals|activities}
Auth
Aplica una acción a varios registros. Contactos y deals: assign, move_stage, delete. Actividades: complete, reschedule, delete.

Body

Campo Tipo Requerido Descripción
action string Sí Acción
ids array Sí Ids (mínimo uno)
owner_id uuid Para assign Nuevo responsable
lifecycle_stage string Para move_stage (contactos) Etapa de vida
stage_id uuid Para move_stage (deals) Etapa del pipeline
due_at date Para reschedule Nueva fecha
Ver respuesta de ejemplo
{ "affected": 12 }
GET /api/v1/leads/{contactId}
Auth
Ficha de lead: contacto, avance de etapa, métricas, oportunidades activas, historia (cotizaciones, facturas, pagos, notas, actividades) y siguiente acción sugerida.
Ver respuesta de ejemplo
{
  "contact": { "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "full_name": "Elena Ruiz", "lifecycle_stage": "sql", "lead_score": 62 },
  "stage_progress": { "current": "sql", "current_label": "SQL", "stages": [] },
  "metrics": { "deals_open_count": 1, "deals_won_count": 0, "won_revenue": 0, "open_pipeline": 44000, "currency": "MXN", "lead_score": 62, "days_since_contact": 12 },
  "active_deals": [],
  "timeline": [{ "kind": "quote_created", "number": "COT-000231", "total": 44000, "status": "sent" }],
  "next_action": { "label": "Llamar para re-enganchar", "priority": "high", "action": { "kind": "activity.call", "params": { "contact_id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21" } } }
}
POST /api/v1/ai/leads/{contactId}/draft-message
Auth
Borrador de correo o WhatsApp para un lead. Si la IA no está disponible, regresa una plantilla con used_ai en false.

Body

Campo Tipo Requerido Descripción
channel string Sí email o whatsapp
goal string Sí Qué se quiere lograr (máx. 500)
context.last_notes string No Notas recientes
Ver respuesta de ejemplo
{ "subject": null, "body": "Hola Elena, le comparto la cotización que platicamos…", "used_ai": true }
App de asesores
Agenda, inicio, equipo, búsqueda y alta rápida. Formas compactas: un contacto es {id, name, phone, email}; una línea {id, name, code, color}.
GET /api/v1/my-day
Auth
La agenda del asesor por bloques: overdue (vencidas), today, hot_leads, rotting_deals y completed. Solo aparecen los bloques con algo.

Parámetros

Campo Tipo Requerido Descripción
date date No Día a ver (YYYY-MM-DD). Por omisión, hoy
Ver respuesta de ejemplo
{
  "date": "2026-10-13",
  "is_viewing_today": true,
  "week": [{ "date": "2026-10-13", "day_label": "MAR", "day_number": 13, "is_today": true, "is_selected": true, "is_past": false, "pending_count": 4 }],
  "greeting": "Buenos días, Andrés",
  "briefing": "Tienes 4 pendientes hoy y una cotización por vencer.",
  "stats": { "completed_today": 2, "total_today": 6, "progress": 0.33, "open_pipeline_amount": 132000, "rotting_amount": 44000, "currency": "MXN", "streak_days": 3 },
  "blocks": [{ "key": "today", "title": "Hoy", "emphasis": "neutral", "count": 1, "items": [{ "kind": "activity", "subject": "Llamar a Elena Ruiz", "type": "call", "due_at": "2026-10-13T18:00:00-06:00", "is_overdue": false }] }]
}
GET /api/v1/home
Auth
Inicio del asesor: pendientes de hoy, cotizaciones esperando respuesta, contratos por firmar, clientes con abonos atrasados, oportunidades que se enfrían, familias en servicio, tira de indicadores y avance del mes.
Ver respuesta de ejemplo
{
  "data": {
    "greeting_name": "Andrés",
    "today": [{ "id": "9d90c2b1-6f7e-4d0a-8c51-3e2f1a7b9d10", "type": "call", "type_label": "Llamada", "subject": "Llamar a Elena Ruiz", "is_overdue": false, "launch_url": "tel:5500001234" }],
    "quotes_waiting": [{ "number": "COT-000231", "status": "sent", "total": 44000, "payment_summary": "$8,000 + 11 × $3,273" }],
    "contracts_to_sign": [],
    "late_clients": [{ "contract": {}, "contact": {}, "overdue_count": 2, "overdue_amount": 2400, "since": "2026-08-15" }],
    "cooling_deals": [],
    "families_in_service": [{ "order_number": "SRV-0042", "deceased_name": "José Martínez" }],
    "strip": { "signed_month_count": 3, "signed_month_amount": 128000, "open_quotes_count": 5, "open_quotes_amount": 210000, "late_count": 1, "late_amount": 2400, "today_count": 4, "today_overdue": 1 },
    "progress": { "today_done": 2, "today_total": 6, "signed_month_count": 3, "signed_last_month_count": 2, "funnel": { "prospects": 14, "quotes": 5, "signed": 3 } }
  }
}
GET /api/v1/team
Auth
Para quien supervisa: cada persona del equipo con firmados del mes, cotizaciones abiertas, pendientes de hoy y atrasadas, más los totales.
Ver respuesta de ejemplo
{
  "data": {
    "members": [{ "user": { "id": "9c12d3e4-5f60-4a7b-8c9d-0e1f2a3b4c5d", "name": "Laura Ortiz", "initials": "LO", "avatar_url": null }, "signed_month_count": 2, "signed_month_amount": 88000, "open_quotes_count": 4, "today_pending": 3, "overdue_count": 1, "last_activity_at": "2026-10-13T10:15:00-06:00" }],
    "totals": { "members": 1, "signed_month_count": 2, "signed_month_amount": 88000, "open_quotes_count": 4, "today_pending": 3, "overdue_count": 1 }
  }
}

Errores

  • 403: "Esta vista es para quien supervisa un equipo."
GET /api/v1/team/{userId}
Auth
El día de una persona del equipo: lo mismo que /home, más user y pending (sus actividades abiertas, máx. 50).

Errores

  • 403: "No supervisas a esta persona."
  • 404: la persona es de otra funeraria.
GET /api/v1/search
Auth
Búsqueda agrupada según los permisos de quien busca: Servicios, Personas, Contratos (desde 3 caracteres), Cotizaciones y Oportunidades.

Parámetros

Campo Tipo Requerido Descripción
q string Sí 2 a 100 caracteres
Ver respuesta de ejemplo
{ "data": { "groups": [{ "label": "Personas", "items": [{ "type": "contact", "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "label": "Elena Ruiz", "sublabel": "55 0000 1234" }] }] } }
GET /api/v1/contact-sources
Auth
Fuentes de contacto activas con sus subtipos, para el alta.
Ver respuesta de ejemplo
{ "data": [{ "id": "a1f0c2d3-4e5f-4061-8273-9a8b7c6d5e4f", "name": "Redes sociales", "children": [{ "id": "b2e1d3c4-5f60-4172-8384-0b9c8d7e6f50", "name": "Facebook" }] }] }
GET /api/v1/contacts/lookalikes
Auth
Posibles duplicados antes de dar de alta: por teléfono (últimos 10 dígitos) o por nombre completo exacto. Hasta 3.

Parámetros

Campo Tipo Requerido Descripción
first_name string No Nombre
last_name string No Apellidos
phone string No Teléfono
except_id uuid No Excluir este contacto
Ver respuesta de ejemplo
{ "data": [{ "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "name": "Elena Ruiz", "phone": "55 0000 1234", "email": "elena.ruiz@example.com" }] }
POST /api/v1/contacts/quick
contacts.create
Alta rápida: crea el prospecto a nombre de quien llama y, por omisión, una llamada para dentro de una hora. duplicates avisa de contactos parecidos; el contacto se crea de todos modos.

Body

Campo Tipo Requerido Descripción
first_name string Sí Nombre
last_name string Sí Apellidos
phone string No Celular
phone_country_code string No Por omisión +52
email string No Correo
source_id uuid No Fuente o subtipo
schedule_call boolean No Por omisión true
curl -X POST https://www.leaderapp.mx/api/v1/contacts/quick \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "first_name": "Jaime", "last_name": "Ortiz", "phone": "55 0000 5678" }'
Ver respuesta de ejemplo
{
  "data": {
    "contact": { "id": "9d41b8d4-2c3f-4a6b-8d9e-8f7a6b5c4d32", "name": "Jaime Ortiz", "phone": "55 0000 5678", "email": null },
    "activity": { "type": "call", "subject": "Llamar a Jaime Ortiz", "due_at": "2026-10-13T12:00:00-06:00" },
    "duplicates": []
  }
}

Errores

  • 403 sin contacts.create.
  • 422: "Falta el nombre.", "Faltan los apellidos."
Clientes
La lista de personas con su situación y la ficha completa, como en la web.
GET /api/v1/clients
contacts.view
Personas con lo que tienen con la funeraria (plan, cotización o nada), qué sigue y abonos vencidos.

Parámetros

Campo Tipo Requerido Descripción
search string No Máx. 100
vista string No todos, mios, prospectos, clientes
per_page integer No Por omisión 25, máximo 50
Ver respuesta de ejemplo
{
  "data": [{
    "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "name": "Elena Ruiz", "phone": "55 0000 1234", "email": "elena.ruiz@example.com",
    "lifecycle_stage": "customer", "lifecycle_label": "Cliente",
    "situation": { "kind": "plan", "title": "Plan PF-000118", "detail": "Activo · $44,000", "business_line": { "name": "Previsión", "code": "PF" } },
    "next": { "type_label": "Llamada", "subject": "Llamar a Elena Ruiz", "due_at": "2026-10-14T18:00:00-06:00", "is_overdue": false },
    "needs_next_step": false,
    "overdue_installments": 2
  }],
  "meta": { "current_page": 1, "last_page": 1, "total": 1 }
}
GET /api/v1/clients/{contactId}
contacts.view
Ficha: datos del contacto (CURP, RFC, domicilio, fuente), siguiente actividad, planes, cotizaciones, oportunidades, historia y lo que falta para hacer contrato. Cada plan dice cuántos abonos debe (overdue_count), cuánto (overdue_amount) y cuál se cobraría hoy (payable_installment: el vencido más viejo o el siguiente).
Ver respuesta de ejemplo
{
  "data": {
    "contact": { "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "name": "Elena Ruiz", "curp": "RUXE680312MDFZZL09", "date_of_birth": "1968-03-12", "age": 58, "postal_code": "06000" },
    "next_activity": null,
    "contracts": [{
      "id": "9d70e1f2-3a4b-4c5d-8e6f-7a8b9c0d1e2f", "number": "PF-000118", "status": "active", "status_label": "Activo", "value": 44000,
      "overdue_count": 2,
      "overdue_amount": 2400,
      "payable_installment": { "id": "9db0f1e2-d3c4-4b5a-9687-786950a1b2c3", "number": 3, "concept": "Abono 3", "amount": 1200, "due_date": "2026-08-15" }
    }],
    "quotes": [],
    "deals": [],
    "timeline": [{ "kind": "note", "title": "Nota", "body": "Pidió llamada el viernes.", "by": "Andrés Vega" }],
    "missing_for_contract": ["domicilio"]
  }
}
POST /api/v1/clients
contacts.create
Alta completa con las reglas de la web: si viene la CURP, llena nacimiento, sexo y entidad cuando estén vacíos. PUT /api/v1/clients/{contactId} (contacts.edit) acepta los mismos campos.

Body

Campo Tipo Requerido Descripción
first_name, last_name string Sí Nombre y apellidos
email string No Correo
phone, phone_country_code string No Celular y lada
home_phone, office_phone, office_extension string No Otros teléfonos
curp string No 18 caracteres
curp_calculada boolean No La CURP se calculó
rfc string No RFC con formato válido
date_of_birth date No Anterior a hoy
gender string No Femenino, Masculino, No binario
birth_place, occupation string No Máx. 255
street, exterior_number, interior_number, neighborhood, city, state string No Domicilio
postal_code string No Cinco dígitos
source_id uuid No Fuente
lifecycle_stage string No Etapa de vida

Errores

  • 422: "Esa CURP no tiene el formato correcto.", "Ese RFC no tiene el formato correcto.", "El código postal son cinco dígitos."
POST /api/v1/clients/{contactId}/notes
contacts.edit
Agrega una nota a la historia del cliente.

Body

Campo Tipo Requerido Descripción
body string Sí Máx. 5000
Ver respuesta de ejemplo
{ "data": { "kind": "note", "id": "9d81c9e5-3d4a-4b7c-9e0f-9a8b7c6d5e43", "at": "2026-10-13T12:20:00-06:00", "title": "Nota", "body": "Pidió llamada el viernes.", "by": "Andrés Vega" } }
Servicios funerarios
Solo lectura para el teléfono.
GET /api/v1/service-orders
service_orders.view
Servicios con velación, destino final, familia y contrato. 30 por página.

Parámetros

Campo Tipo Requerido Descripción
scope string No open (por omisión), mine, today, all
search string No Folio o nombre de quien falleció (desde 2 caracteres)
Ver respuesta de ejemplo
{
  "data": [{
    "id": "9da0a1b2-c3d4-4e5f-8061-728394a5b6c7", "order_number": "SRV-0042", "deceased_name": "José Martínez",
    "stage": "wake", "stage_label": "Velación", "service_type_label": "Inhumación", "branch": "Sucursal Centro", "is_open": true,
    "wake": { "room": "Sala 2", "starts_at": "2026-10-13T16:00:00-06:00", "ends_at": "2026-10-14T10:00:00-06:00" },
    "disposition": { "type_label": "Inhumación", "at": "2026-10-14T12:00:00-06:00", "place": "Panteón Jardín" },
    "family": { "name": "Marta Martínez", "phone": "55 0000 9012" },
    "contract_number": "PF-000077"
  }],
  "meta": { "current_page": 1, "last_page": 1, "total": 1 }
}
GET /api/v1/service-orders/{id}
service_orders.view
El servicio completo: deceased, stages (done, current, pending), people, reservations, places (con liga a Google Maps), plan (el contrato de previsión con el que se otorga el servicio) y timeline.
Cotizador
Mismo catálogo, filtros en cascada y plan de pagos que la web. Los precios los pone el servidor con la lista elegida; la app solo dice qué producto y cuántos.

La edad del titular ya no filtra planes ni se pide para el contrato: los parámetros age y age_range se ignoran y las respuestas ya no traen age_ranges, age_range ni titular_age.

Las promociones las decide el servidor. El descuento del asesor (ad_hoc_discount) se aplica si cabe en su autorización; si no, la cotización se guarda sin él, queda bloqueada y se pide autorización (ver Solicitudes de descuento).

GET /api/v1/quoting/catalog
quotes.create o contracts.create
Líneas, filtros por atributo con conteos, planes con su precio de lista, adicionales y listas de precios (plazos). Si falta un filtro obligatorio, plans llega vacío y missing_filters dice cuáles faltan.

Parámetros

Campo Tipo Requerido Descripción
business_line_id uuid No Por omisión la predeterminada
price_list_id uuid No Por omisión la de contado de la línea
filters[nombre] string No Valor elegido de un atributo
search string No Texto libre (máx. 100)
limit integer No 1 a 100. Por omisión 24
curl "https://www.leaderapp.mx/api/v1/quoting/catalog?filters[tipo_servicio_pf]=Cremación" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": {
    "business_line_id": "9d1c6a52-4c3e-4b7a-9f0e-2b6f3f1d8a10",
    "price_list_id": "9d1d7b63-5d4f-4c8b-8a1f-3c7a4b2e9b21",
    "business_lines": [{ "id": "9d1c6a52-4c3e-4b7a-9f0e-2b6f3f1d8a10", "name": "Previsión", "code": "PF", "color": "#2563eb" }],
    "filters": [{ "name": "tipo_servicio_pf", "label": "Tipo de servicio", "required": true, "options": [{ "value": "Cremación", "label": "Cremación", "count": 3 }] }],
    "missing_filters": [],
    "plans": [{ "id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "name": "Plan Cremación 60", "price": 44000, "specs": { "tipo_servicio_pf": "Cremación" }, "specs_label": "Cremación", "components_count": 7 }],
    "plans_total": 3,
    "extras": [{ "id": "9d21b2c3-d4e5-4f6a-9b7c-8d9e0f1a2b3c", "name": "Arreglo floral", "category": "Flores", "price": 2200, "image_url": null }],
    "price_lists": [
      { "id": "9d1d7b63-5d4f-4c8b-8a1f-3c7a4b2e9b21", "name": "Contado", "payments": 1, "method": "cash", "method_label": "Contado", "down_payment_type": "none", "down_payment_min_percent": null },
      { "id": "9d1e8c74-6e50-4d9c-9b20-4d8b5c3f0c32", "name": "12 meses", "payments": 12, "method": "bank_reference", "method_label": "Referencia bancaria", "down_payment_type": "percentage", "down_payment_min_percent": 10 }
    ]
  }
}

Errores

  • 403 sin quotes.create ni contracts.create.

Carrito: campos comunes de preview y guardar

Campo Tipo Requerido Descripción
business_line_id uuid Sí Línea de negocio
price_list_id uuid Sí Lista de precios: define plazo y precios
items array Sí Mínimo una partida
items[].product_id uuid No* Producto del catálogo; el precio lo pone el servidor
items[].description string No* Concepto libre (obligatorio sin product_id)
items[].unit_price number No* Precio del concepto libre (obligatorio sin product_id)
items[].quantity number No Mínimo 0.01. Por omisión 1
items[].group string No Plan o Adicionales (por omisión)
down_payment number No Enganche; si es menor al mínimo de la lista se usa el mínimo
promo_codes array No Hasta 10 códigos (sin distinguir mayúsculas)
manual_discount_ids array No Promociones manuales elegidas (uuid)
ad_hoc_discount.percent number No 0 a 100; no junto con amount
ad_hoc_discount.amount number No Monto fijo
ad_hoc_discount.reason string No Obligatorio (mín. 5) al guardar si pasa de la autorización

Bloque discounts de la vista previa

Llave Contenido
applied Promociones aplicadas: id, name, code, activation (automatic, code, manual), benefit, benefit_type, amount, items.
gifts Regalos: discount_id, product_id, description, quantity, unit_price, value. También van al final de items_priced con is_gift en true y precio 0.
available_manual Promociones manuales para elegir: id, name, benefit, selected, eligible, reason.
near_misses Promociones que casi aplican: id, message ("Te faltan $8,000 para 5 % de descuento (Mil más).").
code_errors Códigos que no aplican: code, message. En preview solo informan; al guardar dan 422.
notices Avisos: topes de descuento, promociones que no se combinan.
ad_hoc null o { amount, percent, status, approver_name, request_id }. status: applied, needs_approval (approver_name dice quién lo autorizaría), pending (ya hay solicitud), rejected.
order_discount Descuento a nivel cotización por promociones.
totals { subtotal, descuento, total }. Solo cuenta el descuento del asesor si su estado es applied.
POST /api/v1/quoting/preview
Auth
Precios de lista, promociones, descuento del asesor, plan de pagos y comparativo de plazos, sin guardar nada. Además del carrito acepta compare_price_lists (uuid de listas).
curl -X POST https://www.leaderapp.mx/api/v1/quoting/preview \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "business_line_id": "9d1c6a52-4c3e-4b7a-9f0e-2b6f3f1d8a10",
    "price_list_id": "9d1e8c74-6e50-4d9c-9b20-4d8b5c3f0c32",
    "items": [
      { "product_id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "group": "Plan" },
      { "product_id": "9d21b2c3-d4e5-4f6a-9b7c-8d9e0f1a2b3c" }
    ],
    "down_payment": 10000,
    "promo_codes": ["BUENFIN"],
    "ad_hoc_discount": { "percent": 2 },
    "compare_price_lists": ["9d1d7b63-5d4f-4c8b-8a1f-3c7a4b2e9b21"]
  }'
Ver respuesta de ejemplo
{
  "data": {
    "items_priced": [
      { "product_id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "description": "Plan Cremación 60", "quantity": 1, "unit_price": 44000, "group_name": "Plan", "discount_id": null, "is_gift": false, "line_discount": 0 },
      { "product_id": "9d21b2c3-d4e5-4f6a-9b7c-8d9e0f1a2b3c", "description": "Arreglo floral", "quantity": 1, "unit_price": 2200, "group_name": "Adicionales", "discount_id": null, "is_gift": false, "line_discount": 0 }
    ],
    "subtotal": 46200,
    "descuento": 1904,
    "total": 44296,
    "discounts": {
      "applied": [{ "name": "Buen Fin", "code": "BUENFIN", "activation": "code", "benefit_type": "order_fixed", "amount": 1000 }],
      "gifts": [],
      "available_manual": [],
      "near_misses": [],
      "code_errors": [],
      "notices": [],
      "ad_hoc": { "amount": 904, "percent": 2, "status": "applied", "approver_name": null, "request_id": null },
      "order_discount": 1000,
      "totals": { "subtotal": 46200, "descuento": 1904, "total": 44296 }
    },
    "plan": { "total": 44296, "payments": 12, "is_cash": false, "down_payment": 10000, "minimum_down_payment": 4429.6, "installments": 11, "installment_amount": 3117.82, "summary": "Enganche de $10,000.00 y 11 pagos de $3,117.82" },
    "comparisons": [{ "price_list": { "name": "Contado", "payments": 1 }, "plan": { "total": 41800, "is_cash": true, "summary": "Un solo pago de $41,800.00" } }]
  }
}
POST /api/v1/quoting/quotes
quotes.create (contracts.create con direct)
Guarda la cotización. Con direct en true la convierte en contrato en ese momento, salvo que el descuento del asesor espere autorización: entonces se guarda bloqueada, contract es null y needs_approval es true. Si el cliente tiene una oportunidad abierta, la cotización se liga a ella.

Body

Campo Tipo Requerido Descripción
(campos del carrito) Ver arriba
direct boolean No Hacer el contrato en el mismo paso
contact_id uuid Con direct Cliente
deal_id uuid No Oportunidad
valid_until date No Por omisión hoy + 15 días
notes_client string No Notas para el cliente (máx. 5000)
compare_price_lists array No Plazos a mostrar en el PDF
curl -X POST https://www.leaderapp.mx/api/v1/quoting/quotes \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "business_line_id": "9d1c6a52-4c3e-4b7a-9f0e-2b6f3f1d8a10",
    "price_list_id": "9d1e8c74-6e50-4d9c-9b20-4d8b5c3f0c32",
    "contact_id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21",
    "direct": true,
    "items": [{ "product_id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "group": "Plan" }],
    "down_payment": 8000,
    "ad_hoc_discount": { "percent": 15, "reason": "Cliente con dos planes vigentes" }
  }'
Ver respuesta de ejemplo
{
  "data": {
    "quote": { "id": "9d50b2c3-4d5e-4f6a-8b7c-9d0e1f2a3b4c", "number": "COT-000231", "status": "draft", "total": 44000, "payment_summary": "$8,000 + 11 × $3,273" },
    "contract": null,
    "items_priced": [{ "product_id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "discount_id": null, "description": "Plan Cremación 60", "quantity": 1, "unit_price": 44000, "group_name": "Plan", "is_gift": false }],
    "discounts": {
      "lines": [],
      "totals": { "subtotal": 44000, "descuento": 0, "total": 44000 },
      "is_locked": true,
      "discount_request": { "id": "9d60c3d4-5e6f-4a7b-9c8d-0e1f2a3b4c5d", "status": "pending", "percent": 15, "amount": 6600, "approver_name": "Laura Ortiz" }
    },
    "needs_approval": true,
    "message": "Cotización guardada. El descuento espera la autorización de Laura Ortiz."
  }
}

Errores

  • 403 sin el permiso.
  • 422 contact_id: "Para hacer el contrato elige primero al cliente."
  • 422 items: "Elige un plan o agrega al menos un concepto."
  • 422 promo_code: un mensaje por código que no existe, venció, se agotó o no aplica.
  • 422 ad_hoc_discount.reason: el descuento necesita autorización y no hay motivo.
  • 422 ad_hoc_discount: nadie puede autorizar un descuento así.

Sin descuento pendiente y con direct, contract trae el contrato en borrador con has_wizard y sign_url. discounts.lines[].kind: promotion, code, manual o ad_hoc.

POST /api/v1/quotes/{id}/contract
contracts.create
Hacer contrato desde una cotización viva (draft, sent, viewed o approved, sin contrato y sin vencer), como en la web. La cotización debe ser de quien llama, salvo administradores o quien tenga contracts.delete.
Ver respuesta de ejemplo
{
  "data": {
    "contract": {
      "id": "9d70e1f2-3a4b-4c5d-8e6f-7a8b9c0d1e2f", "number": "PF-000118", "status": "draft", "status_label": "Borrador", "value": 44000,
      "contact": { "name": "Elena Ruiz" }, "signed_at": null,
      "has_wizard": true,
      "sign_url": "https://www.leaderapp.mx/sign/Xk29fQ7rT1"
    }
  }
}

Errores

  • 403: "Esta cotización es de otro asesor."
  • 422 quote: "Esta cotización ya no está vigente o ya se hizo contrato."
  • 422 contact_id: "Asigna el cliente en la cotización primero."
GET /api/v1/quotes/{id}/pdf · /api/v1/contracts/{id}/pdf
quotes.view / contracts.view
El PDF de la cotización o del contrato (application/pdf, inline). Para mandarlo a la familia sin sesión, usa pdf_url de la cotización.
Cotizaciones
Crea y gestiona cotizaciones con líneas de detalle.
GET /api/v1/quotes
Auth
Listar cotizaciones. Filtros: search (folio, título o cliente), mias, vista (abiertas, por_vencer, aceptadas, vencidas), contact_id, deal_id, status. Trae un bloque summary (waiting, expiring, expired, open_amount, accepted_month, accepted_month_amount).

Parámetros

Campo Tipo Descripción
contact_id uuid Filtrar por contacto
deal_id uuid Filtrar por deal
status string draft, sent, viewed, approved, rejected, expired, converted
curl "https://www.leaderapp.mx/api/v1/quotes?status=sent" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "714515e9-827a-53d3-ad19-7b0972533b8b",
      "quote_number": "COT-000008",
      "title": "Propuesta Consultoria Fiscal Q3",
      "status": "sent",
      "total": 208800,
      "subtotal": 180000,
      "tax_total": 28800,
      "currency": "MXN",
      "valid_until": "2025-05-15",
      "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
      "deal_id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e",
      "items": [
        {
          "description": "Consultoria fiscal especializada",
          "quantity": 120,
          "unit_price": 1500,
          "tax_rate": 16,
          "total": 208800
        }
      ]
    }
  ]
}
GET /api/v1/quotes/{id}
Auth
Detalle con partidas, descuentos y plazos comparados. pdf_url es la liga pública al PDF para mandarla a la familia. discounts dice qué se descontó y si hay una autorización pendiente. Las partidas de regalo traen is_gift en true y el discount_id de la promoción. Ya no existe titular_age.
curl https://www.leaderapp.mx/api/v1/quotes/9d50b2c3-4d5e-4f6a-8b7c-9d0e1f2a3b4c \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": {
    "id": "9d50b2c3-4d5e-4f6a-8b7c-9d0e1f2a3b4c",
    "quote_number": "COT-000231",
    "status": "sent",
    "status_label": "Enviada",
    "payment": { "label": "Referencia bancaria 12 meses", "payments": 12, "down_payment": 8000, "installments": 11, "installment_amount": 3272.73 },
    "payment_summary": "$8,000 + 11 × $3,273",
    "converted_contract_id": null,
    "pdf_url": "https://www.leaderapp.mx/q/Hq72pL4xN8.pdf",
    "created_by": { "name": "Andrés Vega" },
    "total": "41800.00",
    "subtotal": "44000.00",
    "discount_total": "2200.00",
    "days_waiting": 2,
    "expires_in_days": 13,
    "items": [
      { "product_id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "discount_id": null, "is_gift": false, "description": "Plan Cremación 60", "unit_price": "44000.00", "group_name": "Plan" },
      { "product_id": "9d21b2c3-d4e5-4f6a-9b7c-8d9e0f1a2b3c", "discount_id": "9d31e5f6-7a8b-4c9d-8e0f-2a3b4c5d6e7f", "is_gift": true, "description": "Regalo: Arreglo floral", "unit_price": "0.00", "group_name": "Regalos" }
    ],
    "discounts": {
      "lines": [{ "kind": "promotion", "discount_id": "9d32f6a7-8b9c-4d0e-9f1a-3b4c5d6e7f80", "name": "Día de Muertos", "code": null, "benefit": "5 % de descuento", "amount": 2200 }],
      "totals": { "subtotal": 44000, "descuento": 2200, "total": 41800 },
      "is_locked": false,
      "discount_request": null
    }
  },
  "comparisons": [{ "label": "Contado", "total": 41800, "payments": 1, "is_cash": true, "summary": "Un solo pago de $41,800.00" }]
}
POST /api/v1/quotes
Auth
Crear una cotización con líneas de detalle. Los totales se calculan automáticamente.

Body

Campo Tipo Requerido Descripción
contact_id uuid Sí ID del contacto
deal_id uuid No ID del deal asociado
title string No Titulo de la cotización
currency string No Moneda (ej. MXN)
valid_until date No Fecha de vigencia
items array Sí Min 1 item: description, quantity, unit_price, tax_rate, discount_percent
curl -X POST https://www.leaderapp.mx/api/v1/quotes \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
    "deal_id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e",
    "title": "Propuesta de Servicios TI",
    "currency": "MXN",
    "valid_until": "2025-05-30",
    "items": [
      { "description": "Licencia ERP anual", "quantity": 1, "unit_price": 250000, "tax_rate": 16 },
      { "description": "Implementacion y capacitacion", "quantity": 80, "unit_price": 2500, "discount_percent": 5, "tax_rate": 16 }
    ]
  }'
PUT /api/v1/quotes/{id}
Auth
Actualizar una cotización. Si se envian items, reemplazan los existentes.
curl -X PUT https://www.leaderapp.mx/api/v1/quotes/714515e9-827a-53d3-ad19-7b0972533b8b \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "valid_until": "2025-06-15" }'
DELETE /api/v1/quotes/{id}
Auth
Eliminar una cotización.
curl -X DELETE https://www.leaderapp.mx/api/v1/quotes/714515e9-827a-53d3-ad19-7b0972533b8b \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/quotes/{id}/send
Auth
Enviar cotización. Cambia estado a "sent".
curl -X POST https://www.leaderapp.mx/api/v1/quotes/714515e9-827a-53d3-ad19-7b0972533b8b/send \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/quotes/{id}/approve
Auth
Aprobar cotización. Cambia estado a "approved".
curl -X POST https://www.leaderapp.mx/api/v1/quotes/714515e9-827a-53d3-ad19-7b0972533b8b/approve \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/quotes/{id}/reject
Auth
Rechazar cotización. Opcionalmente con razón.
curl -X POST https://www.leaderapp.mx/api/v1/quotes/714515e9-827a-53d3-ad19-7b0972533b8b/reject \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"reason": "Presupuesto excede nuestro limite aprobado."}'
Descuentos y promociones
Las promociones se administran en la web. El cotizador las aplica solo; estos endpoints sirven para cotizaciones hechas con POST /quotes.
GET /api/v1/discounts
Auth
Promociones encendidas, las más nuevas primero. activation: automatic, code, manual. benefit_type: order_percent, order_fixed, item_percent, item_fixed, item_price, free_item. status: vigente, programada, vencida, agotada, apagada.

Parámetros

Campo Tipo Requerido Descripción
per_page integer No Por omisión 25
Ver respuesta de ejemplo
{
  "data": [{
    "id": "9d30d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e", "name": "Buen Fin", "code": "BUENFIN", "is_coupon": true,
    "activation": "code", "benefit_type": "order_fixed", "sentence": "$1,000 de descuento con el código BUENFIN",
    "status": "vigente", "stackable": true, "value": "1000.00", "min_subtotal": null,
    "valid_from": "2026-11-13", "valid_until": "2026-11-17", "usage_limit": 200, "usage_limit_per_customer": 1, "usage_count": 12,
    "is_public": true, "is_active": true, "is_currently_valid": true
  }],
  "meta": { "current_page": 1, "last_page": 1, "total": 1, "per_page": 25 }
}
POST /api/v1/discounts/validate-code
Auth
Valida un código. Con quote_id revisa también el límite por cliente y el subtotal mínimo.

Body

Campo Tipo Requerido Descripción
code string Sí Sin distinguir mayúsculas (máx. 64)
quote_id uuid No Cotización contra la que se valida
Ver respuesta de ejemplo
{ "valid": true, "discount": { "id": "9d30d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e", "name": "Buen Fin", "code": "BUENFIN" } }

Errores

  • 404: { "valid": false, "reason": "not_found" }
  • 422: reason expired_or_inactive, usage_limit_reached_for_customer o min_subtotal_not_met (con min_subtotal).
POST /api/v1/quotes/{id}/discounts/apply
Auth
Aplica una promoción del catálogo (discount_id) o un descuento personalizado (custom_percent) si cabe en la autorización del usuario.

Body

Campo Tipo Requerido Descripción
discount_id uuid No Promoción o cupón
custom_percent number No 0 a 100
Ver respuesta de ejemplo
{ "applied": true, "kind": "within_authority", "amount_discounted": 2100, "quote": { "id": "9d50b2c3-4d5e-4f6a-8b7c-9d0e1f2a3b4c", "discount_total": "2100.00", "total": "39900.00" } }

Errores

  • 403: pasa de la autorización ({ "applied": false, "requires_approval": true, "your_max_percent": "5.00" }). Pedir autorización con POST /discount-requests.
  • 422: la promoción no está vigente, llegó a su límite o no se cumple el subtotal mínimo.
  • 423: la cotización espera otra autorización (pending_discount_request_id).
Solicitudes de descuento
Cuando un descuento pasa de la autorización del asesor, la solicitud va a la primera persona de su cadena de mando que puede autorizarlo (o al primer administrador). La cotización queda bloqueada hasta que respondan. Quien autoriza recibe un código de 6 dígitos por correo (vigente 10 minutos); la solicitud vence a las 24 horas.
POST /api/v1/discount-requests
Auth
Pide autorización para un descuento y bloquea la cotización.

Body

Campo Tipo Requerido Descripción
quote_id uuid Sí Cotización
requested_percent number Sí 0.01 a 100
requested_amount number No Monto en pesos
reason string Sí 5 a 500 caracteres
Ver respuesta de ejemplo
{
  "data": {
    "id": "9d60c3d4-5e6f-4a7b-9c8d-0e1f2a3b4c5d",
    "status": "pending",
    "requester": { "name": "Andrés Vega", "email": "andres.vega@example.com" },
    "approver": { "name": "Laura Ortiz", "email": "laura.ortiz@example.com" },
    "quote": { "quote_number": "COT-000231", "subtotal": "44000.00", "total": "44000.00" },
    "requested_percent": "15.00",
    "requested_amount": "6600.00",
    "reason": "Cliente con dos planes vigentes",
    "otp_expires_at": "2026-10-13T17:12:11-06:00",
    "expires_at": "2026-10-14T17:02:11-06:00"
  }
}

Errores

  • 422: "Quote already has a pending discount request." o "No approver available for this discount."
GET /api/v1/discount-requests/pending
Auth
Solicitudes pendientes asignadas a quien llama, paginadas.
POST /api/v1/discount-requests/{id}/verify-otp
Auth
Autoriza con el código del correo. Al quinto intento fallido la solicitud se rechaza sola.

Body

Campo Tipo Requerido Descripción
otp string Sí 6 dígitos

Errores

  • 422: "Invalid OTP.", "OTP has expired. Request a new code.", "Request has expired.", "Request is no longer pending.", "Too many failed attempts. Request was auto-rejected."
POST /api/v1/discount-requests/{id}/approve
Auth
Autoriza con la sesión de quien autoriza (o de un administrador), sin código. Aplica el descuento y desbloquea la cotización.

Body

Campo Tipo Requerido Descripción
comment string No Máx. 500
Ver respuesta de ejemplo
{ "data": { "id": "9d60c3d4-5e6f-4a7b-9c8d-0e1f2a3b4c5d", "status": "approved", "approved_at": "2026-10-13T17:20:00-06:00" } }

Errores

  • 403: "Solo quien debe autorizar este descuento puede hacerlo."
  • 422: "Esta solicitud ya se respondió." o "La solicitud venció. El asesor tiene que pedirla otra vez."
POST /api/v1/discount-requests/{id}/reject
Auth
Rechaza la solicitud. La cotización se desbloquea sin el descuento.

Body

Campo Tipo Requerido Descripción
comment string No Máx. 500; lo ve el asesor

Errores

  • 403: "Only the assigned approver can reject this request."
  • 422: "Request is no longer pending."
Facturas
Crea y gestiona facturas con líneas de detalle y seguimiento de pagos.
GET /api/v1/invoices
Auth
Listar facturas con filtros por contacto, deal y estado.

Parámetros

Campo Tipo Descripción
contact_id uuid Filtrar por contacto
deal_id uuid Filtrar por deal
status string draft, sent, viewed, partial, paid, overdue, cancelled
curl "https://www.leaderapp.mx/api/v1/invoices?status=sent" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "95f1970e-4596-548f-aae7-e2d44d1cf155",
      "invoice_number": "FAC-000004",
      "status": "sent",
      "total": 208800,
      "amount_paid": "438d2c80-c873-5375-b542-3992dec0c6b6",
      "amount_due": 208800,
      "currency": "MXN",
      "issued_at": "2025-04-05T00:00:00.000000Z",
      "due_at": "2025-05-05T00:00:00.000000Z",
      "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
      "deal_id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e"
    }
  ]
}
GET /api/v1/invoices/{id}
Auth
Obtener detalle de una factura con items.
curl https://www.leaderapp.mx/api/v1/invoices/95f1970e-4596-548f-aae7-e2d44d1cf155 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/invoices
Auth
Crear factura con líneas de detalle. Número de factura auto-generado (FAC-XXXXXX).

Body

Campo Tipo Requerido Descripción
contact_id uuid Sí ID del contacto
deal_id uuid No ID del deal asociado
currency string No Moneda (max 10)
due_at date No Fecha de vencimiento
items array Sí Min 1 item: description, quantity, unit_price, tax_rate
curl -X POST https://www.leaderapp.mx/api/v1/invoices \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
    "deal_id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e",
    "currency": "MXN",
    "due_at": "2025-05-05",
    "notes": "Favor de realizar pago por transferencia bancaria.",
    "items": [
      { "description": "Consultoria fiscal especializada - 120 hrs", "quantity": 120, "unit_price": 1500, "tax_rate": 16 }
    ]
  }'
PUT /api/v1/invoices/{id}
Auth
Actualizar factura. Si se envian items, reemplazan los existentes.
curl -X PUT https://www.leaderapp.mx/api/v1/invoices/95f1970e-4596-548f-aae7-e2d44d1cf155 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "due_at": "2025-05-20" }'
DELETE /api/v1/invoices/{id}
Auth
Eliminar una factura.
curl -X DELETE https://www.leaderapp.mx/api/v1/invoices/95f1970e-4596-548f-aae7-e2d44d1cf155 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/invoices/{id}/send
Auth
Enviar factura. Cambia estado a "sent".
curl -X POST https://www.leaderapp.mx/api/v1/invoices/95f1970e-4596-548f-aae7-e2d44d1cf155/send \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Contratos
Gestiona contratos con flujo de firma.
GET /api/v1/contracts
Auth
Listar contratos. Filtros: vista (por_firmar, vigentes, firmados_mes, atrasados, cerrados), search, mios, contact_id, deal_id, status (draft, pending_signature, signed, active, on_hold, expired, cancelled, renewed). Trae un bloque summary.
curl "https://www.leaderapp.mx/api/v1/contracts?status=draft" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "99267153-4ac7-5fa9-8194-f635976596ee",
      "contract_number": "CTR-000002",
      "title": "Contrato de Servicios de Consultoria",
      "type": "service",
      "status": "draft",
      "value": 450000,
      "currency": "MXN",
      "start_date": "2025-05-01",
      "end_date": "2025-12-31",
      "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
      "deal_id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e"
    }
  ]
}

Campos del contrato

sign_url: liga de firma a distancia (/sign/{token}). Solo mientras el contrato está en draft o pending_signature; después es null.

portal_url: portal del titular (/p/{token}), si ya se abrió y el contrato no está cancelado. Abrir el detalle del contrato abre el portal.

También: number, status_label, payment_type, down_payment_amount, number_of_installments, overdue_count, overdue_amount, installments_total, installments_paid, next_installment, has_wizard y, en el detalle, installments.

GET /api/v1/contracts/{id}
Auth
Detalle con abonos, ligas de firma y de portal.
Ver respuesta de ejemplo
{
  "data": {
    "id": "9d70e1f2-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
    "contract_number": "PF-000118",
    "type": "prevision",
    "status": "active",
    "status_label": "Activo",
    "payment_type": "installments",
    "overdue_count": 2,
    "overdue_amount": 2400,
    "next_installment": { "number": 3, "due_date": "2026-08-15", "amount": 1200 },
    "has_wizard": true,
    "sign_url": null,
    "portal_url": "https://www.leaderapp.mx/p/Tz81kQ3mW9",
    "installments": [{ "id": "9db0f1e2-d3c4-4b5a-9687-786950a1b2c3", "number": 3, "due_date": "2026-08-15", "amount": 1200, "status": "pending", "paid_at": null, "is_overdue": true }],
    "value": "44000.00",
    "contact": { "full_name": "Elena Ruiz", "phone": "55 0000 1234" }
  }
}
POST /api/v1/contracts
Auth
Crear un contrato. El folio sale de la numeración de la línea de negocio (o CTR-XXXXXX sin línea); estado inicial "draft".

Body

Campo Tipo Requerido Descripción
contact_id uuid No ID del titular
title string No Título (max 255). Por omisión "Contrato {folio}"
deal_id uuid No ID del deal asociado
type string Sí prevision, uso_inmediato, prevision_mascota, cremacion_mascota, cementerio, mantenimiento, columbario, service, license, subscription, nda, partnership, custom
value numeric No Valor del contrato
start_date date No Fecha de inicio
end_date date No Fecha de fin (>= start_date)
curl -X POST https://www.leaderapp.mx/api/v1/contracts \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
    "deal_id": "f9088753-fb0b-58d8-8892-93d2dc6f9e2e",
    "title": "Contrato de Servicios de Consultoria Fiscal",
    "type": "service",
    "value": 450000,
    "currency": "MXN",
    "start_date": "2025-05-01",
    "end_date": "2025-12-31"
  }'
PUT /api/v1/contracts/{id}
Auth
Actualizar un contrato.
curl -X PUT https://www.leaderapp.mx/api/v1/contracts/99267153-4ac7-5fa9-8194-f635976596ee \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "end_date": "2026-03-31" }'
DELETE /api/v1/contracts/{id}
Auth
Eliminar un contrato.
curl -X DELETE https://www.leaderapp.mx/api/v1/contracts/99267153-4ac7-5fa9-8194-f635976596ee \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/contracts/{id}/sign
Auth
Firmar contrato. Cambia estado a "signed" y registra signed_at.

Body (opcional)

Campo Tipo Descripción
client_name string Nombre del firmante
company_name string Empresa del firmante
curl -X POST https://www.leaderapp.mx/api/v1/contracts/99267153-4ac7-5fa9-8194-f635976596ee/sign \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "client_name": "Elena Ruiz",
    "company_name": "Soluciones Integrales SA de CV"
  }'
GET /api/v1/contracts/{id}/wizard
Auth
Los pasos de la plantilla del contrato y lo capturado. step_type: form, signature, payment, product_selector. Sin plantilla responde has_template en false con un mensaje.
Ver respuesta de ejemplo
{
  "has_template": true,
  "sequential_steps": true,
  "progress": 50,
  "completed_steps": ["9e01a2b3-c4d5-4e6f-8a7b-9c0d1e2f3a4b"],
  "step_data": { "9e01a2b3-c4d5-4e6f-8a7b-9c0d1e2f3a4b": { "holder_name": "Elena Ruiz" } },
  "steps": [
    { "id": "9e01a2b3-c4d5-4e6f-8a7b-9c0d1e2f3a4b", "name": "Titular", "step_type": "form", "sort_order": 1, "is_required": true, "fields": [{ "name": "holder_name", "label": "Nombre", "type": "text", "required": true }], "is_completed": true },
    { "id": "9e02b3c4-d5e6-4f7a-9b8c-0d1e2f3a4b5c", "name": "Firma", "step_type": "signature", "sort_order": 2, "is_required": true, "fields": [], "is_completed": false }
  ],
  "contact": { "full_name": "Elena Ruiz", "primary_email": "elena.ruiz@example.com", "primary_phone": "55 0000 1234" }
}
POST /api/v1/contracts/{id}/steps/{stepId}
Auth
Guarda un paso. El paso signature con data.holder_signature firma el contrato; el paso payment toma net_amount, num_payments y down_payment_amount.

Body

Campo Tipo Requerido Descripción
data object Sí Valores del paso
Ver respuesta de ejemplo
{ "success": true, "progress": 100 }

Errores

  • 404: { "error": "Paso no encontrado." }
Cobranza en campo
La cartera del asesor y la liga de pago de Recaudo para mandarla por WhatsApp. Recaudo cobra; Leader asienta el pago cuando Recaudo lo confirma.
GET /api/v1/mi-cartera
contracts.view
Contratos firmados o activos que vendió quien llama, con abonos vencidos o por vencer: más días de atraso primero. Con todos=1, quien lleva la cobranza (payments.edit) ve la de todo el equipo; sin ese permiso se ignora.

Parámetros

Campo Tipo Requerido Descripción
dias integer No Ventana hacia adelante, 0 a 60. Por omisión 15
todos boolean No Toda la cartera (payments.edit)
curl "https://www.leaderapp.mx/api/v1/mi-cartera?dias=7" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [{
    "contract": { "id": "9d70e1f2-3a4b-4c5d-8e6f-7a8b9c0d1e2f", "number": "PF-000118", "title": "Plan Cremación 60", "portal_url": "https://www.leaderapp.mx/p/Tz81kQ3mW9" },
    "holder": { "id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "name": "Elena Ruiz", "first_name": "Elena", "phone": "55 0000 1234" },
    "owner": { "name": "Andrés Vega" },
    "days_late": 59,
    "overdue_count": 2,
    "overdue_amount": 2400,
    "installments": [
      { "id": "9db0f1e2-d3c4-4b5a-9687-786950a1b2c3", "number": 3, "concept": "Abono 3", "amount": 1200, "due_date": "2026-08-15", "days_late": 59, "is_late": true, "has_open_link": false, "link_expires_at": null },
      { "id": "9db2a3b4-c5d6-4e7f-8091-a2b3c4d5e6f7", "number": 5, "concept": "Abono 5", "amount": 1200, "due_date": "2026-10-15", "days_late": 0, "is_late": false, "has_open_link": false, "link_expires_at": null }
    ]
  }],
  "summary": { "late_contracts": 1, "late_installments": 2, "late_amount": 2400 },
  "meta": { "scope": "mios", "can_see_all": false, "online_payments": true }
}

Errores

  • 403 sin contracts.view.
  • 422 si dias sale de 0 a 60.
POST /api/v1/abonos/{id}/link-de-pago
contracts.view
Crea en Recaudo la liga para pagar el abono, o reusa la abierta por el mismo importe. El contrato debe ser de quien llama, de alguien de su equipo si lo supervisa, o tener payments.edit. Límite: 30 por minuto.
Ver respuesta de ejemplo
{ "url": "https://pago.recaudo.app/l/pl-8F2k", "amount": 1200, "expires_at": "2026-10-16T12:00:00-06:00", "portal_url": "https://www.leaderapp.mx/p/Tz81kQ3mW9" }

Errores

  • 403: "Este contrato es de la cartera de otro asesor."
  • 422: "El contrato está cancelado; ya no se cobra."
  • 422: "El cobro en línea no está conectado. Pide en la oficina que conecten Recaudo."
  • 422: "Este abono ya está pagado."
Pagos
Registra pagos contra facturas. Los saldos se recalculan automáticamente.
GET /api/v1/payments
Auth
Listar pagos. Filtros: invoice_id, contact_id, status (completed, pending, refunded).
curl "https://www.leaderapp.mx/api/v1/payments?invoice_id=95f1970e-4596-548f-aae7-e2d44d1cf155" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "5280d6a8-1602-5872-b3a9-0981631ad2f7",
      "amount": 104400,
      "currency": "MXN",
      "method": "transfer",
      "reference": "SPEI-20250410-001",
      "status": "completed",
      "paid_at": "2025-04-10T12:00:00.000000Z",
      "invoice_id": "95f1970e-4596-548f-aae7-e2d44d1cf155",
      "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada"
    }
  ]
}
GET /api/v1/payments/{id}
Auth
Obtener detalle de un pago.
curl https://www.leaderapp.mx/api/v1/payments/5280d6a8-1602-5872-b3a9-0981631ad2f7 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/payments
Auth
Registrar un pago. El saldo de la factura se recalcula automáticamente.

Body

Campo Tipo Requerido Descripción
invoice_id uuid Sí ID de la factura
amount numeric Sí Monto del pago (min 0.01)
method string No transfer, card, cash, check
reference string No Referencia de pago (ej. SPEI)
curl -X POST https://www.leaderapp.mx/api/v1/payments \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "invoice_id": "95f1970e-4596-548f-aae7-e2d44d1cf155",
    "contact_id": "9fd7866a-9330-576a-a943-9bf3657b7ada",
    "amount": 104400,
    "currency": "MXN",
    "method": "transfer",
    "reference": "SPEI-20250410-001"
  }'
PUT /api/v1/payments/{id}
Auth
Actualizar un pago.
curl -X PUT https://www.leaderapp.mx/api/v1/payments/5280d6a8-1602-5872-b3a9-0981631ad2f7 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "reference": "SPEI-20250410-002" }'
DELETE /api/v1/payments/{id}
Auth
Eliminar un pago.
curl -X DELETE https://www.leaderapp.mx/api/v1/payments/5280d6a8-1602-5872-b3a9-0981631ad2f7 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Productos
Catalogo de productos y servicios para cotizaciones y facturas.
GET /api/v1/products
Auth
Listar productos. Filtros: search, category_id, business_line_id, active_only.
curl "https://www.leaderapp.mx/api/v1/products?search=consultoria&active_only=true" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "2d34dfb3-70f5-512b-9ca6-87d15452bf08",
      "name": "Consultoria Fiscal Especializada",
      "sku": "CONS-FISC-001",
      "description": "Hora de consultoria fiscal con especialista certificado.",
      "unit_price": 1500,
      "tax_rate": 16,
      "currency": "MXN",
      "is_active": true
    }
  ]
}
GET /api/v1/products/{id}
Auth
Obtener detalle de un producto.
curl https://www.leaderapp.mx/api/v1/products/2d34dfb3-70f5-512b-9ca6-87d15452bf08 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/products
Auth
Crear un producto o servicio.

Body

Campo Tipo Requerido Descripción
name string Sí Nombre del producto (max 255)
unit_price numeric Sí Precio unitario (min 0)
sku string No Código SKU (max 100)
tax_rate numeric No Tasa de impuesto (ej. 16 para 16%)
is_active boolean No Default: true
curl -X POST https://www.leaderapp.mx/api/v1/products \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Auditoria Financiera Completa",
    "sku": "AUD-FIN-001",
    "description": "Auditoria financiera integral para empresas medianas.",
    "unit_price": 85000,
    "tax_rate": 16,
    "currency": "MXN"
  }'
PUT /api/v1/products/{id}
Auth
Actualizar un producto.
curl -X PUT https://www.leaderapp.mx/api/v1/products/2d34dfb3-70f5-512b-9ca6-87d15452bf08 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "unit_price": 1800 }'
DELETE /api/v1/products/{id}
Auth
Eliminar un producto.
curl -X DELETE https://www.leaderapp.mx/api/v1/products/2d34dfb3-70f5-512b-9ca6-87d15452bf08 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Catálogos
Datos de referencia para cotizar y hacer contratos. Solo lectura.
GET /api/v1/price-lists
Auth
Listas de precios activas (plazos). Con business_line_id, las de esa línea y las generales. GET /api/v1/price-lists/{id} trae una.

Parámetros

Campo Tipo Requerido Descripción
business_line_id uuid No Línea de negocio
Ver respuesta de ejemplo
{
  "data": [{
    "id": "9d1e8c74-6e50-4d9c-9b20-4d8b5c3f0c32", "name": "12 meses", "business_line_id": "9d1c6a52-4c3e-4b7a-9f0e-2b6f3f1d8a10",
    "is_default": false, "is_active": true, "allow_price_edit": false,
    "number_of_payments": 12, "payment_method_type": "bank_reference", "payment_method_label": "Referencia bancaria 12 meses", "is_contado": false,
    "items": [{ "product_id": "9d20a1b2-c3d4-4e5f-8a6b-7c8d9e0f1a2b", "unit_price": 48000 }]
  }]
}
GET /api/v1/business-lines
Auth
Líneas de negocio activas, la predeterminada primero: id, name, slug, is_default, is_active, default_tax_rate, color, default_currency.
GET /api/v1/product-categories
Auth
Categorías activas por nombre: { "data": [{ "id", "name" }] }.
GET /api/v1/product-attributes
Auth
Atributos filtrables (id, name, label, type, options, business_line_id). Con business_line_id, los de esa línea y los generales; sin él, solo los generales.

Parámetros

Campo Tipo Requerido Descripción
business_line_id uuid No Línea de negocio
GET /api/v1/contract-templates
Auth
Plantillas activas: id, name, description, contract_type, default_content, default_terms, default_clauses, default_duration_months, is_default, is_active, has_steps. GET /api/v1/contract-templates/{id} trae una; los pasos se ven en el asistente del contrato.
GET /api/v1/contract-types
Auth
Los 13 tipos de contrato con su etiqueta.
Ver respuesta de ejemplo
{ "data": [{ "value": "prevision", "label": "Previsión a futuro" }, { "value": "uso_inmediato", "label": "Uso inmediato" }, { "value": "cementerio", "label": "Derechos de uso en cementerio" }] }
Pipelines
Lectura de pipelines y sus etapas. Necesarios para crear deals.
GET /api/v1/pipelines
Auth
Obtener todos los pipelines activos con sus etapas. Sin paginación.
curl https://www.leaderapp.mx/api/v1/pipelines \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "10ff6166-58fc-50f3-9926-4ca5cef28080",
      "name": "Pipeline de Ventas",
      "is_default": true,
      "stages": [
        { "id": "1c53c492-b170-51be-83d3-3b7af39a4b53", "name": "Prospecto", "type": "open", "color": "#6B7280", "default_probability": 10 },
        { "id": "938477ef-ab96-55e6-82e9-b72cecea54dd", "name": "Contactado", "type": "open", "color": "#3B82F6", "default_probability": 25 },
        { "id": "d3bc1dd2-de9d-5255-ad46-35dec602e1a0", "name": "Propuesta", "type": "open", "color": "#F59E0B", "default_probability": 50 },
        { "id": "df306fe5-7c37-5b4e-86f0-ca0a30bf7528", "name": "Negociacion", "type": "open", "color": "#8B5CF6", "default_probability": 75 },
        { "id": "17ee3b60-1ed3-5df2-a30c-31ad24138f4c", "name": "Ganado", "type": "won", "color": "#10B981", "default_probability": 100 },
        { "id": "2838cf94-860b-567a-85a0-640ec6a24ba4", "name": "Perdido", "type": "lost", "color": "#EF4444", "default_probability": 0 }
      ]
    }
  ]
}
GET /api/v1/pipelines/{id}
Auth
Obtener un pipeline con sus etapas.
curl https://www.leaderapp.mx/api/v1/pipelines/10ff6166-58fc-50f3-9926-4ca5cef28080 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Eventos
Gestiona eventos, webinars y reuniones con RSVP y check-in.
GET /api/v1/events
Auth
Listar eventos. Filtros: type, upcoming (true/false).
curl "https://www.leaderapp.mx/api/v1/events?upcoming=true" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "4e06ebd5-593a-5e55-a4b1-458c3277f31b",
      "title": "Webinar: Tendencias Fiscales 2025",
      "type": "webinar",
      "start_at": "2025-04-20T17:00:00.000000Z",
      "end_at": "2025-04-20T18:30:00.000000Z",
      "attendees_count": 45
    }
  ]
}
POST /api/v1/events
Auth
Crear un evento.

Body

Campo Tipo Requerido Descripción
title string Sí Titulo del evento (max 255)
type string Sí Tipo (meeting, webinar, training, etc.)
start_at date Sí Fecha/hora de inicio
end_at date Sí Fecha/hora de fin (> start_at)
location string No Ubicacion
max_attendees integer No Máximo de asistentes
curl -X POST https://www.leaderapp.mx/api/v1/events \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "Capacitacion Interna: Nuevo Sistema CRM",
    "type": "training",
    "location": "Sala de Juntas B, Piso 3",
    "start_at": "2025-04-25T09:00:00Z",
    "end_at": "2025-04-25T12:00:00Z",
    "is_mandatory": true,
    "max_attendees": 20
  }'
PUT /api/v1/events/{id}
Auth
Actualizar un evento.
curl -X PUT https://www.leaderapp.mx/api/v1/events/4e06ebd5-593a-5e55-a4b1-458c3277f31b \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "max_attendees": 50 }'
DELETE /api/v1/events/{id}
Auth
Eliminar un evento.
curl -X DELETE https://www.leaderapp.mx/api/v1/events/4e06ebd5-593a-5e55-a4b1-458c3277f31b \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/events/{id}/rsvp
Auth
Confirmar asistencia: accepted, declined, tentative.
curl -X POST https://www.leaderapp.mx/api/v1/events/4e06ebd5-593a-5e55-a4b1-458c3277f31b/rsvp \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"status": "accepted"}'
POST /api/v1/events/{id}/check-in/{attendee_id}
Auth
Registrar asistencia de un participante. Sin body requerido.
curl -X POST https://www.leaderapp.mx/api/v1/events/4e06ebd5-593a-5e55-a4b1-458c3277f31b/check-in/70d79582-aa1a-5613-8ed9-e4f74ca19aaa \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Campañas
Campañas de email marketing vinculadas a segmentos.
GET /api/v1/campaigns
Auth
Listar campañas. Filtro: status (draft, scheduled, sending, sent).
curl "https://www.leaderapp.mx/api/v1/campaigns?status=draft" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "77e10ce2-9786-56b7-ae36-2c8f894b8ca0",
      "name": "Promocion Servicios Fiscales Q2",
      "status": "draft",
      "segment_name": "Clientes Activos Monterrey",
      "stats": null,
      "sent_at": null
    }
  ]
}
POST /api/v1/campaigns
Auth
Crear una campaña de email.

Body

Campo Tipo Requerido Descripción
name string Sí Nombre de la campaña
subject string No Asunto del email
content string No Contenido HTML del email
segment_id uuid No ID del segmento destino
scheduled_at date No Fecha programada de envio
curl -X POST https://www.leaderapp.mx/api/v1/campaigns \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Newsletter Abril 2025",
    "subject": "Novedades y promociones de abril",
    "content": "

Hola!

Estas son nuestras novedades...

", "segment_id": "46bf45be-4078-5337-a843-e263e6a2890f", "scheduled_at": "2025-04-20T09:00:00Z" }'
PUT /api/v1/campaigns/{id}
Auth
Actualizar una campaña. Mismos campos, todos opcionales.
curl -X PUT https://www.leaderapp.mx/api/v1/campaigns/77e10ce2-9786-56b7-ae36-2c8f894b8ca0 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "subject": "Ofertas especiales de abril" }'
DELETE /api/v1/campaigns/{id}
Auth
Eliminar una campaña.
curl -X DELETE https://www.leaderapp.mx/api/v1/campaigns/77e10ce2-9786-56b7-ae36-2c8f894b8ca0 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/campaigns/{id}/send
Auth
Enviar la campaña. Sin body requerido.
curl -X POST https://www.leaderapp.mx/api/v1/campaigns/77e10ce2-9786-56b7-ae36-2c8f894b8ca0/send \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Segmentos
Segmentos estaticos o dinamicos de contactos para campañas.
GET /api/v1/segments
Auth
Listar segmentos. Filtro: type (static, dynamic).
curl "https://www.leaderapp.mx/api/v1/segments?type=dynamic" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    { "id": "46bf45be-4078-5337-a843-e263e6a2890f", "name": "Clientes Activos Monterrey", "type": "dynamic", "member_count": 87 }
  ]
}
POST /api/v1/segments
Auth
Crear un segmento con condiciones de filtro.

Body

Campo Tipo Requerido Descripción
name string Sí Nombre del segmento
type string Sí static o dynamic
conditions array No Condiciones de filtro para segmentos dinamicos
curl -X POST https://www.leaderapp.mx/api/v1/segments \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Leads de Guadalajara",
    "type": "dynamic",
    "conditions": [
      {"field": "lifecycle_stage", "operator": "=", "value": "lead"},
      {"field": "city", "operator": "=", "value": "Guadalajara"}
    ]
  }'
PUT /api/v1/segments/{id}
Auth
Actualizar un segmento.
curl -X PUT https://www.leaderapp.mx/api/v1/segments/46bf45be-4078-5337-a843-e263e6a2890f \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "name": "Leads de GDL 2025" }'
DELETE /api/v1/segments/{id}
Auth
Eliminar un segmento.
curl -X DELETE https://www.leaderapp.mx/api/v1/segments/46bf45be-4078-5337-a843-e263e6a2890f \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
GET /api/v1/segments/{id}/contacts
Auth
Obtener contactos que pertenecen a un segmento. Paginado.
curl "https://www.leaderapp.mx/api/v1/segments/46bf45be-4078-5337-a843-e263e6a2890f/contacts" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Notificaciones
Notificaciones del usuario autenticado.
GET /api/v1/notifications
Auth
Listar notificaciónes. Filtro: unread_only (true/false).
curl "https://www.leaderapp.mx/api/v1/notifications?unread_only=true" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "151300e0-8731-5a24-8a69-96b1d310aa58",
      "type": "deal_won",
      "title": "Negocio ganado",
      "body": "El negocio 'Implementacion ERP' fue marcado como ganado.",
      "url": "/deals/5",
      "read_at": null,
      "created_at": "2025-04-12T15:30:00.000000Z"
    }
  ]
}
POST /api/v1/notifications/{id}/read
Auth
Marcar una notificación como leida.
curl -X POST https://www.leaderapp.mx/api/v1/notifications/151300e0-8731-5a24-8a69-96b1d310aa58/read \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
POST /api/v1/notifications/read-all
Auth
Marcar todas las notificaciónes como leidas.
curl -X POST https://www.leaderapp.mx/api/v1/notifications/read-all \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Usuarios
Usuarios del tenant actual. Solo lectura.
GET /api/v1/users
Auth
Listar usuarios del tenant. Filtro: search (nombre o email).
curl "https://www.leaderapp.mx/api/v1/users?search=jorge" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Ver respuesta de ejemplo
{
  "data": [
    {
      "id": "1e78680c-20f6-5707-89f5-878ef8dc9655",
      "name": "Andrés Vega",
      "email": "andres.vega@example.com",
      "role": "admin",
      "avatar_url": "https://www.leaderapp.mx/storage/avatars/1.jpg"
    }
  ]
}
GET /api/v1/users/{id}
Auth
Obtener detalle de un usuario.
curl https://www.leaderapp.mx/api/v1/users/1e78680c-20f6-5707-89f5-878ef8dc9655 \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
Automatizaciones
Las automatizaciones se arman en la web. Un paso "Enviar con Recaudo" manda datos de Leader a un flujo publicado en Recaudo, que es quien manda el WhatsApp. Estos endpoints los usa el editor (automations.edit).
POST /api/v1/automations/{id}/save
Auth
Guarda pasos y conexiones del lienzo. Un paso de Recaudo es type recaudo_flow con data: label, flow_id, flow_name, recipient (por omisión el teléfono del cliente), variables ([{ key, value }], los valores aceptan llaves del catálogo entre dobles llaves) y required_keys.

Body

Campo Tipo Requerido Descripción
nodes array Sí Pasos del flujo
edges array Sí Conexiones
curl -X POST https://www.leaderapp.mx/api/v1/automations/9f10a2b3-c4d5-4e6f-8a7b-9c0d1e2f3a4b/save \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "nodes": [{
      "id": "n2",
      "type": "recaudo_flow",
      "data": {
        "label": "Mandar contrato",
        "flow_id": "flujo-1",
        "required_keys": ["numero_cliente"],
        "variables": [{ "key": "numero_cliente", "value": "{{contrato.folio}}" }]
      }
    }],
    "edges": [{ "source": "n1", "target": "n2" }]
  }'
Ver respuesta de ejemplo
{ "success": true }

Errores

  • 422: { "success": false, "message": "Al paso «Enviar con Recaudo» le falta decir qué dato va en las variables «1», «numero_cliente»." }
GET /api/v1/automations/recaudo/flows
Auth
Flujos publicados en Recaudo. Sin conexión responde 200 con connected en false, el error y settings_url. Si Recaudo no responde, data viene vacío y error trae el motivo.
Ver respuesta de ejemplo
{ "connected": true, "error": null, "data": [{ "id": "flujo-1", "name": "Contrato y documentación", "description": "Manda el contrato firmado y sus anexos", "channel": "whatsapp", "version": 3 }] }
GET /api/v1/automations/recaudo/flows/{flowId}
Auth
Las variables que espera el flujo (obligatorias primero) y las posiciones de sus plantillas. filled_by customer: Recaudo la llena con los datos del cliente.
Ver respuesta de ejemplo
{
  "connected": true,
  "error": null,
  "data": {
    "id": "flujo-1",
    "name": "Contrato y documentación",
    "variables": [
      { "key": "numero_cliente", "required": true, "filled_by": null, "default": null },
      { "key": "nombre", "required": false, "filled_by": "customer", "default": null }
    ],
    "templates": [{ "template_name": "contrato_firmado", "positions": ["1", "2"] }]
  }
}
GET /api/v1/automations/variables/{trigger}
Auth
Los datos de Leader que se pueden mandar según el disparador. 404 si el disparador no existe. Los valores se leen al correr, no de la foto del disparo.
Ver respuesta de ejemplo
{ "data": [{ "key": "cliente.nombre", "label": "Nombre del cliente", "group": "Cliente" }, { "key": "cotizacion.pdf_url", "label": "Liga del PDF", "group": "Cotización" }] }

Disparadores

Disparador Cuándo
contact_created Se da de alta un contacto
form_submitted Alguien llena un formulario
deal_created Se abre una oportunidad
deal_stage_changed Una oportunidad cambia de etapa
quote_created Se hace una cotización
contract_signed Se firma un contrato
payment_received Llega un pago
activity_completed Se completa una actividad
tag_added Se agrega una etiqueta
service_order_created Se abre un servicio
service_stage_changed Un servicio cambia de etapa
installment_overdue Un abono se atrasa
weekly_direction_summary Cada lunes, el resumen de dirección

Variables por disparador

contact_created · Se da de alta un contacto

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

form_submitted · Alguien llena un formulario

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

deal_created · Se abre una oportunidad

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

deal_stage_changed · Una oportunidad cambia de etapa

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

quote_created · Se hace una cotización

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), cotizacion.folio (Folio), cotizacion.total (Total), cotizacion.descuento (Descuento total), cotizacion.promociones (Promociones aplicadas), cotizacion.plan (Plan), cotizacion.plazo (Plazo (lista de precios)), cotizacion.enganche (Enganche), cotizacion.mensualidad (Mensualidad), cotizacion.mensualidades (Número de mensualidades), cotizacion.resumen_pago (Forma de pago en una frase), cotizacion.vigencia (Vigente hasta), cotizacion.pdf_url (Liga del PDF), cotizacion.pdf_nombre (Nombre del archivo PDF), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

contract_signed · Se firma un contrato

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), contrato.folio (Folio), contrato.total (Total), contrato.plan (Plan), contrato.plazo (Plazo (lista de precios)), contrato.enganche (Enganche), contrato.mensualidad (Mensualidad), contrato.mensualidades (Número de mensualidades), contrato.fecha_firma (Fecha de firma), contrato.pdf_url (Liga del PDF), contrato.pdf_nombre (Nombre del archivo PDF), contrato.documentos (Documentos (uno por mensaje)), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

payment_received · Llega un pago

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), pago.monto (Importe pagado), pago.recibo (Folio del recibo), familia.nombre (Nombre del familiar), familia.telefono (Teléfono del familiar), servicio.finado (Nombre de quien falleció), servicio.etapa (Etapa actual), servicio.mensaje_familia (Mensaje para la familia (dónde, cuándo, qué sigue)), servicio.coordinador (Quién coordina el servicio), servicio.portal_url (Liga del portal de la familia), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

activity_completed · Se completa una actividad

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

tag_added · Se agrega una etiqueta

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

service_order_created · Se abre un servicio

familia.nombre (Nombre del familiar), familia.telefono (Teléfono del familiar), servicio.finado (Nombre de quien falleció), servicio.etapa (Etapa actual), servicio.mensaje_familia (Mensaje para la familia (dónde, cuándo, qué sigue)), servicio.coordinador (Quién coordina el servicio), servicio.portal_url (Liga del portal de la familia), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

service_stage_changed · Un servicio cambia de etapa

familia.nombre (Nombre del familiar), familia.telefono (Teléfono del familiar), servicio.finado (Nombre de quien falleció), servicio.etapa (Etapa actual), servicio.mensaje_familia (Mensaje para la familia (dónde, cuándo, qué sigue)), servicio.coordinador (Quién coordina el servicio), servicio.portal_url (Liga del portal de la familia), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

installment_overdue · Un abono se atrasa

cliente.nombre (Nombre del cliente), cliente.telefono (Teléfono del cliente), contrato.folio (Folio), contrato.plan (Plan), contrato.portal_url (Liga del portal del titular), abono.concepto (Abono (concepto)), abono.monto (Importe del abono), abono.vence (Fecha en que vencía), abono.link_pago (Liga de pago (Recaudo)), asesor.nombre (Nombre del asesor), asesor.telefono (Teléfono del asesor), linea.nombre (Línea de negocio), funeraria.nombre (Nombre de la funeraria)

weekly_direction_summary · Cada lunes, el resumen de dirección

direccion.resumen_semanal (Resumen de la semana para dirección), direccion.periodo (Semana que resume), funeraria.nombre (Nombre de la funeraria)

Integraciones: Recaudo
Recaudo es el único orquestador de cobros y mensajería: ligas de pago, WhatsApp (texto, plantillas y flujos) y avisos de pago pasan por la cuenta de Recaudo de cada funeraria.

Conectar Recaudo (administradores, en la web)

  1. Configuración → Integraciones → Conectar con Recaudo (permiso integrations.edit).
  2. Leader manda a Recaudo a autorizar (OAuth 2 con código de autorización y PKCE S256). Se inicia sesión en Recaudo y se acepta.
  3. Recaudo regresa a Leader; Leader valida la respuesta, cambia el código por tokens y guarda con qué usuario de Recaudo se conectó.
  4. Los tokens se renuevan solos. Si la renovación falla, la pantalla pide reconectar. Desde ahí también se pausa o se desconecta.
GET /api/v1/integrations
Auth
Integraciones activas de la funeraria. Las credenciales nunca se devuelven.
Ver respuesta de ejemplo
{ "data": [{ "id": "9f00b1c2-d3e4-4f5a-8b6c-7d8e9f0a1b2c", "provider": "recaudo", "type": "messaging", "config": { "account_user_name": "Laura Ortiz", "connected_at": "2026-09-20T10:00:00-06:00" }, "last_synced_at": "2026-10-13T09:00:00.000000Z", "last_error": null }] }
GET /api/v1/integrations/recaudo/templates
Auth
Plantillas de WhatsApp aprobadas en Recaudo, para escribir fuera de la ventana de 24 horas. Sin Recaudo, data viene vacío.
Ver respuesta de ejemplo
{ "data": [{ "id": "tpl_8k2", "name": "seguimiento_cotizacion", "language": "es_MX", "category": "UTILITY", "status": "APPROVED" }] }
POST /api/v1/integrations/recaudo/whatsapp
Auth
Manda un WhatsApp por Recaudo: busca o crea al contacto como cliente en Recaudo y le manda el texto o la plantilla.

Body

Campo Tipo Requerido Descripción
contact_id uuid Sí Contacto
body string Sin template_id Texto libre (máx. 4096), dentro de la ventana de 24 horas
template_id string Sin body Plantilla aprobada
template_parameters array No Parámetros de la plantilla
curl -X POST https://www.leaderapp.mx/api/v1/integrations/recaudo/whatsapp \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "contact_id": "9d40a7c3-1b2e-4f5a-9c8d-7e6f5a4b3c21", "template_id": "tpl_8k2", "template_parameters": ["Elena", "COT-000231"] }'
Ver respuesta de ejemplo
{ "success": true, "recaudo_customer_id": "cus_51x", "recaudo_message_id": "msg_93a", "recaudo_conversation_id": "conv_77b" }

Errores

  • 422: "Integración con Recaudo no configurada. Ve a Configuración → Integraciones."
  • 422: "No se pudo encontrar/crear el cliente en Recaudo. Verifica que el contacto tenga teléfono o email."
  • 422: "El contacto no tiene un teléfono de 10 dígitos para mandarle la plantilla."
  • 422: el error que regrese Recaudo (campo error).
MCP
Herramientas del CRM para agentes de IA, con el mismo token de la API.
GET /api/v1/mcp/tools
Auth
Las 49 herramientas con su descripción y sus parámetros en JSON Schema.
Ver respuesta de ejemplo
{ "tools": [{ "name": "search_contacts", "description": "Buscar contactos…", "parameters": { "type": "object", "properties": { "query": { "type": "string" } }, "required": ["query"] } }] }
POST /api/v1/mcp/execute
Auth
Ejecuta una herramienta. Los errores de la herramienta llegan con 200 en result.error.

Body

Campo Tipo Requerido Descripción
tool string Sí Nombre de la herramienta
arguments object Sí Parámetros ({} si no lleva)
curl -X POST https://www.leaderapp.mx/api/v1/mcp/execute \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "tool": "search_contacts", "arguments": { "query": "Ruiz" } }'
Ver respuesta de ejemplo
{ "result": { "contacts": [{ "full_name": "Elena Ruiz" }], "count": 1 } }
Webhooks
Endpoints públicos: formularios externos y avisos de Recaudo.
POST /api/forms/{apiKey}/submit
Pública
Enviar un formulario externo. No requiere autenticación, usa API key en la URL.
curl -X POST https://www.leaderapp.mx/api/forms/abc123def456/submit \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Carlos",
    "last_name": "Martinez Diaz",
    "email": "carlos.mendez@example.com",
    "phone": "55 0000 3456",
    "message": "Me interesa conocer sus servicios de consultoria."
  }'
Ver respuesta de ejemplo
{
  "success": true,
  "submission_id": "ce87be8f-07a3-5af5-8729-bb7c8e816211",
  "contact_id": "fd5032cb-8a47-560e-b9ac-ebe6b0c6979b",
  "assigned_to": "Andrés Vega"
}
POST /api/webhooks/recaudo/cobros
Pública
Recaudo avisa aquí cuando una liga de pago cambia (payment_link.paid, payment.succeeded…). El aviso no se toma como prueba de pago: Leader solo toma el id de la liga y le vuelve a preguntar a Recaudo, con las credenciales de la funeraria, cómo va y qué pagos tiene. Solo se asientan los pagos que Recaudo confirma como succeeded, sin duplicar referencias. Límite: 120 por minuto.
curl -X POST https://www.leaderapp.mx/api/webhooks/recaudo/cobros \
  -H "Content-Type: application/json" \
  -d '{ "type": "payment_link.paid", "data": { "object": { "id": "pl-8F2k" } } }'
Ver respuesta de ejemplo
{ "message": "Revisada", "registered": 1 }

Otras respuestas (200): { "message": "Liga desconocida" } si la liga no es de Leader; { "message": "Sin liga de pago" } si el aviso no trae id.

Por si un aviso no llega, cada 10 minutos Leader revisa con Recaudo las ligas activas de los últimos 10 días. Los portales también consultan antes de mostrar el saldo.

POST /api/webhooks/recaudo
Pública
Uso interno: la facturación de la suscripción de cada funeraria a Leader. Valida la firma X-Recaudo-Signature (HMAC SHA-256 del cuerpo). Eventos: payment.completed, payment.failed, subscription.created, subscription.cancelled, invoice.paid, invoice.overdue.
COPOMEX
Consulta de códigos postales de México.
GET /api/copomex/{cp}
Pública
Buscar datos de un código postal mexicano (5 dígitos).
curl https://www.leaderapp.mx/api/copomex/64000
Ver respuesta de ejemplo
{
  "found": true,
  "municipality": "Monterrey",
  "city": "Monterrey",
  "state": "Nuevo Leon",
  "colonies": ["Centro", "Obispado", "Chepevera"]
}
Guía para AI Agents
Integración con Claude, GPT, Cursor, Copilot y agentes MCP.

Inicio rapido

  1. Autenticar -- POST a /api/v1/auth/login para obtener un bearer token
  2. Obtener contexto -- GET /api/v1/auth/me para confirmar usuario y tenant
  3. Obtener pipelines -- GET /api/v1/pipelines para conocer las etapas de deals
  4. Cotizar -- GET /api/v1/quoting/catalog, POST /api/v1/quoting/preview y POST /api/v1/quoting/quotes
  5. Comenzar -- Todos los endpoints requieren Authorization: Bearer {token}

Herramientas MCP (GET /api/v1/mcp/tools, POST /api/v1/mcp/execute)

Área Herramientas
Contactos search_contacts, create_contact, get_contact, update_contact, delete_contact, add_note_to_contact, get_contact_timeline
Empresas search_companies, create_company, get_company, update_company
Oportunidades create_deal, get_deal, update_deal, mark_deal_won, mark_deal_lost, get_deals_summary, search_deals, move_deal_stage, get_pipeline, get_sales_forecast
Actividades create_activity, search_activities, complete_activity, get_overdue_activities, reschedule_activity
Cotizaciones create_quote, get_quote, send_quote, approve_quote, convert_quote_to_invoice
Facturas y pagos search_invoices, create_invoice, get_invoice, send_invoice, record_payment, get_payment_summary
Contratos create_contract, get_contract, send_contract_for_signature
Eventos y campañas create_event, get_upcoming_events, create_campaign, send_campaign
Otros search_products, get_product, get_unread_notifications, get_dashboard_stats, get_team_performance

Flujos de trabajo comunes

1. Nuevo Lead

Contacto → Deal (con pipeline_id + stage_id) → Actividad de seguimiento

2. Ciclo de Venta Completo

Contacto → Cotizador (catalog → preview → quotes) → contrato (direct o /quotes/{id}/contract) → firma (sign_url) → cobranza (mi-cartera → link-de-pago por Recaudo)

3. Rendimiento del Equipo

Deals ganados + Actividades pendientes + Notificaciones + Distribucion de pipeline

4. Seguimiento Masivo

Listar leads sin actividad → Crear tareas de seguimiento por cada uno

5. Formularios Externos

POST /api/forms/{apiKey}/submit -- sin autenticación, crea contacto automáticamente

Modelo de datos

Tenant (multi-tenant)
  |-- Users (equipo)
  |-- Contacts → Notes, Company, Deals (N:N), Quotes, Invoices, Contracts, Payments
  |-- Companies → Contacts (1:N)
  |-- Pipelines → Stages → Deals
  |-- Deals → Contacts (N:N), Quotes, Invoices, Contracts
  |-- Quotes → Items, Contact, Deal
  |-- Invoices → Items, Payments, Contact, Deal
  |-- Contracts → Contact, Deal, Quote
  |-- Payments → Invoice, Contact
  |-- Products → Images, Category
  |-- Activities (polimorficas: Contact, Deal, Company)
  |-- Events → Attendees
  |-- Campaigns → Segment
  |-- Segments → Contacts (dinamicos/estaticos)
  |-- Notifications (por usuario)

Relaciones clave (que IDs necesitas)

Al crear... Necesitas estos IDs
Contact company_id (opcional), owner_id (opcional)
Deal pipeline_id (requerido), stage_id (requerido), contact_ids (opcional)
Quote / Invoice / Contract contact_id (requerido), deal_id (opcional)
Payment invoice_id (requerido), contact_id (opcional)
Activity activitable_type + activitable_id (opcionales, polimórficos)

Mejores practicas

  • Siempre autenticar primero. Reutilizar el token.
  • Obtener pipelines antes de crear deals (para pipeline_id y stage_id).
  • Buscar antes de crear para evitar duplicados.
  • Usar per_page=100 para operaciónes masivas.
  • Vincular entidades: pasar contact_ids en deals, contact_id en quotes/invoices/contracts.
  • Tipos polimórficos con namespace completo: App\Models\Contact, no solo Contact.
  • Los IDs son UUID (texto), incluido activitable_id.
  • Fechas en ISO 8601: YYYY-MM-DD o 2025-04-15T10:00:00Z.