# API Reference - Horux360 **Base URL:** `https://horuxfin.com/api` **Última actualización:** 2026-04-11 --- ## Autenticación Todos los endpoints (excepto auth y webhooks) requieren header: ``` Authorization: Bearer ``` ### Rate Limits (por IP) | Endpoint | Límite | Ventana | |----------|--------|---------| | `POST /auth/login` | 10 requests | 15 minutos | | `POST /auth/register` | 3 requests | 1 hora | | `POST /auth/refresh` | 20 requests | 15 minutos | | General `/api/*` | 30 requests/s | burst 50 | --- ## Auth (`/api/auth`) ### `POST /auth/register` Registra nueva empresa y usuario admin. Provisiona base de datos dedicada. **Body:** ```json { "empresa": { "nombre": "Mi Empresa", "rfc": "ABC123456789" }, "usuario": { "nombre": "Juan", "email": "juan@empresa.com", "password": "min8chars" } } ``` **Response:** `{ accessToken, refreshToken, user: UserInfo }` ### `POST /auth/login` ```json { "email": "usuario@empresa.com", "password": "..." } ``` **Response:** `{ accessToken, refreshToken, user: UserInfo }` ### `POST /auth/refresh` ```json { "refreshToken": "..." } ``` **Response:** `{ accessToken, refreshToken }` ### `POST /auth/logout` *(requiere auth)* ```json { "refreshToken": "..." } ``` ### `GET /auth/me` *(requiere auth)* **Response:** `UserInfo` --- ## Dashboard (`/api/dashboard`) ### `GET /dashboard/kpis` KPIs principales: ingresos, egresos, utilidad, margen, IVA balance, IVA a favor acumulado/histórico, conteo de CFDIs por régimen. **Query:** `fechaInicio`, `fechaFin` (default: mes actual) ### `GET /dashboard/ingresos-egresos` Datos mensuales de ingresos/egresos desglosados por régimen fiscal para gráfica anual. **Query:** `año` (default: año actual) ### `GET /dashboard/regimenes-periodo` Regímenes fiscales presentes en los CFDIs del rango de fechas. **Query:** `fechaInicio`, `fechaFin` ### `GET /dashboard/alertas` Alertas activas no resueltas, ordenadas por prioridad. **Query:** `limit` (default: 5) --- ## CFDI (`/api/cfdi`) ### `GET /cfdi` Lista paginada de CFDIs con filtros. **Query:** - `page` (default: 1), `limit` (default: 20) - `tipo`: `EMITIDO` | `RECIBIDO` - `tipoComprobante`: `I` | `E` | `T` | `P` | `N` - `estado`: `Vigente` | `Cancelado` | `0` | `1` - `fechaInicio`, `fechaFin` - `rfc`, `emisor`, `receptor`, `search` ### `GET /cfdi/resumen` Resumen de conteo por tipo y estado. ### `GET /cfdi/emisores` Lista de emisores únicos (RFC + nombre). **Query:** `search` ### `GET /cfdi/receptores` Lista de receptores únicos (RFC + nombre). **Query:** `search` ### `GET /cfdi/drill-down` CFDIs filtrados para drill-down desde dashboard. **Query:** `fechaInicio`, `fechaFin`, `type`, `tipoComprobante`, `page`, `limit` ### `GET /cfdi/:id` Detalle de un CFDI. ### `GET /cfdi/:id/conceptos` Conceptos (líneas de detalle) de un CFDI. ### `GET /cfdi/:id/xml` XML original del CFDI (descarga como archivo). ### `POST /cfdi` Crear un CFDI individual. Sujeto a límite de plan. ### `POST /cfdi/bulk` Carga masiva de CFDIs. Body limit: 50MB. Sujeto a límite de plan. ### `DELETE /cfdi/:id` Eliminar un CFDI. --- ## Impuestos (`/api/impuestos`) ### `GET /impuestos/iva/mensual` Datos mensuales de IVA (trasladado, acreditable, retenido, resultado, acumulado). **Query:** `año` (default: año actual) ### `GET /impuestos/iva/resumen` Resumen de IVA para un rango de fechas con desglose por régimen. **Query:** `fechaInicio`, `fechaFin` ### `GET /impuestos/isr/resumen` Resumen de ISR para un rango de fechas con desglose por régimen. **Query:** `fechaInicio`, `fechaFin` ### `GET /impuestos/isr/coeficiente` Coeficiente de utilidad del tenant para un año. **Query:** `anio` ### `PUT /impuestos/isr/coeficiente` *(admin)* Establecer coeficiente de utilidad. **Body:** `{ anio, coeficiente }` --- ## Alertas (`/api/alertas`) ### `GET /alertas` Lista de alertas con filtros opcionales. **Query:** `leida`, `resuelta`, `prioridad` ### `GET /alertas/:id` Detalle de una alerta. ### `GET /alertas/automaticas` Alertas auto-generadas de cumplimiento fiscal (lista negra, concentración, discrepancias, cancelaciones, efectivo). ### `GET /alertas/manuales` Obligaciones manuales pendientes. ### `GET /alertas/stats` Estadísticas de alertas (total, no leídas, por prioridad). ### Drill-down de alertas | Endpoint | Descripción | |----------|-------------| | `GET /alertas/drilldown/lista-negra-clientes` | Clientes en lista negra SAT | | `GET /alertas/drilldown/lista-negra-proveedores` | Proveedores en lista negra SAT | | `GET /alertas/drilldown/concentracion-clientes` | Análisis de concentración (clientes) | | `GET /alertas/drilldown/concentracion-proveedores` | Análisis de concentración (proveedores) | | `GET /alertas/drilldown/discrepancia-regimen` | Discrepancias de régimen fiscal | | `GET /alertas/drilldown/cancelaciones` | CFDIs cancelados | | `GET /alertas/drilldown/efectivo` | Análisis de método de pago efectivo | ### `POST /alertas` Crear alerta manual. ### `PATCH /alertas/:id` Actualizar alerta (leída, resuelta). ### `PATCH /alertas/manuales/:id/resolver` Resolver obligación manual. ### `DELETE /alertas/:id` Eliminar alerta. ### `POST /alertas/mark-all-read` Marcar todas las alertas como leídas. --- ## Conciliacion (`/api/conciliacion`) *(requiere feature 'conciliacion')* ### `GET /conciliacion` Lista CFDIs con estado de conciliacion (pendiente o conciliado). **Query:** - `tipo`: `EMITIDO` | `RECIBIDO` (requerido) - `fechaInicio`, `fechaFin`: rango de fecha de emision - `regimen`: clave de regimen fiscal (opcional) - `estado`: `conciliado` | `pendiente` (opcional, default: todos) **Reglas de exclusion:** - Recibidos: excluye PPD - Emitidos: excluye PPD para todos los regimenes excepto 605 y 616 - Tipo P usa `monto_pago_mxn` en vez de `total_mxn` ### `POST /conciliacion` *(admin, contador)* Conciliar CFDIs en batch. Auto-concilia PPD si la factura P lleva saldo a 0. ```json { "cfdiIds": [1, 2, 3], "fechaDePago": "2026-04-10", "idBanco": 1 } ``` ### `DELETE /conciliacion/:id` *(admin, contador)* Desconciliar un CFDI. Si es tipo P, tambien desconcilia la PPD auto-conciliada. --- ## Bancos (`/api/bancos`) ### `GET /bancos` Listar bancos del tenant. ### `POST /bancos` *(admin)* Crear banco. ```json { "banco": "BBVA", "terminacionCuenta": "1234" } ``` ### `PUT /bancos/:id` *(admin)* Editar banco. ### `DELETE /bancos/:id` *(admin)* Eliminar banco. Falla si tiene conciliaciones asociadas. --- ## Calendario (`/api/calendario`) ### `GET /calendario/generados` Eventos fiscales generados para un año, basados en el catálogo de eventos fiscales y días inhábiles. **Query:** `año` (default: año actual) --- ## Reportes (`/api/reportes`) *(requiere feature 'reportes' en plan)* ### `GET /reportes/estado-resultados` Estado de resultados (P&L). **Query:** `fechaInicio`, `fechaFin` ### `GET /reportes/flujo-efectivo` Flujo de efectivo. **Query:** `fechaInicio`, `fechaFin` ### `GET /reportes/comparativo` Comparativo año contra año. **Query:** `año` ### `GET /reportes/cuentas-x-pagar` Cuentas por pagar (facturas con saldo pendiente). **Query:** `fechaInicio`, `fechaFin`, `regimen` ### `GET /reportes/cuentas-x-cobrar` Cuentas por cobrar. **Query:** `fechaInicio`, `fechaFin`, `regimen` ### `GET /reportes/concentrado-rfc` Concentrado por RFC (top clientes/proveedores). **Query:** `tipo` (`cliente` | `proveedor`), `fechaInicio`, `fechaFin` --- ## Export (`/api/export`) ### `GET /export/cfdis` Exporta CFDIs a Excel. **Query:** `tipo`, `estado`, `fechaInicio`, `fechaFin` ### `GET /export/reporte` Exporta reporte a Excel. **Query:** `tipo` (`estado-resultados` | `flujo-efectivo`), `fechaInicio`, `fechaFin` --- ## Regímenes (`/api/regimenes`) ### `GET /regimenes` Catálogo completo de regímenes fiscales SAT. ### `GET /regimenes/activos` Regímenes activos del tenant. ### `PUT /regimenes/activos` *(admin)* Configurar regímenes activos. **Body:** `{ regimenIds: number[] }` ### `GET /regimenes/ignorados` Regímenes ignorados del tenant (excluidos de cálculos). ### `PUT /regimenes/ignorados` *(admin)* Configurar regímenes ignorados. **Body:** `{ regimenIds: number[] }` --- ## FIEL (`/api/fiel`) ### `POST /fiel/upload` Subir y validar credenciales FIEL (e.firma). ```json { "cerFile": "", "keyFile": "", "password": "..." } ``` - Archivos max 50KB cada uno - Password max 256 caracteres - Encriptación AES-256-GCM por componente ### `GET /fiel/status` Estado actual de la FIEL: configurada, RFC, serial, validez, días hasta expiración. ### `DELETE /fiel` Eliminar credenciales FIEL. --- ## SAT Sync (`/api/sat`) ### `POST /sat/sync` Iniciar sincronización manual con el SAT. ```json { "type": "daily", "dateFrom": "2026-01-01", "dateTo": "2026-01-31" } ``` ### `GET /sat/sync/status` Estado actual de sincronización (job activo, último completado, total sincronizados). ### `GET /sat/sync/history` Historial de sincronizaciones paginado. **Query:** `page`, `limit` ### `GET /sat/sync/:id` Detalle de un job de sincronización (progreso, paquetes, errores). ### `POST /sat/sync/:id/retry` Reintentar un job fallido. ### `GET /sat/cron` *(admin global)* Info del cron de sincronización automática (03:00 AM diario). ### `POST /sat/cron/run` *(admin global)* Ejecutar sincronización global manualmente. --- ## Usuarios (`/api/usuarios`) ### `GET /usuarios` Usuarios del tenant actual. ### `GET /usuarios/global/all` *(admin global)* Todos los usuarios de todas las empresas. ### `POST /usuarios/invite` Invitar usuario (genera password temporal con `crypto.randomBytes`). ```json { "email": "nuevo@empresa.com", "nombre": "María", "role": "contador" } ``` ### `PATCH /usuarios/:id` Actualizar usuario (nombre, role, active). Scope: tenant. ### `DELETE /usuarios/:id` Eliminar usuario. Scope: tenant. ### `PATCH /usuarios/global/:id` *(admin global)* Actualizar usuario de cualquier empresa. Puede cambiar tenant. ### `DELETE /usuarios/global/:id` *(admin global)* Eliminar usuario de cualquier empresa. --- ## Tenants / Clientes (`/api/tenants`) *(admin global)* ### `GET /tenants` Lista de todos los tenants/clientes. ### `GET /tenants/:id` Detalle de un tenant. ### `POST /tenants` Crear nuevo tenant. Provisiona base de datos dedicada. Envía email al admin. ```json { "nombre": "Empresa Nueva", "rfc": "ENE123456789", "plan": "business", "cfdiLimit": 500, "usersLimit": 3, "adminNombre": "Pedro", "adminEmail": "pedro@nueva.com", "amount": 999 } ``` ### `PUT /tenants/:id` Actualizar tenant (nombre, rfc, plan, limits, active). ### `DELETE /tenants/:id` Soft delete — renombra la base de datos a `{name}_deleted_{timestamp}`. --- ## Suscripciones (`/api/subscriptions`) *(admin global)* ### `GET /subscriptions/:tenantId` Suscripción activa del tenant. ### `POST /subscriptions/:tenantId/generate-link` Generar link de pago MercadoPago. ### `POST /subscriptions/:tenantId/mark-paid` Marcar como pagado manualmente. ```json { "amount": 999 } ``` ### `GET /subscriptions/:tenantId/payments` Historial de pagos. --- ## Webhooks (`/api/webhooks`) ### `POST /webhooks/mercadopago` Webhook de MercadoPago. Requiere headers: - `x-signature`: Firma HMAC-SHA256 - `x-request-id`: ID del request Maneja notificaciones de tipo `payment` y `preapproval`. --- ## Roles y Permisos | Rol | Descripción | Acceso | |-----|-------------|--------| | `admin` | Administrador del tenant | Todo dentro de su tenant + invitar usuarios + configuración | | `contador` | Contador | CFDI, impuestos, reportes, dashboard, alertas | | `visor` | Solo lectura | Dashboard, CFDI (solo ver), reportes | ### Admin Global El admin del tenant con RFC `HTS240708LJA` tiene acceso adicional: - Gestión de todos los tenants (`/api/tenants`) - Suscripciones (`/api/subscriptions`) - SAT cron (`/api/sat/cron`) - Impersonación via `X-View-Tenant` header (bypass de plan limits) - Gestión global de usuarios (`/api/usuarios/global/*`) --- ## Middlewares | Middleware | Descripción | |------------|-------------| | **auth** | Verifica JWT, extrae payload a `req.user`. Factory `authorize(...roles)` para roles. | | **tenant** | Resuelve pool de BD del tenant. Cache 5min. Soporta `X-View-Tenant` para admin global. | | **plan-limits** | Verifica suscripción activa. Read-only si inactiva. Limita creación de CFDIs. Cache 5min. | | **feature-gate** | Gate por features del plan (`requireFeature('reportes')`). 403 si no incluido. | | **error** | Handler centralizado. `AppError` para respuestas estructuradas; 500 para no manejados. | --- ## Tipos Compartidos (`@horux/shared`) ### UserInfo ```typescript interface UserInfo { id: string; email: string; nombre: string; role: 'admin' | 'contador' | 'visor'; tenantId: string; tenantName: string; tenantRfc: string; plan: string; } ``` ### JWTPayload ```typescript interface JWTPayload { userId: string; email: string; role: Role; tenantId: string; iat?: number; exp?: number; } ```