Documentación
API de Legio Recovery
JSON sobre HTTPS. Base: https://app.legioagencia.es. Integraciones de servidor: cabecera Authorization: Bearer sk_… (créala en Ajustes → Tracker e integraciones). Errores: { "error": { "code", "message", "ref" } }.
Ejemplo: registrar un presupuesto enviado desde tu CRM
curl -X POST https://app.legioagencia.es/api/events \
-H "Authorization: Bearer sk_xxx" -H "content-type: application/json" \
-d '{ "email": "carlos@example.com", "type": "quote_sent",
"properties": { "amount": 4850, "service": "reforma de cocina" } }'Autenticación
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/auth/register | Crear cuenta (opcional: empresa demo o aceptar invitación) | Pública | { name, email, password, demo?, invite_token? } |
| POST | /api/auth/login | Iniciar sesión | Pública | { email, password, next? } |
| PATCH | /api/account | Cambiar mi nombre | Sesión (cookie + X-CSRF-Token) | { name } |
| POST | /api/account/password | Cambiar mi contraseña (cierra las demás sesiones) | Sesión (cookie + X-CSRF-Token) | { current_password, new_password } |
| POST | /api/auth/logout | Cerrar sesión | Sesión (cookie + X-CSRF-Token) | |
| POST | /api/auth/forgot | Solicitar enlace para restablecer contraseña | Pública | { email } |
| POST | /api/auth/reset | Restablecer contraseña con token | Pública | { token, password } |
| POST | /api/auth/verify/resend | Reenviar el email de verificación (máx. 3/hora y 6/día) | Sesión (cookie + X-CSRF-Token) | |
| POST | /api/auth/verify | Confirmar email con el token recibido | Pública | { token } |
Empresa
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/orgs | Crear empresa (tenant) | Sesión (cookie + X-CSRF-Token) | { name, website?, sector? } |
| POST | /api/orgs/demo | Crear/abrir la empresa demo «Clínica Nova» | Sesión (cookie + X-CSRF-Token) | |
| POST | /api/orgs/switch | Cambiar de empresa activa | Sesión (cookie + X-CSRF-Token) | { org_id } |
| DELETE | /api/orgs/current | Eliminar la empresa activa y todos sus datos (irreversible) | Sesión (cookie + X-CSRF-Token) permiso: settings.update | { confirm: "<nombre de la empresa>" } |
| POST | /api/onboarding | Guardar un paso del onboarding (paso 7 lanza el primer análisis) | Sesión (cookie + X-CSRF-Token) permiso: settings.update | { step, name?, website?, sector?, primary_goal? } |
| POST | /api/platform/plan | Cambiar el plan de la empresa activa (solo SUPER_ADMIN, mientras no hay pagos) | Sesión (cookie + X-CSRF-Token) | { plan } |
| POST | /api/billing/checkout | Solicitar un plan (manual hoy: devuelve instrucciones; Stripe en el futuro: URL de pago) | Sesión (cookie + X-CSRF-Token) permiso: settings.update | { plan } |
Equipo
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/invitations/:token/accept | Aceptar invitación | Sesión (cookie + X-CSRF-Token) | |
| POST | /api/members/invite | Invitar a un miembro (devuelve el enlace de invitación) | Sesión (cookie + X-CSRF-Token) permiso: members.manage | { email, role: admin|member } |
| PATCH | /api/members/:userId | Cambiar rol | Sesión (cookie + X-CSRF-Token) permiso: members.manage | |
| DELETE | /api/members/:userId | Quitar miembro | Sesión (cookie + X-CSRF-Token) permiso: members.manage | |
| DELETE | /api/invitations/:id | Cancelar invitación | Sesión (cookie + X-CSRF-Token) permiso: members.manage |
Tracker
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /api/onboarding/tracker-status | ¿Ha llegado algún evento del tracker? | Sesión (cookie + X-CSRF-Token) | |
| POST | /api/track | Registrar un evento desde la web (Legio.track) | Clave pública pk_… (en el cuerpo) | { pk, anonymous_id, event, properties?, url?, ts? } |
| POST | /api/identify | Identificar al visitante tras un mecanismo legítimo (formulario, login…) — Legio.identify | Clave pública pk_… (en el cuerpo) | { pk, anonymous_id, email, name?, phone?, consent?, signature? } |
| POST | /api/form | Formulario enviado por un visitante en cualquier web (legio.js). Crea el lead; solo enlaza el historial con consentimiento | Clave pública pk_… (en el cuerpo) | { pk, email, name?, phone?, form?, service?, consent?: {marketing, text}, anonymous_id? (solo con consentimiento), url? } |
| GET | /api/settings/tracking/check | ¿Está conectada mi web? (tracker, plugin de WordPress o formularios) | Sesión (cookie + X-CSRF-Token) | |
| PATCH | /api/settings/tracking | Activar/desactivar tracking, verificación de identidad y orígenes permitidos | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| POST | /api/settings/tracking/rotate-key | Regenerar la clave pública del tracker | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| POST | /api/settings/tracking/identity-secret | Mostrar el secreto para firmar identify() (HMAC-SHA256) | Sesión (cookie + X-CSRF-Token) permiso: apikeys.manage |
Formularios
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/forms/:token | Recibir un formulario de cualquier web o plataforma (Webflow, Wix, Zapier, Make, Shopify Flow, HTML). Token fk_ en la URL: solo crea leads | Token fk_… en la URL (solo crea leads de formularios) | JSON o form-urlencoded: email, nombre|name, telefono|phone, servicio?, consentimiento?, _form?, _redirect? |
| POST | /api/settings/forms/endpoint | Crear una URL para recibir formularios (fk_…, se muestra una vez) | Sesión (cookie + X-CSRF-Token) permiso: apikeys.manage |
Leads
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /api/leads | Listar leads (q, status, consent, sort, limit, offset) | Sesión o Bearer sk_… permiso: lead.view | |
| POST | /api/leads | Crear o actualizar (por email / external_id) un lead | Sesión o Bearer sk_… permiso: lead.write | { email?, name?, phone?, external_id?, source?, estimated_value?, customer_status?, consent_status?, consent_note? } |
| GET | /api/leads/:id | Detalle de un lead con timeline y oportunidades | Sesión o Bearer sk_… permiso: lead.view | |
| PATCH | /api/leads/:id | Actualizar datos de un lead | Sesión o Bearer sk_… permiso: lead.write | |
| POST | /api/leads/:id/summary | Resumen del historial del lead (IA con respaldo determinista) | Sesión (cookie + X-CSRF-Token) permiso: lead.view |
Privacidad
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/leads/:id/consent | Registrar la base legal / consentimiento de un lead | Sesión o Bearer sk_… permiso: lead.write | { status: granted|legitimate_interest|unknown|denied|withdrawn, note? } |
| POST | /api/leads/:id/do-not-contact | Marcar lead como «no contactar» (añade a la lista de supresión y cierra sus oportunidades) | Sesión (cookie + X-CSRF-Token) permiso: lead.write | |
| GET | /api/leads/:id/export | Exportar todos los datos de un lead (derecho de acceso/portabilidad) | Sesión (cookie + X-CSRF-Token) permiso: privacy.manage | |
| DELETE | /api/leads/:id | Eliminar un lead y todos sus datos (derecho de supresión) | Sesión (cookie + X-CSRF-Token) permiso: privacy.manage | { keep_suppression?: boolean } |
| GET | /api/privacy/suppression | Lista de supresión (solo se guarda un hash y una pista del email) | Sesión (cookie + X-CSRF-Token) permiso: privacy.manage | |
| POST | /api/privacy/suppression | Añadir email a la lista de no contactar | Sesión (cookie + X-CSRF-Token) permiso: privacy.manage | { email } |
| DELETE | /api/privacy/suppression/:id | Quitar de la lista (solo si la persona lo pide expresamente) | Sesión (cookie + X-CSRF-Token) permiso: privacy.manage | |
| POST | /api/privacy/retention/run | Aplicar ahora la política de retención | Sesión (cookie + X-CSRF-Token) permiso: privacy.manage | |
| GET | /api/orgs/current/export | Exportar TODOS los datos de la empresa (NDJSON por tablas; auditado) | Sesión (cookie + X-CSRF-Token) permiso: data.export |
Eventos
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/leads/:id/events | Registrar un evento de negocio para un lead (p. ej. quote_sent con amount) | Sesión o Bearer sk_… permiso: event.create | { type, properties?, occurred_at?, page_url? } |
| POST | /api/events | Registrar un evento de servidor (identifica al lead por lead_id, email o external_id; usado por el plugin de WordPress) | Sesión o Bearer sk_… permiso: event.create | { lead_id? | email? | external_id?, name?, phone?, type, properties?, occurred_at?, page_url?, anonymous_id?, consent_status?, consent_text? } |
Oportunidades
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /api/opportunities | Listar oportunidades (status=open|closed|all|<estado>, type, min_score, q, sort) | Sesión o Bearer sk_… permiso: opportunity.view | |
| GET | /api/opportunities/:id | Detalle de una oportunidad (lead, emails, respuestas, historial) | Sesión o Bearer sk_… permiso: opportunity.view | |
| POST | /api/opportunities/:id/generate-email | Generar un borrador de email personalizado (IA o plantilla) — nunca se envía solo | Sesión (cookie + X-CSRF-Token) permiso: email.generate | |
| PATCH | /api/emails/:id | Editar un borrador (vuelve a pasar las comprobaciones) | Sesión (cookie + X-CSRF-Token) permiso: email.approve | { subject, body } |
| POST | /api/opportunities/:id/approve | Aprobar un borrador (requiere persona; MEMBER o ADMIN) | Sesión (cookie + X-CSRF-Token) permiso: email.approve | { email_id, subject?, body?, acknowledge_flags? } |
| POST | /api/opportunities/:id/send | Enviar un email aprobado (ADMIN). Con approve=true aprueba y envía en un paso | Sesión (cookie + X-CSRF-Token) permiso: email.send | { email_id, approve?, subject?, body?, acknowledge_flags? } |
| POST | /api/emails/:id/cancel | Cancelar un email que espera en la cola de envío (ADMIN) | Sesión (cookie + X-CSRF-Token) permiso: email.send | |
| GET | /api/emails | Envíos de la empresa con su estado de entrega (cola, enviados, simulados, fallidos, rebotes…) | Sesión o Bearer sk_… | |
| POST | /api/emails/:id/discard | Descartar un borrador | Sesión (cookie + X-CSRF-Token) permiso: email.approve | |
| POST | /api/opportunities/:id/dismiss | Descartar (estado Ignorada) | Sesión (cookie + X-CSRF-Token) permiso: opportunity.update | { note? } |
| POST | /api/opportunities/:id/do-not-contact | No contactar: bloquea al contacto en todas las campañas futuras | Sesión (cookie + X-CSRF-Token) permiso: opportunity.update | |
| POST | /api/opportunities/:id/status | Cambiar estado manualmente (Nueva, Revisar, Contactada, Respondió, Perdida, Ignorada) | Sesión (cookie + X-CSRF-Token) permiso: opportunity.update | { status, note? } |
| POST | /api/opportunities/:id/recover | Marcar como recuperada con valor, fecha y fuente (atribución) | Sesión (cookie + X-CSRF-Token) permiso: opportunity.update | { value, date?, source?, note? } |
| POST | /api/analysis/run | Analizar ahora todos los leads (Opportunity Engine) | Sesión o Bearer sk_… permiso: analysis.run |
Ajustes
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /api/sender-domains | Dominios de envío propios de la empresa y sus registros DNS | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| POST | /api/sender-domains | Añadir un dominio de envío propio (devuelve los registros DNS) | Sesión (cookie + X-CSRF-Token) permiso: settings.update | { domain } |
| POST | /api/sender-domains/:id/check | Comprobar los registros DNS de un dominio de envío | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| DELETE | /api/sender-domains/:id | Quitar un dominio de envío (vuelve el remitente de la plataforma) | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| PATCH | /api/settings/sender | Elegir remitente: plataforma o dominio verificado | Sesión (cookie + X-CSRF-Token) permiso: settings.update | { mode: platform|domain, domain_id?, local_part? } |
| PATCH | /api/settings/business | Perfil de negocio, tono y comunicación | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| PATCH | /api/settings/organization | Datos de la empresa | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| POST | /api/settings/test-email | Enviar un email de prueba al usuario actual | Sesión (cookie + X-CSRF-Token) permiso: settings.update |
Respuestas
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/opportunities/:id/replies | Registrar la respuesta de un cliente; se clasifica y se notifica | Sesión (cookie + X-CSRF-Token) permiso: reply.create | { text } |
| POST | /api/replies/:id/classification | Corregir la clasificación de una respuesta | Sesión (cookie + X-CSRF-Token) permiso: reply.create | { classification } |
Estadísticas
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /api/stats | Métricas del dashboard (days=30|90|0) | Sesión o Bearer sk_… permiso: opportunity.view |
Alertas
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /api/notifications | Listar alertas | Sesión (cookie + X-CSRF-Token) permiso: notification.view | |
| POST | /api/notifications/read | Marcar alertas como leídas | Sesión (cookie + X-CSRF-Token) permiso: notification.view | { id? } |
Base de conocimiento
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/knowledge | Crear entrada | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| PATCH | /api/knowledge/:id | Editar entrada | Sesión (cookie + X-CSRF-Token) permiso: settings.update | |
| DELETE | /api/knowledge/:id | Eliminar entrada | Sesión (cookie + X-CSRF-Token) permiso: settings.update |
Reglas
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| PATCH | /api/rules/scoring/:id | Editar una regla de puntuación | Sesión (cookie + X-CSRF-Token) permiso: rules.update | |
| PATCH | /api/rules/detectors/:id | Activar/configurar un detector integrado | Sesión (cookie + X-CSRF-Token) permiso: rules.update | { active?, params?: { … } } |
| POST | /api/rules/custom | Crear regla personalizada (SI condiciones ENTONCES acciones) | Sesión (cookie + X-CSRF-Token) permiso: rules.update | { name, conditions: [{field, op, value}], actions: { create_opportunity?, score_delta?, recommended_action? } } |
| PATCH | /api/rules/custom/:id | Editar regla personalizada | Sesión (cookie + X-CSRF-Token) permiso: rules.update | |
| DELETE | /api/rules/custom/:id | Eliminar regla personalizada | Sesión (cookie + X-CSRF-Token) permiso: rules.update |
API keys
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/api-keys | Crear clave secreta (sk_…). Se muestra UNA vez; solo se guarda su hash | Sesión (cookie + X-CSRF-Token) permiso: apikeys.manage | { name, kind?: api|wordpress, scopes?: [ingest, read], expires_in_days? } |
| POST | /api/api-keys/:id/regenerate | Regenerar una clave (revoca la anterior y devuelve la nueva una sola vez) | Sesión (cookie + X-CSRF-Token) permiso: apikeys.manage | |
| GET | /api/integrations/ping | Comprobar una clave sk_ (usado por «Probar conexión» del plugin de WordPress) | Sesión o Bearer sk_… permiso: event.create | |
| DELETE | /api/api-keys/:id | Revocar clave | Sesión (cookie + X-CSRF-Token) permiso: apikeys.manage |
Webhooks
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/webhooks/inbound-email | Email entrante (respuestas). Compatible con JSON genérico, Mailgun routes y Postmark inbound | Secreto de webhook | { to, text } |
| POST | /api/webhooks/email/resend | Eventos de Resend: entregas, rebotes, quejas, fallos, aperturas, clics y dominios (firmados con Svix, idempotentes) | Secreto de webhook |
Operación
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| POST | /api/cron/run | Ejecutar tareas programadas (análisis, retención, salud de integraciones) | Bearer CRON_SECRET / METRICS_TOKEN | |
| GET | /health | Liveness: el proceso está vivo | Pública | |
| GET | /ready | Readiness: base de datos accesible y migraciones aplicadas | Pública | |
| GET | /api/health | Alias de /ready (compatibilidad con v0.2 y health check de Railway) | Pública | |
| GET | /api/wp-plugin/latest | Última versión del plugin de WordPress (comprobación de actualizaciones) | Pública | |
| GET | /api/metrics | Métricas Prometheus | Bearer CRON_SECRET / METRICS_TOKEN |
Email tracking
| Método | Ruta | Descripción | Autenticación | Cuerpo |
|---|---|---|---|---|
| GET | /t/o/:token | Píxel de apertura (opcional, desactivado por defecto) | Token firmado en la URL | |
| GET | /t/c/:token | Redirección de clic firmada | Token firmado en la URL |
Tipos de evento
page_view Visitó una páginaservice_view Visitó un serviciopricing_view Visitó precioscontact_view Visitó contactoproduct_view Vio un productoform_start Inició un formularioform_submit Envió un formularioquote_request Solicitó presupuestoquote_sent Presupuesto enviadoquote_accepted Aceptó el presupuestoquote_rejected Rechazó el presupuestoadd_to_cart Añadió al carritocheckout_start Inició el pagocheckout_abandon Abandonó el pagopurchase Compróbooking_start Inició una reservabooking_complete Completó una reservacustom_event Evento personalizadoEventos propios: usa el prefijo custom_ (p. ej. custom_demo_requested). Los importes se leen de amount, value o total.