# 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 <accessToken>
```

### 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": "<base64>",
  "keyFile": "<base64>",
  "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;
}
```
