{"openapi":"3.1.0","info":{"title":"Ticke API","description":"API REST para el sistema de gestión fiscal Ticke.\n\n**Características principales:**\n- Gestión de usuarios y negocios\n- Facturación electrónica\n- Gestión de clientes\n- Cálculos fiscales automáticos\n- Autenticación JWT\n\n**Autenticación:**\nPara acceder a los endpoints protegidos, primero debes:\n1. Registrarte con POST /api/auth/register\n2. Iniciar sesión con POST /api/auth/login\n3. Usar el token JWT recibido en el header: `Authorization: Bearer {token}`\n\n**Errores:**\nTodos los 4xx/5xx devuelven JSON con `errorCode` estable, `message`\nlegible y pista de `resolution` (schema: `ErrorResponse`). Sin páginas HTML.\n\n**Rate limits:**\nLas respuestas API incluyen `RateLimit-Limit`, `RateLimit-Remaining`\ny `RateLimit-Reset`. Al agotar la cuota: 429 con `Retry-After`\n(segundos) y `errorCode` RATE_LIMIT_EXCEEDED. Límites: 5 req/min\npor IP en login, 60 req/min por usuario autenticado.\n\n**Versionado:**\nSin versionado en URL ni cabecera en V1. Los cambios incompatibles\nse anuncian en https://ticke.es/developers con ≥6 meses de migración;\nlas operaciones deprecadas se señalizan con `Sunset`/`Deprecation`.\n","contact":{"name":"Equipo Ticke","url":"https://ticke.es","email":"dev@ticke.es"},"license":{"name":"MIT License","url":"https://opensource.org/licenses/MIT"},"version":"1.0.0"},"servers":[{"url":"http://localhost:8080","description":"Servidor de desarrollo local"},{"url":"https://api.ticke.es","description":"Servidor de producción"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Segregacion Fiscal","description":"Endpoints para segregacion de IVA e IRPF por trimestre y ano"},{"name":"Agent Consent","description":"AI agent memory consent management"},{"name":"Onboarding","description":"User onboarding endpoints"},{"name":"Usuarios","description":"Gestión de usuarios del sistema"},{"name":"Products","description":"Business products and services catalog"},{"name":"Business","description":"Business management endpoints"},{"name":"Agent Model Config Internal","description":"Internal agent-facing model mapping"},{"name":"Billing Lock Internal","description":"Internal agent-facing billing lock verdict"},{"name":"WhatsApp Internal","description":"Internal agent-facing endpoints"},{"name":"AI Model Config","description":"Hot-swap the LiteLLM models used by the agent and OCR (SYSTEM_ADMIN only)"},{"name":"Fiscal Calendar","description":"Calendario fiscal AEAT (plazos 303, 130, 390, 111, 115, 349, 347, 100)"},{"name":"Invoice Numbering","description":"Invoice numbering configuration and preview endpoints"},{"name":"Admin Billing","description":"Admin views over Stripe subscriptions and webhook activity"},{"name":"WhatsApp","description":"User-facing WhatsApp linking management"},{"name":"Invitations","description":"Accept a guest-manager invitation (public)"},{"name":"Invoice Templates","description":"Manage customizable invoice PDF templates"},{"name":"GDPR","description":"GDPR compliance endpoints — right to erasure (Art. 17) and right of access (Art. 15)"},{"name":"Agent Knowledge","description":"Read-only view of what the AI agent remembers"},{"name":"Notifications","description":"System notification management"},{"name":"Stripe Billing Portal","description":"Authenticated billing portal endpoints"},{"name":"Facturas","description":"Gestión completa de facturas con operaciones CRUD y funcionalidades avanzadas"},{"name":"WhatsApp Bot","description":"Bot-facing endpoints for WhatsApp linking"},{"name":"Confirmation Tokens","description":"Tokens single-use que prueban consentimiento humano antes de acciones irreversibles"},{"name":"System Settings","description":"System settings management (SYSTEM_ADMIN only)"},{"name":"Autenticación","description":"Endpoints para registro, login y gestión de tokens"},{"name":"Business Invitations","description":"Owner-only invitation and member management"},{"name":"Documentos de Gastos","description":"Scanner AI de documentos de gastos con OCR y extracción automática"},{"name":"Agent Preferences","description":"Zero agent auto-confirm preferences"},{"name":"My Subscription","description":"Authenticated user's subscription summary"},{"name":"Clientes","description":"Gestión de clientes del sistema"},{"name":"Stripe Checkout","description":"Public self-service signup endpoints"},{"name":"Facturas Recurrentes","description":"Gestión de plantillas de facturación recurrente (MONTHLY/QUARTERLY/YEARLY)"},{"name":"Admin Verifactu","description":"Admin reconciliation of Verifactu invoices (SYSTEM_ADMIN only)"},{"name":"SEO","description":"Crawler directives"},{"name":"Notification Preferences","description":"Preferencias proactivas de notificación del usuario"},{"name":"Admin","description":"Panel de administración (SYSTEM_ADMIN only)"},{"name":"Modelos Fiscales","description":"Generacion y gestion de modelos fiscales (303, 130, 390, 349, 347, 111, 190)"},{"name":"Stripe Webhook","description":"Stripe event receiver (HMAC-signed)"},{"name":"Dashboard","description":"Métricas y análisis del dashboard principal"},{"name":"Agent AI Quota Internal","description":"Internal agent-facing AI quota gate"},{"name":"Template Metadata","description":"Template field definitions and metadata"},{"name":"Magic-link Signup","description":"Public magic-link signup endpoints"}],"paths":{"/api/users/{id}":{"get":{"tags":["Usuarios"],"summary":"Obtener usuario por ID","description":"Devuelve la información de un usuario específico (solo administradores)","operationId":"getUserById","parameters":[{"name":"id","in":"path","description":"ID del usuario","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Usuario encontrado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Usuario no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Usuarios"],"summary":"Actualizar usuario","description":"Actualiza la información de un usuario específico (solo administradores)","operationId":"updateUser","parameters":[{"name":"id","in":"path","description":"ID del usuario","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequest"}}},"required":true},"responses":{"200":{"description":"Usuario actualizado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Usuario no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Usuarios"],"summary":"Desactivar usuario","description":"Desactiva un usuario específico (soft delete, solo administradores)","operationId":"deactivateUser","parameters":[{"name":"id","in":"path","description":"ID del usuario","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Usuario desactivado exitosamente"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Usuario no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users/me":{"get":{"tags":["Usuarios"],"summary":"Obtener perfil propio","description":"Devuelve la información del usuario autenticado","operationId":"getCurrentUser","responses":{"200":{"description":"Perfil obtenido exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Usuarios"],"summary":"Actualizar perfil propio","description":"Actualiza la información del usuario autenticado","operationId":"updateCurrentUser","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequest"}}},"required":true},"responses":{"200":{"description":"Perfil actualizado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"Datos inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users/me/password":{"put":{"tags":["Usuarios"],"summary":"Cambiar contraseña","description":"Permite al usuario cambiar su propia contraseña","operationId":"changePassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"200":{"description":"Contraseña actualizada exitosamente"},"400":{"description":"Contraseña actual incorrecta o nueva contraseña inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users/me/active-business":{"put":{"tags":["Usuarios"],"summary":"Set active business","description":"Persists the user's selected active business (validates membership).","operationId":"setActiveBusiness","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetActiveBusinessRequest"}}},"required":true},"responses":{"200":{"description":"Active business updated"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not a member of the requested business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/lines/clave":{"put":{"tags":["Modelos Fiscales"],"summary":"Corregir clave de línea (Modelo 349)","description":"Corrige la clave de operacion (E/A/S) de una linea agregada de un Modelo 349","operationId":"applyLineClave","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyLineClaveRequest"}}},"required":true},"responses":{"200":{"description":"Correccion aplicada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Formulario no modificable, no es un 349 o linea no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/adjustments":{"put":{"tags":["Modelos Fiscales"],"summary":"Aplicar ajuste manual","description":"Modifica una casilla manualmente","operationId":"applyAdjustment","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyAdjustmentRequest"}}},"required":true},"responses":{"200":{"description":"Ajuste aplicado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Formulario no modificable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/recurring-invoices/{id}":{"get":{"tags":["Facturas Recurrentes"],"summary":"Obtener detalle de una plantilla recurrente","operationId":"get","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Plantilla encontrada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/RecurringInvoiceScheduleDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Plantilla no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Facturas Recurrentes"],"summary":"Actualizar plantilla recurrente","description":"Los cambios solo aplican a futuras generaciones (AC-5).","operationId":"update","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRecurringInvoiceScheduleRequest"}}},"required":true},"responses":{"200":{"description":"Plantilla actualizada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/RecurringInvoiceScheduleDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Plantilla no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Facturas Recurrentes"],"summary":"Eliminar plantilla (soft delete)","description":"Las facturas históricas se preservan (AC-9).","operationId":"delete","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Plantilla eliminada"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/products/{id}":{"get":{"tags":["Products"],"summary":"Get an active product or service","operationId":"getProduct","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Active product not found in the current business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Products"],"summary":"Replace editable product or service details","description":"Full replacement (not a patch): omitted optional fields reset to their defaults (description null, unit \"ud\", taxRate 21.00, isTaxExempt false)","operationId":"updateProduct","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveProductRequest"}}},"required":true},"responses":{"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Active product not found in the current business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Products"],"summary":"Soft-delete a product or service","description":"Marks it inactive; it disappears from list and detail","operationId":"deleteProduct","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Product deleted"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Active product not found in the current business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/notifications/{notificationId}/read":{"put":{"tags":["Notifications"],"summary":"Mark notification as read","description":"Marks a single notification as read. Idempotent - no error if already read.","operationId":"markAsRead","parameters":[{"name":"notificationId","in":"path","description":"Notification ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Notification marked as read"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No access to this notification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Notification not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/notifications/read-all":{"put":{"tags":["Notifications"],"summary":"Mark all notifications as read","description":"Marks all unread notifications as read for the current user","operationId":"markAllAsRead","responses":{"204":{"description":"All notifications marked as read"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/notification-preferences":{"get":{"tags":["Notification Preferences"],"summary":"Obtener preferencias de notificación","description":"Devuelve las 6 preferencias (3 kinds × 2 channels), hora preferida, timezone y estado de WhatsApp.","operationId":"getPreferences","responses":{"200":{"description":"Preferencias obtenidas","content":{"*/*":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Notification Preferences"],"summary":"Actualizar preferencias de notificación","description":"Upsert de preferencias, hora preferida y timezone. Devuelve el estado resultante.","operationId":"updatePreferences","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Preferencias actualizadas","content":{"*/*":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"400":{"description":"preferredHour fuera de rango o timezone inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/me/agent-preferences":{"get":{"tags":["Agent Preferences"],"summary":"Get auto-confirm preferences","description":"Returns the full auto-confirmable catalogue with stored values applied.","operationId":"getPreferences_1","responses":{"200":{"description":"Preferences retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AgentActionPreferencesResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Agent Preferences"],"summary":"Update auto-confirm preference","description":"Enables or disables auto-confirm for a single auto-confirmable action.","operationId":"updatePreference","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentActionPreferenceUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Preference updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AgentActionPreferencesResponse"}}}},"400":{"description":"Action is not auto-confirmable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Auto-confirm is disabled server-wide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{invoiceId}/lines/{lineId}":{"get":{"tags":["invoice-line-controller"],"summary":"Get invoice line","description":"Returns a single invoice line by id.","operationId":"getInvoiceLineById","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"lineId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceLineDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["invoice-line-controller"],"summary":"Update invoice line","description":"Updates description, quantities or prices of an invoice line.","operationId":"updateInvoiceLine","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"lineId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInvoiceLineRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceLineDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["invoice-line-controller"],"summary":"Delete invoice line","description":"Removes a line from a draft invoice.","operationId":"deleteInvoiceLine","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"lineId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/invoices/{id}":{"get":{"tags":["Facturas"],"summary":"Get invoice","description":"Returns a single invoice with its lines by id.","operationId":"getInvoiceById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Facturas"],"summary":"Update invoice","description":"Updates a draft invoice and its lines.","operationId":"updateInvoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInvoiceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Facturas"],"summary":"Delete invoice","description":"Deletes a draft invoice.","operationId":"deleteInvoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/status":{"put":{"tags":["Facturas"],"summary":"Change invoice status","description":"Transitions an invoice to a new lifecycle status.","operationId":"changeInvoiceStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/payment-status":{"put":{"tags":["Facturas"],"summary":"Update payment status","description":"Updates paid/unpaid state and amounts of an invoice.","operationId":"updatePaymentStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePaymentStatusRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/clients/{id}":{"get":{"tags":["Clientes"],"summary":"Obtener cliente por ID","description":"Devuelve la información de un cliente específico","operationId":"getClientById","parameters":[{"name":"id","in":"path","description":"ID del cliente","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Cliente encontrado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ClientDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Cliente no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Clientes"],"summary":"Actualizar cliente","description":"Actualiza la información de un cliente específico","operationId":"updateClient","parameters":[{"name":"id","in":"path","description":"ID del cliente","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateClientRequest"}}},"required":true},"responses":{"200":{"description":"Cliente actualizado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ClientDto"}}}},"400":{"description":"Datos de cliente inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Cliente no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Clientes"],"summary":"Desactivar cliente","description":"Desactiva un cliente específico (soft delete). Requiere X-Confirmation-Token.","operationId":"deactivateClient","parameters":[{"name":"id","in":"path","description":"ID del cliente","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Confirmation-Token","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"204":{"description":"Cliente desactivado exitosamente"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token de confirmación faltante o inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Cliente no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}":{"get":{"tags":["Business"],"summary":"Get business details","description":"Retrieve detailed information about a business","operationId":"getBusiness","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Business retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BusinessDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Business"],"summary":"Update business","description":"Update business information","operationId":"updateBusiness","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBusinessRequest"}}},"required":true},"responses":{"200":{"description":"Business updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BusinessDto"}}}},"400":{"description":"Invalid business data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/templates/{templateId}":{"get":{"tags":["Invoice Templates"],"summary":"Get template by ID","operationId":"getTemplate","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceTemplateDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Invoice Templates"],"summary":"Update existing template","operationId":"updateTemplate","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceTemplateDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Invoice Templates"],"summary":"Delete template (cannot delete default)","operationId":"deleteTemplate","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/invoice-numbering/config":{"get":{"tags":["Invoice Numbering"],"summary":"Get numbering configuration","description":"Retrieve the current invoice numbering configuration for a business. Returns default configuration if none has been set.","operationId":"getConfig","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Configuration retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceNumberingConfigDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied to this business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Invoice Numbering"],"summary":"Update numbering configuration","description":"Update the invoice numbering configuration for a business. Only provided fields will be updated. Requires owner or admin role.","operationId":"updateConfig","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNumberingConfigRequest"}}},"required":true},"responses":{"200":{"description":"Configuration updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceNumberingConfigDto"}}}},"400":{"description":"Invalid configuration values","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied - requires owner or admin role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/expense-documents/{documentId}":{"get":{"tags":["Documentos de Gastos"],"summary":"Obtener documento por ID","description":"Devuelve los detalles completos de un documento de gasto incluyendo datos extraídos por AI","operationId":"getDocument","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","description":"ID del documento","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Documento obtenido exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Documento no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Documentos de Gastos"],"summary":"Actualizar datos del documento","description":"Actualiza los datos extraídos del documento (correcciones manuales o desde AI)","operationId":"updateDocument","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","description":"ID del documento","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExpenseDocumentRequest"}}},"required":true},"responses":{"200":{"description":"Documento actualizado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"400":{"description":"Datos inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Documento no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Documentos de Gastos"],"summary":"Eliminar documento","description":"Elimina físicamente un documento de gasto y su archivo asociado","operationId":"deleteDocument","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","description":"ID del documento","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Documento eliminado exitosamente"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Documento no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/expense-categories":{"get":{"tags":["Business"],"summary":"Get expense categories","description":"Get the list of expense categories for a business","operationId":"getExpenseCategories","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Categories retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Business"],"summary":"Update expense categories","description":"Update the comma-separated list of expense categories for a business","operationId":"updateExpenseCategories","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Categories updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BusinessDto"}}}},"400":{"description":"Invalid categories data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/agent/consent":{"get":{"tags":["Agent Consent"],"summary":"Get current consent state","description":"Returns the current AI agent memory consent settings for the authenticated user's business.","operationId":"getConsent","responses":{"200":{"description":"Consent settings retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ConsentResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Agent Consent"],"summary":"Update consent preferences","description":"Updates AI agent memory consent preferences. If memory is disabled, any previously stored agent data will be erased asynchronously.","operationId":"updateConsent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRequest"}}},"required":true},"responses":{"200":{"description":"Consent preferences updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ConsentResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/admin/settings/{key}":{"get":{"tags":["System Settings"],"summary":"Get specific setting","description":"Retrieves a system setting by its key identifier. Only accessible to SYSTEM_ADMIN.","operationId":"getSetting","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Setting retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SystemSettingDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Setting not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["System Settings"],"summary":"Update system setting","description":"Updates a system setting value by key. Generic update without validation. Only accessible to SYSTEM_ADMIN.","operationId":"updateSetting","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingRequest"}}},"required":true},"responses":{"200":{"description":"Setting updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SystemSettingDTO"}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Setting not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings/verifactu/provider":{"put":{"tags":["System Settings"],"summary":"Change VeriFactu provider","description":"Changes the active VeriFactu provider (e.g., 'irene_solutions'). Cache is automatically cleared. Only accessible to SYSTEM_ADMIN.","operationId":"setVerifactuProvider","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"VeriFactu provider updated successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings/verifactu/enabled":{"put":{"tags":["System Settings"],"summary":"Toggle VeriFactu enabled status","description":"Enables or disables VeriFactu integration. When disabled, invoices are not sent to AEAT (mock mode). Cache is automatically cleared. Only accessible to SYSTEM_ADMIN.","operationId":"setVerifactuEnabled","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"}}}},"required":true},"responses":{"200":{"description":"VeriFactu status updated successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings/seed-template":{"get":{"tags":["System Settings"],"summary":"Get seed template","description":"Retrieves the current seed template JSON used for invoice template generation. Only accessible to SYSTEM_ADMIN.","operationId":"getSeedTemplate","responses":{"200":{"description":"Seed template retrieved successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/JsonNode"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Seed template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["System Settings"],"summary":"Update seed template","description":"Updates the seed template with full validation. Validates required fields, QR code size, and template structure. Only accessible to SYSTEM_ADMIN.","operationId":"updateSeedTemplate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingRequest"}}},"required":true},"responses":{"200":{"description":"Seed template updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SystemSettingDTO"}}}},"400":{"description":"Invalid template structure or missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Seed template setting not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/ai-models":{"get":{"tags":["AI Model Config"],"summary":"Get active model mapping and selectable catalog","description":"Returns the current tier→alias mapping plus every selectable alias.","operationId":"getConfig_1","responses":{"200":{"description":"Config retrieved","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AiModelConfigResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]},"put":{"tags":["AI Model Config"],"summary":"Update the model mapping","description":"Assigns a LiteLLM alias to each tier. Each alias must be a valid catalog option for its tier.","operationId":"updateConfig_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiModelTiersRequest"}}},"required":true},"responses":{"200":{"description":"Mapping updated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AiModelTiers"}}}},"400":{"description":"Invalid alias for a tier","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/ai-models/catalog":{"put":{"tags":["AI Model Config"],"summary":"Replace the selectable alias catalog","description":"Sets the full list of LiteLLM aliases selectable for any tier. An alias currently assigned to a tier may not be removed. Each alias must also exist as a model group in LiteLLM to work.","operationId":"updateCatalog","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiModelCatalogRequest"}}},"required":true},"responses":{"200":{"description":"Catalog updated","content":{"*/*":{"schema":{"type":"array","items":{"type":"string"}}}}},"400":{"description":"An in-use alias would be removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/users/me/email-change":{"post":{"tags":["Usuarios"],"summary":"Iniciar cambio de email","description":"Verifica la contraseña actual y envía un link de confirmación al nuevo email. El cambio NO se aplica hasta que se confirma vía /me/email-change/confirm.","operationId":"initiateEmailChange","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeEmailRequest"}}},"required":true},"responses":{"204":{"description":"Verificación enviada al nuevo email"},"400":{"description":"Contraseña incorrecta o email inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Email ya en uso por otra cuenta","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users/me/email-change/confirm":{"post":{"tags":["Usuarios"],"summary":"Confirmar cambio de email","description":"Aplica el cambio de email usando el token enviado al nuevo email. El email anterior recibirá una notificación.","operationId":"confirmEmailChange","parameters":[{"name":"token","in":"query","description":"Token de verificación recibido por email","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Email cambiado exitosamente"},"400":{"description":"Token inválido o expirado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Email ya en uso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users/me/avatar":{"get":{"tags":["Usuarios"],"summary":"Obtener avatar","description":"Devuelve la imagen de perfil del usuario","operationId":"getAvatar","responses":{"200":{"description":"Avatar obtenido exitosamente","content":{"image/jpeg":{"schema":{"type":"string","format":"byte"}},"image/png":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"El usuario no tiene avatar","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Usuarios"],"summary":"Subir avatar","description":"Permite al usuario subir una imagen de perfil","operationId":"uploadAvatar","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Avatar subido exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"Archivo inválido o formato no soportado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/regenerate":{"post":{"tags":["Modelos Fiscales"],"summary":"Recalcular formulario","description":"Recalcula el formulario preservando ajustes manuales","operationId":"regenerateForm","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Formulario recalculado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Formulario no modificable, o Modelo 130 no soportado para actividad empresarial (IAE seccion 1) - MODELO_130_BUSINESS_ACTIVITY_UNSUPPORTED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Negocio dado de baja para el Modelo 130 (MODELO_130_ACTIVITY_NOT_ACTIVE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/mark-filed":{"post":{"tags":["Modelos Fiscales"],"summary":"Marcar como presentado","description":"Marca el formulario como presentado ante la AEAT","operationId":"markAsFiled","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkFiledRequest"}}}},"responses":{"200":{"description":"Formulario marcado como presentado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Formulario no presentable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/lock":{"post":{"tags":["Modelos Fiscales"],"summary":"Bloquear formulario","description":"Bloquea el formulario para evitar modificaciones","operationId":"lockForm","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Formulario bloqueado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Formulario no bloqueable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/generate":{"post":{"tags":["Modelos Fiscales"],"summary":"Generar formulario","description":"Genera un nuevo formulario fiscal con calculos automaticos","operationId":"generateForm","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFormRequest"}}},"required":true},"responses":{"201":{"description":"Formulario generado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Modelo 130 no soportado para actividad empresarial (IAE seccion 1) - MODELO_130_BUSINESS_ACTIVITY_UNSUPPORTED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Ya existe un formulario para este periodo, o negocio dado de baja para el Modelo 130 (MODELO_130_ACTIVITY_NOT_ACTIVE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/stripe/webhook":{"post":{"tags":["Stripe Webhook"],"summary":"Receive Stripe webhook event","description":"Verifies HMAC signature, persists event with idempotent PK, dispatches to handler.","operationId":"receive","parameters":[{"name":"Stripe-Signature","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Event processed or duplicate ignored","content":{"*/*":{"schema":{"type":"string"}}}},"400":{"description":"Invalid signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Handler failure (Stripe will retry)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/recurring-invoices":{"get":{"tags":["Facturas Recurrentes"],"summary":"Listar plantillas recurrentes","description":"Lista paginada de plantillas activas para el negocio del usuario autenticado.","operationId":"list","parameters":[{"name":"page","in":"query","description":"Número de página (0-indexed)","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","description":"Tamaño de página","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","description":"Campo de ordenamiento","required":false,"schema":{"type":"string","default":"nextRunAt"}},{"name":"sortDirection","in":"query","description":"Dirección de ordenamiento (asc|desc)","required":false,"schema":{"type":"string","default":"asc"}}],"responses":{"200":{"description":"Lista paginada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageRecurringInvoiceScheduleDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Facturas Recurrentes"],"summary":"Crear plantilla recurrente","operationId":"create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRecurringInvoiceScheduleRequest"}}},"required":true},"responses":{"201":{"description":"Plantilla creada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/RecurringInvoiceScheduleDto"}}}},"400":{"description":"Datos inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/recurring-invoices/{id}/run":{"post":{"tags":["Facturas Recurrentes"],"summary":"Generar factura ahora (on-demand)","description":"Genera inmediatamente una factura desde esta plantilla. Funciona también con plantillas pausadas (el usuario confirma en la UI) y NO modifica nextRunAt — el calendario automático sigue intacto.","operationId":"runNow","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Factura generada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceSummaryDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Plantilla no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"La plantilla ya está siendo procesada (cron en curso)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/recurring-invoices/{id}/resume":{"post":{"tags":["Facturas Recurrentes"],"summary":"Reanudar plantilla","description":"Recalcula nextRunAt desde hoy. Meses pausados NO se rellenan (AC-7).","operationId":"resume","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Plantilla reanudada"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/recurring-invoices/{id}/pause":{"post":{"tags":["Facturas Recurrentes"],"summary":"Pausar plantilla","operationId":"pause","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Plantilla pausada (idempotente)"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/products":{"get":{"tags":["Products"],"summary":"List active products and services","description":"Literal, case-insensitive name/description search; ordered by name then ID","operationId":"getProducts","parameters":[{"name":"search","in":"query","required":false,"schema":{"type":"string","default":"","maxLength":255,"minLength":0}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20,"maximum":100,"minimum":1}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageProductDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Products"],"summary":"Create a product or service","operationId":"createProduct","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveProductRequest"}}},"required":true},"responses":{"201":{"description":"Product created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProductDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/onboarding/complete":{"post":{"tags":["Onboarding"],"summary":"Complete onboarding","description":"Creates a business for the authenticated user. Only users without a business can use this.","operationId":"completeOnboarding","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingRequest"}}},"required":true},"responses":{"201":{"description":"Business created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/OnboardingResponse"}}}},"400":{"description":"User already has a business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/notifications":{"get":{"tags":["Notifications"],"summary":"List notifications","description":"Returns paginated list of notifications for the current user, including business-wide notifications","operationId":"getNotifications","parameters":[{"name":"page","in":"query","description":"Page number (0-indexed)","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"unreadOnly","in":"query","description":"Filter to unread notifications only","required":false,"schema":{"type":"boolean","default":false}},{"name":"severity","in":"query","description":"Filter by severity level","required":false,"schema":{"type":"string","enum":["INFO","WARNING","ERROR","SUCCESS"]}}],"responses":{"200":{"description":"Notifications retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PagedResponseNotificationDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Notifications"],"summary":"Create notification","description":"Creates a new notification for the current user's business. Supports deduplication via referenceId.","operationId":"createNotification","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNotificationRequest"}}},"required":true},"responses":{"201":{"description":"Notification created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/NotificationDto"}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/notification-preferences/enable-whatsapp":{"post":{"tags":["Notification Preferences"],"summary":"Activar canal WhatsApp","description":"Marca enabled=true en todas las preferencias con channel=AGENT_WHATSAPP del usuario.","operationId":"enableWhatsapp","responses":{"200":{"description":"Canal WhatsApp activado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"No autenticado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices":{"get":{"tags":["Facturas"],"summary":"List invoices","description":"Returns paginated invoices of the current business with search and date filters.","operationId":"getInvoices","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"search","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"clientId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"createdAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"desc"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PagedResponseInvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Facturas"],"summary":"Crear factura","description":"Crea una factura en borrador. Acepta un header opcional Idempotency-Key (o X-Idempotency-Key): repetir la petición con la misma key devuelve 200 con la factura existente en lugar de crear un duplicado. Los cuerpos no se comparan: la misma key con un payload distinto también devuelve la factura original. Si la key pertenece a una factura ya eliminada, la petición se rechaza con 409 (INVOICE_IDEMPOTENCY_KEY_CONFLICT).","operationId":"createInvoice","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}},{"name":"X-Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvoiceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{invoiceId}/lines":{"get":{"tags":["invoice-line-controller"],"summary":"List invoice lines","description":"Returns all lines of an invoice in the current business.","operationId":"getInvoiceLines","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceLineDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["invoice-line-controller"],"summary":"Create invoice line","description":"Adds a line (description, quantity, prices, taxes) to a draft invoice.","operationId":"createInvoiceLine","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvoiceLineRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceLineDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/invoices/{id}/void":{"post":{"tags":["Facturas"],"summary":"Anular factura sin enviar","description":"Anula una factura en borrador o lista sin enviarla a AEAT","operationId":"voidInvoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Factura anulada exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Factura no se puede anular (ya fue enviada)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/verifactu/retry":{"post":{"tags":["Facturas"],"summary":"Reintentar registro en VeriFactu","description":"Reintenta el registro de una factura que falló con error de proveedor (PROVIDER_ERROR)","operationId":"retryVerifactuRegistration","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Reintento procesado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Factura no puede reintentarse (no tiene PROVIDER_ERROR)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/verifactu/retry-rectification":{"post":{"tags":["Facturas"],"summary":"Reintentar registro de rectificativa en VeriFactu","description":"Reintenta el registro de una rectificativa R1 que quedó en PENDING_REGISTRATION (respuesta perdida) o ERROR + PROVIDER_ERROR (rollout previo). Reutiliza el número R asignado para que AEAT pueda dedup vía error 3000.","operationId":"retryVerifactuRectification","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Reintento procesado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Estado no permite retry o no es rectificativa","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Operación previa todavía en curso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/verifactu/retry-cancellation":{"post":{"tags":["Facturas"],"summary":"Reintentar cancelación en VeriFactu","description":"Reintenta la cancelación de una factura que quedó en PENDING_CANCELLATION (respuesta perdida) o ERROR + PROVIDER_ERROR. Reutiliza el invoiceNumber para preservar IDFactura.","operationId":"retryVerifactuCancellation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Reintento procesado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Estado no permite retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Operación previa todavía en curso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/store-pdfs":{"post":{"tags":["Facturas"],"summary":"Almacenar ambos PDFs de factura registrada","description":"Almacena el PDF borrador (sin QR) y el PDF final (con QR) de una factura registrada en VeriFactu. Solo disponible para facturas que han sido registradas exitosamente.","operationId":"storeBothPdfs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreBothPdfsRequest"}}},"required":true},"responses":{"200":{"description":"Ambos PDFs almacenados exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"La factura no ha sido registrada en VeriFactu","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Servicio de almacenamiento no disponible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/store-pdf":{"post":{"tags":["Facturas"],"summary":"Store invoice PDF","description":"Persists a generated PDF in object storage.","operationId":"storePdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorePdfRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/StorePdfResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/send":{"post":{"tags":["Facturas"],"summary":"Send invoice","description":"Marks the invoice as sent to the customer.","operationId":"sendInvoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/return-to-draft":{"post":{"tags":["Facturas"],"summary":"Devolver factura a borrador","description":"Devuelve una factura con error a estado borrador para corregirla","operationId":"returnInvoiceToDraft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Factura devuelta a borrador exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Factura no está en estado de error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/resend-email":{"post":{"tags":["Facturas"],"summary":"Reenviar email de factura","description":"Reenvía el email de la factura al cliente. Solo disponible para facturas registradas con cliente que tenga email.","operationId":"resendInvoiceEmail","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Email reenviado correctamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ResendEmailResponse"}}}},"400":{"description":"La factura no puede reenviarse (no registrada o cliente sin email)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/register":{"post":{"tags":["Facturas"],"summary":"Registrar factura en VeriFactu","description":"Registra una factura en borrador en VeriFactu (AEAT). Transición: DRAFT → REGISTERED (éxito) o ERROR (fallo). Requiere X-Confirmation-Token (SEC-AG-04).","operationId":"registerInvoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Confirmation-Token","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Factura procesada (ver estado resultante)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Factura no está en estado borrador","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token de confirmación faltante o inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/rectifications":{"post":{"tags":["Facturas"],"summary":"Emitir factura rectificativa R1","description":"Emite una factura rectificativa R1 (error fundado en derecho) sobre la factura original indicada. Requiere X-Confirmation-Token (SEC-AG-04).","operationId":"createRectification","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Confirmation-Token","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRectificationRequest"}}},"required":true},"responses":{"201":{"description":"Rectificativa emitida con warnings opcionales","content":{"*/*":{"schema":{"$ref":"#/components/schemas/RectificationResponseDto"}}}},"400":{"description":"Original no rectificable o motivo insuficiente","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token de confirmación faltante o inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura original no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"AEAT/Irene rechazó la rectificación","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/mark-paid":{"post":{"tags":["Facturas"],"summary":"Mark invoice as paid","description":"Registers full payment of an invoice.","operationId":"markInvoiceAsPaid","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/generate-pdfs":{"post":{"tags":["Facturas"],"summary":"Generar y almacenar los PDFs de una factura registrada","description":"Renderiza el PDF borrador y el final vía ticke-headless y los almacena en S3. Idempotente por defecto: si la factura ya tiene ambos PDFs, no vuelve a generarlos. Con force=true los regenera y sobrescribe — reparación para facturas cuyo PDF almacenado quedó mal (sin número fiscal o sin QR). NUNCA vuelve a registrar la factura en VeriFactu.","operationId":"generatePdfs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"force","in":"query","description":"Regenera y sobrescribe los PDFs aunque ya estén almacenados","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"PDFs generados y almacenados (o ya existentes)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"La factura no ha sido registrada en VeriFactu","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Servicio de renderizado no disponible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Renderizado backend deshabilitado (ticke.headless.enabled=false)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/generate-pdf":{"post":{"tags":["Facturas"],"summary":"Generate invoice PDF","description":"Renders the legal PDF of a registered invoice.","operationId":"generateInvoicePDF","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/cancel":{"post":{"tags":["Facturas"],"summary":"Anular factura registrada","description":"Anula una factura registrada en AEAT. Requiere acknowledgement explícito cuando el trimestre ya está declarado. Requiere X-Confirmation-Token (SEC-AG-04).","operationId":"cancelInvoice","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Confirmation-Token","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelInvoiceRequest"}}}},"responses":{"200":{"description":"Factura anulada exitosamente (idempotente si ya estaba anulada)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceDto"}}}},"400":{"description":"Factura no anulable (DRAFT, rectificada, sin CSV, o trimestre declarado sin ack)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Token de confirmación faltante o inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Operación VeriFactu previa todavía en curso","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"AEAT/Irene rechazó la anulación","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/send-reminders":{"post":{"tags":["Facturas"],"summary":"Enviar recordatorios masivos","description":"Envía recordatorios de pago a facturas pendientes","operationId":"sendBulkReminders","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkOperationRequest"}}},"required":true},"responses":{"200":{"description":"Recordatorios enviados","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BulkOperationResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/export":{"post":{"tags":["Facturas"],"summary":"Exportar facturas","description":"Exporta facturas a CSV, Excel o PDF según los filtros especificados","operationId":"exportInvoices","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportRequest"}}},"required":true},"responses":{"200":{"description":"Archivo exportado exitosamente","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Parámetros de exportación inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/bulk":{"post":{"tags":["Facturas"],"summary":"Operaciones masivas","description":"Realiza operaciones masivas sobre un conjunto de facturas","operationId":"bulkOperation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkOperationRequest"}}},"required":true},"responses":{"200":{"description":"Operación masiva completada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BulkOperationResponse"}}}},"400":{"description":"Solicitud inválida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invitations/{token}/accept":{"post":{"tags":["Invitations"],"summary":"Accept an invitation","description":"Consumes a single-use invitation token, associates the invitee with the business as a read-only member, and returns JWT credentials.","operationId":"accept","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptRequest"}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AcceptResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/internal/whatsapp-token":{"post":{"tags":["WhatsApp Internal"],"summary":"Generate agent token for WhatsApp user","description":"Generates a short-lived JWT for the agent to act on behalf of a linked WhatsApp user.","operationId":"generateToken","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsappTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token generated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/WhatsappTokenResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Phone number not linked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"User has no business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/gdpr/export":{"post":{"tags":["GDPR"],"summary":"Request data export","description":"Idempotent GDPR data export (right of access, Art. 15 GDPR). Returns the in-flight or still-downloadable request when one exists (200), otherwise queues a new one (202) — poll GET /api/gdpr/export/{exportId} for status. EXPIRED/FAILED requests never block a fresh one. OWNER/ADMIN only. Rate limited to 1 live export per 7 days. Download link expires after 24 hours.","operationId":"requestExport","responses":{"200":{"description":"Usable export request already exists","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GdprExportRequestDTO"}}}},"202":{"description":"Export request accepted and queued","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GdprExportRequestDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not an owner/admin of the business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — one live export per 7 days","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/gdpr/erasure":{"get":{"tags":["GDPR"],"summary":"List erasure requests","description":"Returns a paginated list of erasure requests for the authenticated user, ordered by most recent first.","operationId":"listErasureRequests","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"Paginated list of erasure requests","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageGdprDeletionRequestDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["GDPR"],"summary":"Request data erasure","description":"Runs a GDPR erasure request. AGENT_ONLY deletes AI memory only; FULL additionally anonymises fiscal data. The erasure runs before the response is written, so 200 means it actually completed (status = COMPLETED) — a partial failure answers 500 and the request row is left in FAILED for auditing. Clients must NOT treat any non-200 response as a completed deletion.","operationId":"requestErasure","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GdprErasureRequest"}}},"required":true},"responses":{"200":{"description":"Erasure completed (status = COMPLETED)","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GdprDeletionRequestDTO"}}}},"400":{"description":"Invalid scope value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Another erasure request is already active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — one request per 24 hours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Erasure failed — nothing was erased","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/confirmation-tokens":{"post":{"tags":["Confirmation Tokens"],"summary":"Emitir token de confirmación","description":"Devuelve un token de un solo uso (TTL ~5 min) ligado al usuario, acción y recurso indicados. El frontend debe invocarlo SOLO tras click humano y enviarlo en X-Confirmation-Token cuando ejecute la acción real.","operationId":"issue","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueConfirmationTokenRequest"}}},"required":true},"responses":{"201":{"description":"Token emitido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ConfirmationTokenResponse"}}}},"400":{"description":"Payload inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Auto-confirm no permitido (source=AUTO_PREF)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/clients":{"get":{"tags":["Clientes"],"summary":"Listar clientes","description":"Devuelve una lista paginada de clientes con filtros opcionales","operationId":"getClients","parameters":[{"name":"page","in":"query","description":"Número de página (0-indexed)","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","description":"Tamaño de página","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","description":"Campo de ordenamiento","required":false,"schema":{"type":"string","default":"name"}},{"name":"sortDirection","in":"query","description":"Dirección de ordenamiento","required":false,"schema":{"type":"string","default":"asc"}},{"name":"search","in":"query","description":"Filtro de búsqueda por nombre o CIF/NIF","required":false,"schema":{"type":"string"}},{"name":"startDate","in":"query","description":"Fecha inicio de creación (ISO date, ej: 2026-01-01)","required":false,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","description":"Fecha fin de creación (ISO date, ej: 2026-03-31)","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Lista de clientes obtenida","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageClientDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Clientes"],"summary":"Crear nuevo cliente","description":"Crea un nuevo cliente en el sistema","operationId":"createClient","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateClientRequest"}}},"required":true},"responses":{"201":{"description":"Cliente creado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ClientDto"}}}},"400":{"description":"Datos de cliente inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/checkout/create-session":{"post":{"tags":["Stripe Checkout"],"summary":"Create Stripe Checkout Session","description":"Public endpoint used by the landing page to start a self-service signup. Gated by SIGNUP_STRIPE_ENABLED.","operationId":"createSession","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutSessionRequest"}}},"required":true},"responses":{"200":{"description":"Checkout URL returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/CreateCheckoutSessionResponse"}}}},"400":{"description":"Invalid plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Self-service signup disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Stripe API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/templates":{"get":{"tags":["Invoice Templates"],"summary":"Get all templates for a business","operationId":"getTemplates","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceTemplateDTO"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Invoice Templates"],"summary":"Create new template","operationId":"createTemplate","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceTemplateDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/templates/{templateId}/duplicate":{"post":{"tags":["Invoice Templates"],"summary":"Duplicate existing template","operationId":"duplicateTemplate","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"templateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceTemplateDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/invitations":{"post":{"tags":["Business Invitations"],"summary":"Create an invitation","description":"Invites a gestor by email (owner only).","operationId":"createInvitation","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvitationSummary"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/expense-documents":{"get":{"tags":["Documentos de Gastos"],"summary":"Listar documentos de gastos","description":"Devuelve documentos paginados con filtros opcionales por estado, fecha y búsqueda","operationId":"getDocuments","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","description":"Número de página (0-indexed)","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","description":"Tamaño de página","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"status","in":"query","description":"Filtro por estado (UPLOADING, PROCESSING, PENDING_VALIDATION, VALIDATED, ERROR, EXTRACTION_FAILED)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Buscar por nombre del emisor o descripción","required":false,"schema":{"type":"string"}},{"name":"startDate","in":"query","description":"Fecha inicio (ISO date, ej: 2026-01-01)","required":false,"schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","description":"Fecha fin (ISO date, ej: 2026-03-31)","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Lista de documentos obtenida","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageExpenseDocumentDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Documentos de Gastos"],"summary":"Crear documento desde archivo subido","description":"Crea un nuevo documento de gasto tras subir archivo (solo metadata, sin extracción AI). El documento queda en EXTRACTION_FAILED para introducir los datos manualmente","operationId":"createDocument","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"filename","in":"query","description":"Nombre del archivo","required":true,"schema":{"type":"string"}},{"name":"fileUrl","in":"query","description":"URL del archivo almacenado","required":true,"schema":{"type":"string"}},{"name":"fileType","in":"query","description":"Tipo de archivo (pdf, image)","required":true,"schema":{"type":"string"}},{"name":"fileSize","in":"query","description":"Tamaño del archivo en bytes","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"201":{"description":"Documento creado pendiente de entrada manual de datos","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"400":{"description":"Datos de archivo inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/expense-documents/{documentId}/validate":{"post":{"tags":["Documentos de Gastos"],"summary":"Validar documento","description":"Marca un documento en estado PENDING_VALIDATION como validado por el usuario","operationId":"validateDocument","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","description":"ID del documento","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Documento validado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"400":{"description":"Documento no está en estado de validación pendiente","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Documento no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/expense-documents/{documentId}/retry":{"post":{"tags":["Documentos de Gastos"],"summary":"Reintentar procesamiento AI","description":"Reintenta el procesamiento AI de un documento que falló (estado ERROR o EXTRACTION_FAILED). Incrementa contador de reintentos (máx. 3)","operationId":"retryProcessing","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","description":"ID del documento","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"language","in":"query","description":"Idioma para descripción y categoría sugerida (es, en). Default: es","required":false,"schema":{"type":"string","default":"es"}}],"responses":{"200":{"description":"Reintento iniciado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"400":{"description":"Documento no puede ser reintentado (no está en ERROR/EXTRACTION_FAILED o alcanzó límite de reintentos)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Documento no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/expense-documents/upload":{"post":{"tags":["Documentos de Gastos"],"summary":"Subir archivo de gasto","description":"Sube un archivo de gasto y lo procesa con AI automáticamente. Soporta PDF e imágenes (JPG, PNG). La extracción AI usa LiteLLM multi-model para OCR y extracción de datos.","operationId":"uploadDocument","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"language","in":"query","description":"Idioma para descripción y categoría sugerida (es, en). Default: es","required":false,"schema":{"type":"string","default":"es"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Archivo a procesar (PDF, JPG, PNG)"}},"required":["file"]}}}},"responses":{"200":{"description":"Contenido duplicado - devuelve el documento existente con duplicate=true","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"201":{"description":"Archivo subido y procesamiento AI completado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseDocumentDto"}}}},"400":{"description":"Archivo inválido o no soportado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Subida duplicada concurrente (EXPENSE_DOCUMENT_DUPLICATE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/bot/whatsapp/validate-otp":{"post":{"tags":["WhatsApp Bot"],"summary":"Validate WhatsApp linking OTP","description":"Validates an OTP and links the WhatsApp phone number to the user account.","operationId":"validateOtp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateOtpRequest"}}},"required":true},"responses":{"200":{"description":"OTP valid, phone linked","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No pending linking request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"OTP invalid, expired, or max attempts reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/bot/whatsapp/initiate-linking":{"post":{"tags":["WhatsApp Bot"],"summary":"Initiate WhatsApp linking","description":"Creates an OTP for linking a WhatsApp phone to a Ticke account. Always returns 200 for anti-enumeration.","operationId":"initiateLinking","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiateLinkingRequest"}}},"required":true},"responses":{"200":{"description":"Request processed (always 200)","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/billing/topup-session":{"post":{"tags":["Stripe Billing Portal"],"summary":"Create Stripe Checkout session for an AI credit top-up","description":"Returns a Stripe-hosted Checkout URL (mode=payment) for a one-time AI credit top-up. The amount must be one of the offered packs (10/20/30/50 EUR) and is the NET price: 21% IVA is added at checkout. The buyer is the user's active business, whose fiscal data (tax ID and address) must be complete.","operationId":"createTopupSession","parameters":[{"name":"X-Active-Business-Id","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTopupSessionRequest"}}},"required":true},"responses":{"200":{"description":"Checkout URL returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/CreateTopupSessionResponse"}}}},"400":{"description":"Denomination not offered, or the business fiscal data is incomplete (AI_TOPUP_FISCAL_DATA_INCOMPLETE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Malformed or foreign active-business header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No subscription on file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Stripe API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/billing/portal-session":{"post":{"tags":["Stripe Billing Portal"],"summary":"Create Stripe Billing Portal session","description":"Returns a Stripe-hosted Billing Portal URL for the authenticated user's active business.","operationId":"createPortalSession","parameters":[{"name":"X-Active-Business-Id","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Portal URL returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PortalSessionResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Not an owner/admin of the business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No subscription on file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Stripe API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/auth/reset-password":{"post":{"tags":["Autenticación"],"summary":"Restablecer contraseña","description":"Consume el token recibido por email y fija la nueva contraseña. Invalida el token y las sesiones previas. Rate limit: 10/hora por IP.","operationId":"resetPassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Contraseña actualizada","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Body inválido (contraseña débil / token ausente)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Token caducado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Token inválido o ya usado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Demasiados intentos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/register":{"post":{"tags":["Autenticación"],"summary":"Registro público deshabilitado","description":"El registro público está deshabilitado. Contacte al administrador para obtener acceso.","operationId":"register","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequest"}}},"required":true},"responses":{"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Registro público deshabilitado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/refresh":{"post":{"tags":["Autenticación"],"summary":"Refrescar token","description":"Genera un nuevo token de acceso usando el refresh token","operationId":"refresh","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token refrescado exitosamente","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Body inválido (refreshToken ausente)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Refresh token inválido o expirado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/magic-link/resend":{"post":{"tags":["Magic-link Signup"],"summary":"Resend magic link","description":"Re-issues a magic link for a pending signup email. Rate-limited 3/hour/email.","operationId":"resend","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/magic-link/consume":{"post":{"tags":["Magic-link Signup"],"summary":"Consume magic-link token","description":"Exchanges a single-use magic-link token for JWT credentials. Creates the User+Business pair on first consume.","operationId":"consume","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsumeRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MagicLinkConsumeResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/logout":{"post":{"tags":["Autenticación"],"summary":"Cerrar sesion","description":"Invalida el access token del Bearer y el refresh token del body opcional {refreshToken}","operationId":"logout","parameters":[{"name":"Authorization","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Logout exitoso","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Ni access token ni refresh token validos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/login":{"post":{"tags":["Autenticación"],"summary":"Iniciar sesión","description":"Autentica un usuario y devuelve tokens JWT","operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Login exitoso","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Credenciales inválidas","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Usuario no encontrado (USER_NOT_FOUND)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/forgot-password":{"post":{"tags":["Autenticación"],"summary":"Solicitar restablecimiento de contraseña","description":"Envía un enlace de un solo uso (caduca en 30 min) si el email pertenece a una cuenta activa. Devuelve siempre 200 con el mismo cuerpo. Rate limit: 5/hora por IP+email y 10/hora por email.","operationId":"forgotPassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Solicitud aceptada","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Email inválido","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Demasiadas solicitudes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/auth/create-test-business":{"post":{"tags":["Autenticación"],"summary":"Crear negocio de prueba","description":"DEPRECATED - Requiere SYSTEM_ADMIN","operationId":"createTestBusiness","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"deprecated":true}},"/api/admin/verifactu/reconcile/{invoiceId}":{"post":{"tags":["Admin Verifactu"],"summary":"Reconcile a single Verifactu invoice from the local audit log","description":"Resolves a PENDING_* / ERROR invoice based on the latest invoice_verifactu_integration row. Uses canonical Business → Invoice lock order. Persists an audit row with event_type=RECONCILE_LOCAL_AUDIT and the actor user id.","operationId":"reconcileInvoice","parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Reconcile completed; report included","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReconcileReportDTO"}}}},"400":{"description":"Invoice not in a reconcilable state or no audit log","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Caller is not SYSTEM_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invoice not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/users/create-with-business":{"post":{"tags":["Admin"],"summary":"Crear usuario + negocio completo","description":"Crea usuario, negocio, estados de factura y configuración de email en una transacción. Solo SYSTEM_ADMIN.","operationId":"createUserWithBusiness","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateUserRequest"}}},"required":true},"responses":{"201":{"description":"Usuario creado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AdminUserCreationResponse"}}}},"400":{"description":"Datos inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No autorizado - Requiere SYSTEM_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Email o CIF/NIF ya existe","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/users/bulk-import":{"post":{"tags":["Admin"],"summary":"Importar usuarios en lote","description":"Crea usuarios a partir de una lista de emails y envía emails de acceso beta. Solo SYSTEM_ADMIN.","operationId":"bulkImportUsers","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkImportRequest"}}},"required":true},"responses":{"200":{"description":"Importación procesada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BulkImportResponse"}}}},"400":{"description":"Lista vacía","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No autorizado - Requiere SYSTEM_ADMIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings/verifactu/cache/evict":{"post":{"tags":["System Settings"],"summary":"Evict VeriFactu configuration cache","description":"Manually clears the VeriFactu configuration cache. Useful after direct database changes. Only accessible to SYSTEM_ADMIN.","operationId":"evictVerifactuCache","responses":{"200":{"description":"Cache evicted successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings/seed-template/reset":{"post":{"tags":["System Settings"],"summary":"Reset seed template to default","description":"Resets the seed template to the hardcoded default template from application code. Only accessible to SYSTEM_ADMIN.","operationId":"resetSeedTemplate","responses":{"200":{"description":"Seed template reset successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SystemSettingDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Seed template setting not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/recurring-invoices/run":{"post":{"tags":["Admin"],"summary":"Disparar manualmente el job de facturas recurrentes","description":"Ejecuta una tanda inmediata del job que normalmente corre a las 06:00 Europe/Madrid. Solo SYSTEM_ADMIN.","operationId":"runRecurringInvoicesJob","responses":{"200":{"description":"Tanda ejecutada — devuelve contadores","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BatchSummary"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Job deshabilitado por configuración","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/billing/legacy-notice":{"post":{"tags":["Admin Billing"],"summary":"Queue legacy free→paid notices for the given users","operationId":"sendLegacyNotice","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyNoticeRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/robots.txt":{"get":{"tags":["SEO"],"summary":"robots.txt","description":"Crawler directives for search engines.","operationId":"robotsTxt","responses":{"200":{"description":"OK","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/whatsapp/linking/status":{"get":{"tags":["WhatsApp"],"summary":"Get WhatsApp linking status","description":"Returns the current linking status for the authenticated user. Shows pending OTP if a linking request is active.","operationId":"getStatus","responses":{"200":{"description":"Status retrieved","content":{"*/*":{"schema":{"$ref":"#/components/schemas/WhatsappLinkingStatusResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users":{"get":{"tags":["Usuarios"],"summary":"Listar usuarios","description":"Devuelve una lista paginada de usuarios con filtros opcionales (solo administradores)","operationId":"getUsers","parameters":[{"name":"page","in":"query","description":"Número de página (0-indexed)","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","description":"Tamaño de página","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","description":"Campo de ordenamiento","required":false,"schema":{"type":"string","default":"createdAt"}},{"name":"sortDirection","in":"query","description":"Dirección de ordenamiento","required":false,"schema":{"type":"string","default":"desc"}},{"name":"name","in":"query","description":"Filtro por nombre","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Lista de usuarios obtenida","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageUserDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/templates/seed":{"get":{"tags":["Template Metadata"],"summary":"Get seed template with all available fields","operationId":"getSeedTemplate_1","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/JsonNode"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/templates/fields":{"get":{"tags":["Template Metadata"],"summary":"Get available template fields","operationId":"getAvailableFields","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TemplateFieldsDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/tax/segregation/iva":{"get":{"tags":["Segregacion Fiscal"],"summary":"Resumen trimestral IVA","description":"IVA repercutido y soportado deducible desglosado por tipo","operationId":"getQuarterlyIvaSummary","parameters":[{"name":"year","in":"query","description":"Ano fiscal","required":true,"schema":{"type":"integer","format":"int32","maximum":2099,"minimum":2020}},{"name":"quarter","in":"query","description":"Trimestre (1-4)","required":true,"schema":{"type":"integer","format":"int32","maximum":4,"minimum":1}}],"responses":{"200":{"description":"Resumen IVA obtenido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/QuarterlyIvaSummaryDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/segregation/iva/annual":{"get":{"tags":["Segregacion Fiscal"],"summary":"Resumen anual IVA","description":"Agregacion de los 4 trimestres del ano","operationId":"getAnnualIvaSummary","parameters":[{"name":"year","in":"query","description":"Ano fiscal","required":true,"schema":{"type":"integer","format":"int32","maximum":2099,"minimum":2020}}],"responses":{"200":{"description":"Resumen anual IVA obtenido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AnnualIvaSummaryDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/segregation/irpf":{"get":{"tags":["Segregacion Fiscal"],"summary":"Resumen trimestral IRPF","description":"Ingresos, gastos deducibles y rendimiento neto","operationId":"getQuarterlyIrpfSummary","parameters":[{"name":"year","in":"query","description":"Ano fiscal","required":true,"schema":{"type":"integer","format":"int32","maximum":2099,"minimum":2020}},{"name":"quarter","in":"query","description":"Trimestre (1-4)","required":true,"schema":{"type":"integer","format":"int32","maximum":4,"minimum":1}}],"responses":{"200":{"description":"Resumen IRPF obtenido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/QuarterlyIrpfSummaryDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/segregation/dashboard":{"get":{"tags":["Segregacion Fiscal"],"summary":"Dashboard fiscal rapido","description":"Snapshot del trimestre actual con proximo deadline","operationId":"getFiscalDashboard","responses":{"200":{"description":"Dashboard fiscal obtenido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/FiscalDashboardDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms":{"get":{"tags":["Modelos Fiscales"],"summary":"Listar formularios del ano","description":"Lista todos los formularios fiscales de un ano","operationId":"getFormsByYear","parameters":[{"name":"year","in":"query","description":"Ano fiscal","required":true,"schema":{"type":"integer","format":"int32","maximum":2099,"minimum":2020}}],"responses":{"200":{"description":"Lista de formularios obtenida","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}":{"get":{"tags":["Modelos Fiscales"],"summary":"Detalle del formulario","description":"Obtiene el formulario con todas sus casillas","operationId":"getFormDetail","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Detalle obtenido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TaxFormDetailDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Formulario no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/export":{"get":{"tags":["Modelos Fiscales"],"summary":"Exportar desglose fiscal","description":"Descarga el desglose fiscal trazable en Excel o CSV. PDF no esta soportado para el desglose fiscal.","operationId":"exportBreakdown","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"format","in":"query","description":"Formato de export: EXCEL o CSV","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Archivo exportado","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Formato de export no soportado (p.ej. PDF)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Formulario de otro negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Formulario no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tax/forms/{id}/breakdown":{"get":{"tags":["Modelos Fiscales"],"summary":"Desglose fiscal trazable","description":"Devuelve los importes macro del formulario (p.ej. facturado, IVA repercutido, IVA soportado, retenido, gastos deducibles segun el modelo) con sus casillas y las lineas de documentos origen. snapshotAvailable=false indica un formulario anterior al snapshot (sin desglose recuperable). ?macro= filtra un macro; ?summary=true omite las lineas.","operationId":"getBreakdown","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"macro","in":"query","description":"Filtrar por importe macro","required":false,"schema":{"type":"string","enum":["FACTURADO","IVA_REPERCUTIDO","IVA_SOPORTADO","RETENIDO","GASTOS_DEDUCIBLES"]}},{"name":"summary","in":"query","description":"Devolver solo totales, sin lineas","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Desglose obtenido","content":{"*/*":{"schema":{"$ref":"#/components/schemas/FiscalBreakdownDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Formulario de otro negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Formulario no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/recurring-invoices/{id}/generated-invoices":{"get":{"tags":["Facturas Recurrentes"],"summary":"Listar facturas generadas por esta plantilla","description":"AC-8 — historial de facturas creadas por el job de recurrencia.","operationId":"getGeneratedInvoices","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"Lista paginada de facturas","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageInvoiceSummaryDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/performance/recommendations":{"get":{"tags":["performance-controller"],"summary":"Get performance recommendations","description":"Returns heuristic tuning recommendations.","operationId":"getPerformanceRecommendations","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/performance/query-metrics":{"get":{"tags":["performance-controller"],"summary":"Get query metrics","description":"Returns database pool and query performance metrics.","operationId":"getQueryMetrics","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/performance/cache-stats":{"get":{"tags":["performance-controller"],"summary":"Get cache statistics","description":"Returns names and basic stats of application caches.","operationId":"getCacheStats","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/notifications/{notificationId}":{"get":{"tags":["Notifications"],"summary":"Get notification by ID","description":"Returns a specific notification by its ID","operationId":"getNotificationById","parameters":[{"name":"notificationId","in":"path","description":"Notification ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Notification retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/NotificationDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No access to this notification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Notification not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Notifications"],"summary":"Delete notification","description":"Permanently deletes a notification. Only the owner can delete it.","operationId":"deleteNotification","parameters":[{"name":"notificationId","in":"path","description":"Notification ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Notification deleted"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Notification not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/notifications/unread-count":{"get":{"tags":["Notifications"],"summary":"Get unread notification count","description":"Returns the count of unread notifications for displaying in the notification badge","operationId":"getUnreadCount","responses":{"200":{"description":"Count retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UnreadCountResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/me/subscription":{"get":{"tags":["My Subscription"],"summary":"Get my subscription summary","operationId":"getMySubscription","parameters":[{"name":"X-Active-Business-Id","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MySubscriptionResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/invoices/{id}/verifactu-status":{"get":{"tags":["Facturas"],"summary":"Consultar estado en VeriFactu","description":"Consulta el estado actual de una factura en el sistema de VeriFactu","operationId":"getVerifactuStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Estado consultado exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/VerifactuInfoDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada o no registrada en VeriFactu","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/signed-url":{"get":{"tags":["Facturas"],"summary":"Obtener URL pre-firmada del PDF","description":"Devuelve una URL pre-firmada de S3 que permite acceso temporal (15 minutos) al PDF de la factura","operationId":"getSignedUrl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"URL pre-firmada generada exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SignedUrlResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada o sin PDF","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/rectification-chain":{"get":{"tags":["Facturas"],"summary":"Obtener cadena de rectificación","description":"Devuelve la cadena ordenada [original → rectificativa → ...] de la factura indicada.","operationId":"getRectificationChain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Cadena de rectificación","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/preview-pdf":{"get":{"tags":["Facturas"],"summary":"Previsualizar el PDF borrador de una factura","description":"Renderiza el PDF borrador (sin QR ni leyenda) en el momento, vía ticke-headless. No persiste en S3 y no requiere que la factura esté registrada.","operationId":"previewPdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"PDF borrador","content":{"application/pdf":{}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Servicio de renderizado no disponible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Renderizado backend deshabilitado (ticke.headless.enabled=false)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/pdf":{"get":{"tags":["Facturas"],"summary":"Obtener PDF para descarga","description":"Devuelve el PDF almacenado de una factura como base64 para descarga en el cliente","operationId":"getPdfForDownload","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"PDF obtenido exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PdfDownloadResponse"}}}},"400":{"description":"Factura en estado borrador (no tiene PDF almacenado)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura o PDF no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/has-final-pdf":{"get":{"tags":["Facturas"],"summary":"Verificar existencia de PDF final","description":"Verifica si una factura tiene un PDF final (con QR de VeriFactu) almacenado. Útil para determinar si se necesita recuperación del PDF.","operationId":"hasFinalPdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Verificación completada","content":{"*/*":{"schema":{"$ref":"#/components/schemas/HasFinalPdfResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/final-pdf":{"get":{"tags":["Facturas"],"summary":"Descargar PDF final de factura","description":"Descarga el PDF final (con código QR de VeriFactu) de una factura registrada. Este es el PDF oficial que debe enviarse al cliente.","operationId":"downloadFinalPdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"PDF final descargado exitosamente","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada o sin PDF final","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/draft-pdf":{"get":{"tags":["Facturas"],"summary":"Descargar PDF borrador de factura","description":"Descarga el PDF borrador (sin código QR) de una factura registrada. Este PDF es para fines de auditoría y compliance.","operationId":"downloadDraftPdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"PDF borrador descargado exitosamente","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Factura no encontrada o sin PDF borrador","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/{id}/download-pdf/{fileId}":{"get":{"tags":["Facturas"],"summary":"Download invoice PDF","description":"Downloads a stored invoice PDF file.","operationId":"downloadPdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/upcoming-due":{"get":{"tags":["Facturas"],"summary":"Facturas próximas a vencer","description":"Obtiene facturas que vencen en los próximos días","operationId":"getUpcomingDueInvoices","parameters":[{"name":"daysUntilDue","in":"query","description":"Días hasta vencimiento","required":false,"schema":{"type":"integer","format":"int32","default":7},"example":7},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"Facturas próximas a vencer obtenidas","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PagedResponseInvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/stats":{"get":{"tags":["Facturas"],"summary":"Get invoice stats","description":"Returns totals and counts grouped by status for dashboards.","operationId":"getInvoiceStats","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceStatsDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/sequence-gaps":{"get":{"tags":["Facturas"],"summary":"Detectar huecos en secuencia de facturas","description":"Detecta huecos en la numeración de facturas para auditoría VeriFactu. Los huecos pueden indicar facturas eliminadas o faltantes, lo cual no está permitido según la normativa.","operationId":"detectSequenceGaps","parameters":[{"name":"year","in":"query","description":"Año a auditar (por defecto el año actual)","required":false,"schema":{"type":"integer","format":"int32"},"example":2025}],"responses":{"200":{"description":"Lista de números de factura faltantes","content":{"*/*":{"schema":{"type":"array","items":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/pending":{"get":{"tags":["Facturas"],"summary":"List pending invoices","description":"Returns unpaid and overdue invoices for collection follow-up.","operationId":"getPendingInvoices","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"dueDate"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"asc"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PagedResponseInvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invoices/by-client/{clientId}":{"get":{"tags":["Facturas"],"summary":"Facturas por cliente","description":"Obtiene todas las facturas de un cliente específico","operationId":"getInvoicesByClient","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"createdAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"desc"}}],"responses":{"200":{"description":"Facturas del cliente obtenidas","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PagedResponseInvoiceDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/invitations/{token}":{"get":{"tags":["Invitations"],"summary":"Preview an invitation","description":"Reads an invitation by its single-use token WITHOUT consuming it, so the accept page can show the business name and branch on whether the invitee needs to create a password (new account) or just confirm (existing account). Public — the token is the auth.","operationId":"preview","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/internal/billing-lock/{businessId}":{"get":{"tags":["Billing Lock Internal"],"summary":"Billing lock verdict for a business","description":"Returns {lockState: ok|grace|locked, graceEndsAt: ISO-8601 UTC|null}. Real business without a covering subscription → ok.","operationId":"getLock","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Verdict returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BillingLockResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid internal secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown business id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/internal/ai-quota/{businessId}":{"get":{"tags":["Agent AI Quota Internal"],"summary":"Whether a business may run another AI turn","description":"Same decision as the OCR quota gate: honours enforcement flag, AI_QUOTA_EXEMPT_EMAILS, monthly cap and prepaid balance of the business OWNER.","operationId":"getQuota","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Verdict returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AiQuotaStatusResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid internal secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/internal/agent-model-config":{"get":{"tags":["Agent Model Config Internal"],"summary":"Get the active tier→alias mapping for the agent","description":"Returns the complex/simple/ocr alias mapping so the agent can hot-swap models.","operationId":"getModelConfig","responses":{"200":{"description":"Mapping retrieved","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AiModelTiers"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid internal secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/gdpr/export/{exportId}":{"get":{"tags":["GDPR"],"summary":"Get export request status","description":"Returns the current status of a data export request. Only the requesting user can see their own exports. When status = READY, use the downloadUrl to fetch the file.","operationId":"getExportStatus","parameters":[{"name":"exportId","in":"path","description":"UUID of the export request","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Export request found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GdprExportRequestDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Export request not found or does not belong to user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/gdpr/export/{exportId}/download":{"get":{"tags":["GDPR"],"summary":"Download exported data","description":"Downloads the JSON export file. Only available when status = READY and the link has not expired (24 h window). Returns application/json as a downloadable attachment.","operationId":"downloadExport","parameters":[{"name":"exportId","in":"path","description":"UUID of the export request","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Export file returned as attachment","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"Export is not ready for download","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Export request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Export download has expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/gdpr/export/current":{"get":{"tags":["GDPR"],"summary":"Get current usable export","description":"Returns the newest PENDING/PROCESSING request, or the newest READY one whose download has not expired — so a client without a stored export id (fresh browser, locked user) recovers it. 404 when there is none.","operationId":"getCurrentExport","responses":{"200":{"description":"Usable export found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GdprExportRequestDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No usable export","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/gdpr/erasure/{requestId}":{"get":{"tags":["GDPR"],"summary":"Get erasure request status","description":"Returns the current status and result of an erasure request. Only the requesting user can see their own requests.","operationId":"getErasureStatus","parameters":[{"name":"requestId","in":"path","description":"UUID of the erasure request","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Erasure request found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/GdprDeletionRequestDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Erasure request not found or does not belong to user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/fiscal/deadlines":{"get":{"tags":["Fiscal Calendar"],"summary":"Próximos plazos fiscales","description":"Devuelve los próximos vencimientos ordenados por proximidad.","operationId":"getUpcomingDeadlines","parameters":[{"name":"limit","in":"query","description":"Nº máximo de plazos (0 = sin límite)","required":false,"schema":{"type":"integer","format":"int32","default":4},"example":4}],"responses":{"200":{"description":"Lista de plazos obtenida","content":{"*/*":{"schema":{"$ref":"#/components/schemas/FiscalCalendarResponseDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/dashboard/summary":{"get":{"tags":["Dashboard"],"summary":"Obtener resumen ejecutivo","description":"Devuelve un resumen ejecutivo con las métricas más importantes","operationId":"getExecutiveSummary","responses":{"200":{"description":"Resumen ejecutivo obtenido exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExecutiveSummaryDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/dashboard/recent-activity":{"get":{"tags":["Dashboard"],"summary":"Obtener actividad reciente","description":"Devuelve las últimas actividades realizadas en el sistema","operationId":"getRecentActivity","parameters":[{"name":"limit","in":"query","description":"Límite de actividades a devolver","required":false,"schema":{"type":"integer","format":"int32","default":20},"example":20}],"responses":{"200":{"description":"Actividad reciente obtenida exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/RecentActivityDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/dashboard/metrics":{"get":{"tags":["Dashboard"],"summary":"Obtener métricas del dashboard","description":"Devuelve KPIs generales, estadísticas financieras y datos de tendencias","operationId":"getDashboardMetrics","responses":{"200":{"description":"Métricas obtenidas exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/DashboardMetricsDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/dashboard/expense-metrics":{"get":{"tags":["Dashboard"],"summary":"Obtener métricas de gastos","description":"Devuelve métricas detalladas de gastos: totales mensuales, desglose por categoría, tendencia y top proveedores","operationId":"getExpenseMetrics","responses":{"200":{"description":"Métricas de gastos obtenidas exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExpenseMetricsDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/dashboard/anomalies":{"get":{"tags":["Dashboard"],"summary":"Detectar anomalías del negocio","description":"Informe consolidado: facturas vencidas, borradores estancados (>N días) y gastos sin validar. Parámetros opcionales permiten desactivar tipos.","operationId":"getAnomalies","parameters":[{"name":"checkOverdueInvoices","in":"query","description":"Incluir facturas vencidas sin cobrar","required":false,"schema":{"type":"boolean","default":true}},{"name":"checkStaleDrafts","in":"query","description":"Incluir borradores estancados","required":false,"schema":{"type":"boolean","default":true}},{"name":"checkUnvalidatedExpenses","in":"query","description":"Incluir gastos pendientes de validación","required":false,"schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"Informe de anomalías generado","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AnomalyReportDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/dashboard/analytics":{"get":{"tags":["Dashboard"],"summary":"Obtener datos analíticos (DEPRECATED)","description":"Este endpoint está deprecado. Use /metrics en su lugar, que incluye trendData","operationId":"getAnalyticsData","parameters":[{"name":"periodMonths","in":"query","description":"Período de análisis en meses","required":false,"schema":{"type":"integer","format":"int32","default":8},"example":12}],"responses":{"200":{"description":"Datos analíticos obtenidos exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TrendDataDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"deprecated":true,"security":[{"bearerAuth":[]}]}},"/api/dashboard/alerts":{"get":{"tags":["Dashboard"],"summary":"Obtener alertas del dashboard","description":"Devuelve alertas importantes como facturas vencidas, pagos pendientes, etc.","operationId":"getDashboardAlerts","responses":{"200":{"description":"Alertas obtenidas exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/DashboardAlertsDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/clients/search":{"get":{"tags":["Clientes"],"summary":"Buscar clientes","description":"Busca por nombre o CIF/NIF","operationId":"searchClients","parameters":[{"name":"query","in":"query","description":"Término de búsqueda","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resultados de búsqueda obtenidos","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/clients/list":{"get":{"tags":["Clientes"],"summary":"Listar todos los clientes","description":"Devuelve una lista simple de todos los clientes para uso en selects","operationId":"getAllClients","responses":{"200":{"description":"Lista de clientes obtenida","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/templates/default":{"get":{"tags":["Invoice Templates"],"summary":"Get default template for a business","operationId":"getDefaultTemplate","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InvoiceTemplateDTO"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/members":{"get":{"tags":["Business Invitations"],"summary":"List members + pending invitations","description":"Owner only.","operationId":"listMembers","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MembersResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/invoice-numbering/preview":{"get":{"tags":["Invoice Numbering"],"summary":"Preview next invoice number","description":"Shows what the next invoice number will be without reserving it. Useful for displaying to users before they create an invoice.","operationId":"previewNextNumber","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Preview generated successfully","content":{"*/*":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied to this business","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/expense-documents/{documentId}/signed-url":{"get":{"tags":["Documentos de Gastos"],"summary":"Obtener URL pre-firmada del documento","description":"Devuelve una URL pre-firmada de S3 que permite acceso temporal (15 minutos) al archivo del documento","operationId":"getSignedUrl_1","parameters":[{"name":"businessId","in":"path","description":"ID del negocio","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"documentId","in":"path","description":"ID del documento","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"URL pre-firmada generada exitosamente","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SignedUrlResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Acceso denegado al negocio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Documento no encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/expense-categories-full":{"get":{"tags":["Business"],"summary":"Get expense categories with full details","description":"Get expense categories with UUIDs for document assignment","operationId":"getExpenseCategoriesFull","parameters":[{"name":"businessId","in":"path","description":"Business ID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Categories retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseCategoryDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Business not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/agent/knowledge-summary":{"get":{"tags":["Agent Knowledge"],"summary":"Get agent's working memory for the business","description":"Returns the structured working memory that Zero has built from conversations. Reads directly from the Mastra storage — no LLM call needed.","operationId":"getKnowledgeSummary","responses":{"200":{"description":"Knowledge summary retrieved","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/agent/consent/status":{"get":{"tags":["Agent Consent"],"summary":"Check if consent has been given","description":"Returns whether the business has formally given consent to AI agent memory.","operationId":"getConsentStatus","responses":{"200":{"description":"Consent status retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/admin/users":{"get":{"tags":["Admin"],"summary":"Listar usuarios","description":"Obtiene listado paginado de todos los usuarios del sistema. Solo SYSTEM_ADMIN.","operationId":"listAllUsers","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"createdAt"}},{"name":"sortDirection","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"Lista de usuarios","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PagedResponseAdminUserListDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"No autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/stats":{"get":{"tags":["Admin"],"summary":"Estadísticas del sistema","description":"Obtiene métricas generales del sistema. Solo SYSTEM_ADMIN.","operationId":"getSystemStats","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings":{"get":{"tags":["System Settings"],"summary":"List all system settings","description":"Retrieves all system configuration settings. Only accessible to SYSTEM_ADMIN.","operationId":"getAllSettings","responses":{"200":{"description":"Settings retrieved successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SystemSettingDTO"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/settings/verifactu":{"get":{"tags":["System Settings"],"summary":"Get VeriFactu configuration","description":"Retrieves the current VeriFactu provider configuration including enabled status. Only accessible to SYSTEM_ADMIN.","operationId":"getVerifactuConfig","responses":{"200":{"description":"VeriFactu configuration retrieved successfully","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Requires SYSTEM_ADMIN role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"Bearer Authentication":[]}]}},"/api/admin/billing/subscriptions":{"get":{"tags":["Admin Billing"],"summary":"List subscriptions (paginated)","operationId":"listSubscriptions","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageAdminSubscriptionListItemDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/admin/billing/subscriptions/{id}":{"get":{"tags":["Admin Billing"],"summary":"Get subscription detail","operationId":"getSubscriptionDetail","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AdminSubscriptionDetailDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/admin/billing/subscriptions/{id}/webhook-logs":{"get":{"tags":["Admin Billing"],"summary":"List webhook events filtered by subscription","operationId":"getWebhookLogs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookLogDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/admin/billing/reconciliation":{"get":{"tags":["Admin Billing"],"summary":"Cross-reference Stripe charges against Verifactu invoices (online)","operationId":"reconciliation","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"startingAfter","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReconciliationRowDto"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/whatsapp/linking":{"delete":{"tags":["WhatsApp"],"summary":"Unlink WhatsApp","description":"Removes the WhatsApp phone number linked to the authenticated user.","operationId":"unlink","responses":{"204":{"description":"WhatsApp unlinked"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/performance/cache/{cacheName}":{"delete":{"tags":["performance-controller"],"summary":"Clear one cache","description":"Evicts a single named application cache.","operationId":"clearCache","parameters":[{"name":"cacheName","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/performance/cache/clear":{"delete":{"tags":["performance-controller"],"summary":"Clear all caches","description":"Evicts every application cache. Use with caution in production.","operationId":"clearAllCaches","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/businesses/{businessId}/members/{userId}":{"delete":{"tags":["Business Invitations"],"summary":"Revoke a member","description":"Removes a user from the business (owner only).","operationId":"revokeMember","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/businesses/{businessId}/invitations/{invitationId}":{"delete":{"tags":["Business Invitations"],"summary":"Revoke a pending invitation","description":"Marks the invitation REVOKED (owner only).","operationId":"revokeInvitation","parameters":[{"name":"businessId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"invitationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/api/agent/knowledge-summary/instructions/{index}":{"delete":{"tags":["Agent Knowledge"],"summary":"Delete a user instruction from working memory","description":"Removes a specific user instruction by index from the agent's working memory.","operationId":"deleteUserInstruction","parameters":[{"name":"index","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Instruction deleted"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded. Retry after the seconds in Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}}},"components":{"schemas":{"UpdateUserRequest":{"type":"object","properties":{"email":{"type":"string"},"fullName":{"type":"string","maxLength":100,"minLength":2},"preferredLanguage":{"type":"string","maxLength":5,"minLength":2}}},"BusinessMembershipDto":{"type":"object","description":"A business membership: business id, name and the user's role","properties":{"id":{"type":"string","format":"uuid","description":"Business unique identifier"},"name":{"type":"string","description":"Business name"},"role":{"type":"string","description":"User's role in this business","enum":["OWNER","ADMIN","ACCOUNTANT","VIEWER"]}}},"UserDto":{"type":"object","description":"User information","properties":{"id":{"type":"string","format":"uuid","description":"User unique identifier","example":"123e4567-e89b-12d3-a456-426614174000"},"email":{"type":"string","description":"User email address","example":"user@example.com"},"fullName":{"type":"string","description":"User full name","example":"John Doe"},"isActive":{"type":"boolean","description":"Whether the user is active","example":true},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp","example":"2024-01-15T10:30:00"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp","example":"2024-01-15T10:30:00"},"preferredLanguage":{"type":"string","description":"User's preferred language code","enum":["es","en"],"example":"es"},"trialMode":{"type":"boolean","description":"Whether the user is currently in trial mode","example":true},"trialInvoicesCreated":{"type":"integer","format":"int32","description":"Number of invoices created during trial (cap = 5)","example":3},"businesses":{"type":"array","description":"Businesses the user belongs to, with their role in each","items":{"$ref":"#/components/schemas/BusinessMembershipDto"}}}},"ChangePasswordRequest":{"type":"object","description":"Request to change user password","properties":{"currentPassword":{"type":"string","description":"Current password"},"newPassword":{"type":"string","description":"New password","maxLength":100,"minLength":8,"pattern":"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).*$"},"confirmPassword":{"type":"string","description":"New password confirmation"}},"required":["confirmPassword","currentPassword","newPassword"]},"SetActiveBusinessRequest":{"type":"object","properties":{"businessId":{"type":"string","format":"uuid"}},"required":["businessId"]},"ApplyLineClaveRequest":{"type":"object","properties":{"nifIva":{"type":"string","maxLength":20,"minLength":0},"claveOriginal":{"type":"string","pattern":"E|A|S"},"nuevaClave":{"type":"string","pattern":"E|A|S"},"motivo":{"type":"string","maxLength":500,"minLength":0}},"required":["claveOriginal","nifIva","nuevaClave"]},"TaxFormDetailDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"taxPeriodId":{"type":"string","format":"uuid"},"year":{"type":"integer","format":"int32"},"quarter":{"type":"integer","format":"int32"},"formType":{"type":"string"},"status":{"type":"string"},"calculatedData":{"type":"object","additionalProperties":{}},"manualAdjustments":{"type":"object","additionalProperties":{}},"finalData":{"type":"object","additionalProperties":{}},"resultAmount":{"type":"number"},"dataAsOf":{"type":"string","format":"date","description":"Fecha del snapshot de datos usado para generar/regenerar este modelo (zona Europe/Madrid). Null para modelos creados antes de TICA-90.","example":"2026-04-01"},"filedAt":{"type":"string","format":"date-time"},"lockedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApplyAdjustmentRequest":{"type":"object","properties":{"casilla":{"type":"string","maxLength":20,"minLength":0},"valor":{"type":"number"},"motivo":{"type":"string","maxLength":500,"minLength":0}},"required":["casilla","valor"]},"CreateRecurringScheduleLineRequest":{"type":"object","properties":{"description":{"type":"string","maxLength":500,"minLength":0},"quantity":{"type":"number","minimum":0.01},"unitPrice":{"type":"number","minimum":0},"taxRate":{"type":"number","maximum":100,"minimum":0},"irpfRate":{"type":"number","maximum":100,"minimum":0},"discount":{"type":"number","maximum":100,"minimum":0}},"required":["description","quantity","unitPrice"]},"UpdateRecurringInvoiceScheduleRequest":{"type":"object","properties":{"templateId":{"type":"string","format":"uuid"},"name":{"type":"string","maxLength":255,"minLength":0},"frequency":{"type":"string","enum":["MONTHLY","QUARTERLY","YEARLY"]},"dayOfMonth":{"type":"integer","format":"int32","maximum":28,"minimum":1},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"notesTemplate":{"type":"string","maxLength":1000,"minLength":0},"sendEmailOnRegister":{"type":"boolean"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/CreateRecurringScheduleLineRequest"}}},"required":["dayOfMonth","frequency","lines","name","startDate"]},"RecurringInvoiceScheduleDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"businessId":{"type":"string","format":"uuid"},"clientId":{"type":"string","format":"uuid"},"clientName":{"type":"string"},"templateId":{"type":"string","format":"uuid"},"name":{"type":"string"},"frequency":{"type":"string","enum":["MONTHLY","QUARTERLY","YEARLY"]},"dayOfMonth":{"type":"integer","format":"int32"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"status":{"type":"string","enum":["ACTIVE","PAUSED"]},"nextRunAt":{"type":"string","format":"date-time"},"lastRunAt":{"type":"string","format":"date-time"},"lastError":{"type":"string"},"errorCount":{"type":"integer","format":"int32"},"notesTemplate":{"type":"string"},"sendEmailOnRegister":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/RecurringInvoiceScheduleLineDto"}}}},"RecurringInvoiceScheduleLineDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"description":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"taxRate":{"type":"number"},"irpfRate":{"type":"number"},"discount":{"type":"number"},"lineOrder":{"type":"integer","format":"int32"}}},"SaveProductRequest":{"type":"object","description":"Product or service details; prices are EUR before VAT","properties":{"name":{"type":"string","maxLength":255,"minLength":0},"description":{"type":"string","description":"Optional plain-text description","maxLength":5000,"minLength":0},"unitPrice":{"type":"number","description":"Unit price in EUR before VAT","example":75.5,"maximum":99999999.99,"minimum":0},"isService":{"type":"boolean"},"unit":{"type":"string","default":"ud","maxLength":50,"minLength":0},"taxRate":{"type":"number","default":"21.00","description":"VAT percentage (0, 4, 10 or 21, as Verifactu accepts); any value is stored as 0.00 when isTaxExempt is true","maximum":100,"minimum":0},"isTaxExempt":{"type":"boolean","default":"false","description":"VAT does not apply when true"}},"required":["isService","isTaxExempt","name","taxRate","unit","unitPrice"]},"ProductDto":{"type":"object","description":"Business catalog product or service","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"unitPrice":{"type":"number","description":"Unit price in EUR before VAT"},"isService":{"type":"boolean"},"unit":{"type":"string"},"taxRate":{"type":"number"},"isTaxExempt":{"type":"boolean"},"currency":{"type":"string","enum":["EUR"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"NotificationPreferenceDTO":{"type":"object","description":"Preferencia de notificación para una combinación (kind, channel)","properties":{"kind":{"type":"string","description":"Tipo de notificación","enum":["FISCAL_DEADLINE","INVOICE_OVERDUE","ANOMALY","WEEKLY_SUMMARY"],"example":"FISCAL_DEADLINE"},"channel":{"type":"string","description":"Canal de entrega","enum":["WEB_APP","AGENT_WHATSAPP"],"example":"WEB_APP"},"enabled":{"type":"boolean","description":"Si el usuario acepta recibir este tipo de notificación por este canal","example":true}},"required":["channel","enabled","kind"]},"NotificationPreferencesUpdateRequest":{"type":"object","description":"Payload para actualizar preferencias de notificación","properties":{"preferences":{"type":"array","description":"Preferencias a actualizar. Se hace upsert de cada fila.","items":{"$ref":"#/components/schemas/NotificationPreferenceDTO"}},"preferredHour":{"type":"integer","format":"int32","description":"Hora preferida de envío (0-23)","example":9,"maximum":23,"minimum":0},"timezone":{"type":"string","description":"Zona horaria IANA","example":"Europe/Madrid"}},"required":["preferences","preferredHour","timezone"]},"NotificationPreferencesResponse":{"type":"object","description":"Estado completo de preferencias de notificación del usuario","properties":{"preferences":{"type":"array","description":"Lista de preferencias (6 filas: 3 kinds × 2 channels)","items":{"$ref":"#/components/schemas/NotificationPreferenceDTO"}},"preferredHour":{"type":"integer","format":"int32","description":"Hora preferida de envío (0-23), aplicada a todas las filas","example":9},"timezone":{"type":"string","description":"Zona horaria IANA del usuario","example":"Europe/Madrid"},"whatsappLinked":{"type":"boolean","description":"Si el usuario tiene un número de WhatsApp vinculado","example":false}}},"AgentActionPreferenceUpdateRequest":{"type":"object","description":"Update Zero agent auto-confirm preference for one action","properties":{"action":{"type":"string","description":"Acción auto-confirmable a configurar","enum":["DELETE_CLIENT","REGISTER_INVOICE","RECTIFY_INVOICE","CANCEL_INVOICE"],"example":"REGISTER_INVOICE"},"autoConfirm":{"type":"boolean","description":"true para permitir auto-confirm, false para exigir tarjeta humana"}},"required":["action","autoConfirm"]},"ActionPreference":{"type":"object","properties":{"action":{"type":"string","enum":["DELETE_CLIENT","REGISTER_INVOICE","RECTIFY_INVOICE","CANCEL_INVOICE"]},"autoConfirm":{"type":"boolean"}}},"AgentActionPreferencesResponse":{"type":"object","properties":{"systemDisabled":{"type":"boolean"},"actions":{"type":"array","items":{"$ref":"#/components/schemas/ActionPreference"}}}},"UpdateInvoiceLineRequest":{"type":"object","properties":{"description":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"taxRate":{"type":"number"},"irpfRate":{"type":"number","maximum":100,"minimum":0},"discount":{"type":"number","maximum":100,"minimum":0}}},"InvoiceLineDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"description":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"taxRate":{"type":"number"},"irpfRate":{"type":"number"},"discount":{"type":"number"},"lineSubtotal":{"type":"number"},"discountAmount":{"type":"number"},"taxAmount":{"type":"number"},"irpfAmount":{"type":"number"},"totalWithTax":{"type":"number"}}},"UpdateInvoiceRequest":{"type":"object","properties":{"clientId":{"type":"string","format":"uuid"},"issueDate":{"type":"string","format":"date"},"dueDate":{"type":"string","format":"date"},"notes":{"type":"string","maxLength":1000,"minLength":0},"templateId":{"type":"string","format":"uuid"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/UpdateInvoiceLineRequest"}}}},"AddressDto":{"type":"object","description":"Address information","properties":{"id":{"type":"string","format":"uuid","description":"Address unique identifier"},"addressLine1":{"type":"string","description":"Address line 1","example":123},"addressLine2":{"type":"string","description":"Address line 2","example":"Apt 4B"},"city":{"type":"string","description":"City","example":"Madrid"},"province":{"type":"string","description":"Province","example":"Madrid"},"postalCode":{"type":"string","description":"Postal code","example":28001},"country":{"type":"string","description":"Country","example":"Spain"}}},"ClientSummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"cifNif":{"type":"string"},"email":{"type":"string"},"defaultTaxRate":{"type":"number"},"isTaxExempt":{"type":"boolean"},"address":{"$ref":"#/components/schemas/AddressDto"},"notes":{"type":"string"}}},"InvoiceDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"invoiceNumber":{"type":"string"},"draftIdentifier":{"type":"string"},"issueDate":{"type":"string","format":"date"},"dueDate":{"type":"string","format":"date"},"subtotal":{"type":"number"},"discountAmount":{"type":"number"},"taxAmount":{"type":"number"},"irpfAmount":{"type":"number"},"totalAmount":{"type":"number"},"notes":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"client":{"$ref":"#/components/schemas/ClientSummaryDto"},"status":{"$ref":"#/components/schemas/InvoiceStatusDto"},"template":{"$ref":"#/components/schemas/InvoiceTemplateSummaryDto"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceLineDto"}},"verifactuInfo":{"$ref":"#/components/schemas/VerifactuInfoDto"},"convertedToInvoiceId":{"type":"string","format":"uuid"},"isPaid":{"type":"boolean"},"isDraft":{"type":"boolean"},"isRegistered":{"type":"boolean"},"isError":{"type":"boolean"},"isCancelled":{"type":"boolean"},"isVoid":{"type":"boolean"},"isUnpaid":{"type":"boolean"},"isOverdue":{"type":"boolean"},"hasDraftPdf":{"type":"boolean"},"hasFinalPdf":{"type":"boolean"},"rectifiesInvoiceId":{"type":"string","format":"uuid"},"rectifiesInvoiceNumber":{"type":"string"},"rectificationCode":{"type":"string"},"rectificationReason":{"type":"string"},"rectifiedByInvoiceId":{"type":"string","format":"uuid"},"rectifiedByInvoiceNumber":{"type":"string"},"aeatCancellationCsv":{"type":"string"},"cancelledAt":{"type":"string","format":"date-time"},"quarterAlreadyDeclared":{"type":"boolean"},"emailSentAt":{"type":"string","format":"date-time"},"sendEmailOnRegister":{"type":"boolean"}}},"InvoiceStatusDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"isDraft":{"type":"boolean"},"isRegistered":{"type":"boolean"},"isError":{"type":"boolean"},"isPaid":{"type":"boolean"},"isCancelled":{"type":"boolean"},"isVoid":{"type":"boolean"},"isUnpaid":{"type":"boolean"},"isOverdue":{"type":"boolean"}}},"InvoiceTemplateSummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"isDefault":{"type":"boolean"}}},"VerifactuInfoDto":{"type":"object","properties":{"status":{"type":"string"},"registeredAt":{"type":"string","format":"date-time"},"csv":{"type":"string"},"validationUrl":{"type":"string"},"errorType":{"type":"string"},"errorMessage":{"type":"string"},"verifactuMode":{"type":"string","description":"Régimen fiscal de emisión: VERIFACTU, PRE_VERIFACTU, SIF","enum":["VERIFACTU","PRE_VERIFACTU","SIF"]},"verifactuEnvironment":{"type":"string","description":"Entorno AEAT: PROD o PREPROD","enum":["PROD","PREPROD"]}}},"UpdatePaymentStatusRequest":{"type":"object","properties":{"paid":{"type":"boolean"},"paymentDate":{"type":"string","format":"date"},"paymentReference":{"type":"string"},"notes":{"type":"string"}},"required":["paid"]},"Address":{"type":"object","properties":{"addressLine1":{"type":"string","maxLength":255,"minLength":0},"addressLine2":{"type":"string","maxLength":255,"minLength":0},"city":{"type":"string","maxLength":100,"minLength":0},"province":{"type":"string","maxLength":100,"minLength":0},"postalCode":{"type":"string","maxLength":10,"minLength":0},"country":{"type":"string","maxLength":2,"minLength":0}}},"UpdateClientRequest":{"type":"object","description":"Request to update an existing client","properties":{"name":{"type":"string","description":"Client name","example":"ACME Corp Updated","maxLength":255,"minLength":2},"cifNif":{"type":"string","description":"Tax identification number (CIF/NIF)","example":"B12345678","maxLength":20,"minLength":0},"taxIdType":{"type":"string","description":"Type of tax identification document. Values: NIF, CIF, NIE, VAT, PASSPORT, OTHER. Null means auto-detect from cifNif format.","example":"NIF"},"email":{"type":"string","description":"Client email","example":"contact@acmecorp.com","maxLength":255,"minLength":0},"phone":{"type":"string","description":"Client phone","example":"+34 612 345 678","maxLength":20,"minLength":0},"address":{"$ref":"#/components/schemas/Address","description":"Client address"},"defaultTaxRate":{"type":"number","description":"Default tax rate for this client","example":21},"isTaxExempt":{"type":"boolean","description":"Whether this client is tax exempt","example":false},"taxExemptionCode":{"type":"string","description":"VAT exemption reason code (E1-E6), required when client is tax exempt","enum":["ARTICLE_20","ARTICLE_21","ARTICLE_22","ARTICLE_23_24","ARTICLE_25","OTHER"],"example":"ARTICLE_20"},"notes":{"type":"string","description":"Optional notes about the client. Can be included in invoice templates.","example":"Pago a 30 días. Descuento del 5% en pedidos superiores a 1000€.","maxLength":500,"minLength":0}}},"ClientDto":{"type":"object","description":"Client information","properties":{"id":{"type":"string","format":"uuid","description":"Client unique identifier"},"name":{"type":"string","description":"Client name","example":"ACME Corp"},"email":{"type":"string","description":"Client email","example":"contact@acmecorp.com"},"phone":{"type":"string","description":"Client phone","example":"+34 612 345 678"},"taxId":{"type":"string","description":"Tax identification number","example":"B12345678"},"address":{"$ref":"#/components/schemas/AddressDto","description":"Client address"},"defaultTaxRate":{"type":"number","description":"Default tax rate for this client (%)","example":21},"isTaxExempt":{"type":"boolean","description":"Whether this client is tax exempt","example":false},"taxExemptionCode":{"type":"string","description":"VAT exemption reason code (E1-E6)"},"status":{"type":"string","description":"Client status (active/inactive)","example":"active"},"invoiceCount":{"type":"integer","format":"int32","description":"Total number of invoices","example":15},"totalAmount":{"type":"number","description":"Total amount invoiced","example":25000.5},"pendingAmount":{"type":"number","description":"Amount pending collection: sum of issued (PENDING) invoices not yet paid. Excludes drafts, cancelled and deleted invoices.","example":1250},"lastInvoiceDate":{"type":"string","format":"date","description":"Fecha de emisión (issueDate) de la última factura emitida (PENDING/PAID) del cliente. Es la fecha civil de la factura, no la fecha de alta del registro en la app.","example":"2026-06-30"},"cifNif":{"type":"string","description":"CIF/NIF (alias for taxId)"},"taxIdType":{"type":"string","description":"Type of tax identification document (NIF, CIF, NIE, VAT, PASSPORT, OTHER). Null means auto-detect.","example":"NIF"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"},"validationWarnings":{"type":"array","description":"Validation warnings from external NIF/CIF verification. Informational only - does not block operations. Null if external validation was not performed.","example":["El nombre registrado difiere del proporcionado"],"items":{"type":"string"}},"notes":{"type":"string","description":"Optional notes about the client. Can be included in invoice templates via {{clientNotes}}.","example":"Pago a 30 días. Descuento del 5% en pedidos superiores a 1000€."}}},"UpdateBusinessRequest":{"type":"object","description":"Request to update business information","properties":{"name":{"type":"string","description":"Business name","example":"Mi Empresa S.L.","maxLength":255,"minLength":0},"taxId":{"type":"string","description":"Tax ID (CIF/NIF)","example":"B12345678"},"email":{"type":"string","description":"Business email","example":"info@miempresa.com"},"phone":{"type":"string","description":"Business phone","example":"+34 900 123 456","pattern":"^$|^\\+?[0-9\\s-()]+$"},"website":{"type":"string","description":"Business website","example":"https://miempresa.com","pattern":"^$|^(https?://)?[\\w.-]+\\.[a-z]{2,}(/.*)?$"},"description":{"type":"string","description":"Business description","maxLength":500,"minLength":0},"addressLine1":{"type":"string","description":"Address line 1","example":"Calle Principal, 123"},"addressLine2":{"type":"string","description":"Address line 2"},"city":{"type":"string","description":"City","example":"Madrid"},"province":{"type":"string","description":"Province/State","example":"Madrid"},"postalCode":{"type":"string","description":"Postal code","example":28001,"pattern":"^[0-9]{5}$"},"country":{"type":"string","description":"Country (ISO 3166-1 alpha-2)","example":"ES","maxLength":2,"minLength":2},"defaultTaxRate":{"type":"number","description":"Default tax rate","example":21,"maximum":100,"minimum":0},"defaultIrpfRate":{"type":"number","description":"Default IRPF withholding rate","example":15,"maximum":47,"minimum":0},"fiscalYearStart":{"type":"string","format":"date","description":"Fiscal year start date"},"activityType":{"type":"string","description":"Economic activity type (IAE section). Null means \"don't change\".","enum":["PROFESSIONAL","BUSINESS"],"example":"PROFESSIONAL"},"catalogMode":{"type":"string","description":"What the business sells (catalog naming). Null means \"don't change\".","enum":["SERVICES","PRODUCTS","BOTH"],"example":"SERVICES"}},"required":["addressLine1","city","country","email","name","postalCode","province","taxId"]},"BusinessDto":{"type":"object","description":"Business information","properties":{"id":{"type":"string","format":"uuid","description":"Business ID","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"Business name","example":"Mi Empresa S.L."},"taxId":{"type":"string","description":"Tax ID","example":"B12345678"},"email":{"type":"string","description":"Business email","example":"info@miempresa.com"},"phone":{"type":"string","description":"Business phone","example":"+34 900 123 456"},"website":{"type":"string","description":"Business website","example":"https://miempresa.com"},"description":{"type":"string","description":"Business description"},"addressLine1":{"type":"string","description":"Address line 1","example":"Calle Principal, 123"},"addressLine2":{"type":"string","description":"Address line 2"},"city":{"type":"string","description":"City","example":"Madrid"},"province":{"type":"string","description":"Province/State","example":"Madrid"},"postalCode":{"type":"string","description":"Postal code","example":28001},"country":{"type":"string","description":"Country","example":"ES"},"defaultTaxRate":{"type":"number","description":"Default tax rate","example":21},"defaultIrpfRate":{"type":"number","description":"Default IRPF withholding rate","example":15},"fiscalYearStart":{"type":"string","format":"date","description":"Fiscal year start date"},"activityType":{"type":"string","description":"Economic activity type (IAE section). PROFESSIONAL = IAE section 2 (default); BUSINESS = IAE section 1 (Modelo 130 not yet supported).","enum":["PROFESSIONAL","BUSINESS"],"example":"PROFESSIONAL"},"catalogMode":{"type":"string","description":"What the business sells; only changes how the catalog is named. SERVICES (default), PRODUCTS or BOTH.","enum":["SERVICES","PRODUCTS","BOTH"],"example":"SERVICES"},"isActive":{"type":"boolean","description":"Is business active","example":true},"expenseCategories":{"type":"string","description":"Comma-separated list of expense categories","example":"Compras,Servicios,Gastos fijos,Personal,Marketing y ventas,Transporte y viajes,Otros gastos"},"createdAt":{"type":"string","format":"date-time","description":"Creation date"},"updatedAt":{"type":"string","format":"date-time","description":"Last update date"}}},"JsonNode":{"type":"object"},"UpdateTemplateRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"minLength":0},"templateJson":{"$ref":"#/components/schemas/JsonNode"},"isDefault":{"type":"boolean"}}},"InvoiceTemplateDTO":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"businessId":{"type":"string","format":"uuid"},"name":{"type":"string"},"templateJson":{"$ref":"#/components/schemas/JsonNode"},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"UpdateNumberingConfigRequest":{"type":"object","description":"Request to update invoice numbering configuration","properties":{"prefix":{"type":"string","description":"Invoice number prefix (optional, can be empty)","example":"FACT","maxLength":10,"minLength":0,"pattern":"^[A-Za-z0-9]*$"},"separator":{"type":"string","description":"Separator between parts (-, /, .) or empty for no separator","example":"-","maxLength":2,"minLength":1,"pattern":"^[-/.]?$"},"yearFormat":{"type":"string","description":"Year format: YYYY for 4 digits, YY for 2 digits","enum":["YYYY","YY"],"example":"YYYY","pattern":"^(YYYY|YY)$"},"sequencePadding":{"type":"integer","format":"int32","description":"Number of digits in sequence (3-6)","example":4,"maximum":6,"minimum":3},"resetYearly":{"type":"boolean","description":"Whether to reset sequence at start of each year","example":true},"nextSequence":{"type":"integer","format":"int32","description":"Override next sequence number (use with caution)","example":100,"minimum":1},"initialSequence":{"type":"integer","format":"int32","description":"Set initial sequence number (one-time only, cannot be changed after)","example":15,"maximum":999999,"minimum":1},"formatOrder":{"type":"string","description":"Order of elements in invoice number format (comma-separated: PREFIX, YEAR, SEQUENCE)","example":"PREFIX,YEAR,SEQUENCE","pattern":"^(PREFIX|YEAR|SEQUENCE),(PREFIX|YEAR|SEQUENCE),(PREFIX|YEAR|SEQUENCE)$"}}},"InvoiceNumberingConfigDto":{"type":"object","description":"Invoice numbering configuration for a business","properties":{"id":{"type":"string","format":"uuid","description":"Configuration ID","example":"123e4567-e89b-12d3-a456-426614174000"},"businessId":{"type":"string","format":"uuid","description":"Business ID","example":"123e4567-e89b-12d3-a456-426614174000"},"prefix":{"type":"string","description":"Invoice number prefix","example":"FACT","maxLength":10,"minLength":1},"separator":{"type":"string","description":"Separator between parts","example":"-","maxLength":2,"minLength":1},"yearFormat":{"type":"string","description":"Year format: YYYY for 4 digits, YY for 2 digits","enum":["YYYY","YY"],"example":"YYYY"},"sequencePadding":{"type":"integer","format":"int32","description":"Number of digits in sequence (with leading zeros)","example":4,"maximum":6,"minimum":3},"resetYearly":{"type":"boolean","description":"Whether to reset sequence at start of each year","example":true},"nextSequence":{"type":"integer","format":"int32","description":"Next sequence number to be assigned","example":42},"lastYearUsed":{"type":"integer","format":"int32","description":"Last year when an invoice was generated","example":2025},"sequenceWasEdited":{"type":"boolean","description":"Whether the initial sequence was manually edited (can only be done once)","example":false},"formatOrder":{"type":"string","description":"Order of elements in invoice number format (comma-separated: PREFIX, YEAR, SEQUENCE)","example":"PREFIX,YEAR,SEQUENCE"},"previewNextNumber":{"type":"string","description":"Preview of next invoice number with current configuration","example":"FACT-2025-0042"},"exampleFormat":{"type":"string","description":"Example format showing how invoice numbers will look","example":"FACT-2025-0042"},"createdAt":{"type":"string","format":"date-time","description":"Configuration creation date"},"updatedAt":{"type":"string","format":"date-time","description":"Configuration last update date"}}},"UpdateExpenseDocumentRequest":{"type":"object","properties":{"invoiceNumber":{"type":"string","maxLength":100,"minLength":0},"issueDate":{"type":"string","format":"date"},"issuerName":{"type":"string","maxLength":255,"minLength":0},"issuerNif":{"type":"string","maxLength":20,"minLength":0},"issuerAddress":{"type":"string"},"recipientName":{"type":"string","maxLength":255,"minLength":0},"recipientNif":{"type":"string","maxLength":20,"minLength":0},"recipientAddress":{"type":"string"},"description":{"type":"string"},"taxBase":{"type":"number"},"vatRate":{"type":"number"},"vatAmount":{"type":"number"},"totalAmount":{"type":"number"},"irpfRetentionRate":{"type":"number","minimum":0},"irpfRetentionAmount":{"type":"number","minimum":0},"categoryId":{"type":"string","format":"uuid"},"notes":{"type":"string"}}},"ExpenseCategoryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"isActive":{"type":"boolean"},"displayOrder":{"type":"integer","format":"int32"},"vatDeductibilityRate":{"type":"number"},"vatDeductibilityType":{"type":"string"},"irpfDeductible":{"type":"boolean"},"fiscalNotes":{"type":"string"}}},"ExpenseDocumentDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"businessId":{"type":"string","format":"uuid"},"filename":{"type":"string"},"fileUrl":{"type":"string"},"fileType":{"type":"string"},"fileSize":{"type":"integer","format":"int64"},"status":{"type":"string"},"confidence":{"type":"integer","format":"int32"},"extractedData":{"$ref":"#/components/schemas/ExtractedExpenseDataDto"},"category":{"$ref":"#/components/schemas/ExpenseCategoryDto"},"suggestedCategory":{"$ref":"#/components/schemas/ExpenseCategoryDto"},"notes":{"type":"string"},"errorType":{"type":"string"},"errorMessage":{"type":"string"},"validationDeadline":{"type":"string","format":"date-time"},"validatedAt":{"type":"string","format":"date-time"},"validatedBy":{"type":"string"},"uploadedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"duplicate":{"type":"boolean"},"deductibleVatAmount":{"type":"number"},"deductibleVatRate":{"type":"number"},"deductibleIrpfPct":{"type":"integer","format":"int32"},"deductibleIrpfAmount":{"type":"number"},"casilla303":{"type":"integer","format":"int32"},"deductibleVatAmountEstimated":{"type":"number"},"isHighConfidence":{"type":"boolean"},"timeRemainingMs":{"type":"integer","format":"int64"}}},"ExtractedExpenseDataDto":{"type":"object","properties":{"invoiceNumber":{"type":"string"},"issueDate":{"type":"string","format":"date"},"issuerName":{"type":"string"},"issuerNif":{"type":"string"},"issuerAddress":{"type":"string"},"recipientName":{"type":"string"},"recipientNif":{"type":"string"},"recipientAddress":{"type":"string"},"description":{"type":"string"},"taxBase":{"type":"number"},"vatRate":{"type":"number"},"vatAmount":{"type":"number"},"totalAmount":{"type":"number"},"irpfRetentionRate":{"type":"number"},"irpfRetentionAmount":{"type":"number"}}},"UpdateRequest":{"type":"object","properties":{"memoryEnabled":{"type":"boolean"},"semanticRecallEnabled":{"type":"boolean"},"observationalMemoryEnabled":{"type":"boolean"}}},"ConsentResponse":{"type":"object","properties":{"businessId":{"type":"string","format":"uuid"},"memoryEnabled":{"type":"boolean"},"semanticRecallEnabled":{"type":"boolean"},"observationalMemoryEnabled":{"type":"boolean"},"consentGivenAt":{"type":"string","format":"date-time"},"consentVersion":{"type":"string"},"role":{"type":"string","enum":["OWNER","ADMIN","ACCOUNTANT","VIEWER"]}}},"UpdateSettingRequest":{"type":"object","description":"Request to update a system setting value","properties":{"settingValue":{"$ref":"#/components/schemas/JsonNode","description":"New setting value as JSON (can be string, number, object, or array)","example":{"value":1001}}},"required":["settingValue"]},"SystemSettingDTO":{"type":"object","description":"System setting configuration with JSONB value","properties":{"settingKey":{"type":"string","description":"Setting key identifier","example":"invoice.next_number"},"settingValue":{"$ref":"#/components/schemas/JsonNode","description":"Setting value stored as JSON (can be string, number, object, or array)","example":{"value":1000}},"description":{"type":"string","description":"Human-readable description of the setting","example":"Next invoice number to be used"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp","example":"2024-12-01T10:30:00"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp","example":"2024-12-01T15:45:00"}},"required":["settingKey","settingValue"]},"UpdateAiModelTiersRequest":{"type":"object","description":"New LiteLLM alias for each agent model tier","properties":{"complex":{"type":"string"},"simple":{"type":"string"},"ocr":{"type":"string"}},"required":["complex","ocr","simple"]},"AiModelTiers":{"type":"object","properties":{"complex":{"type":"string"},"simple":{"type":"string"},"ocr":{"type":"string"}}},"UpdateAiModelCatalogRequest":{"type":"object","description":"Full replacement list of selectable LiteLLM aliases","properties":{"aliases":{"type":"array","items":{"type":"string"}}},"required":["aliases"]},"ChangeEmailRequest":{"type":"object","description":"Request to initiate an email change (requires current password challenge)","properties":{"currentPassword":{"type":"string","description":"Current account password (re-authentication challenge)"},"newEmail":{"type":"string","description":"New email address","maxLength":255,"minLength":0}},"required":["currentPassword","newEmail"]},"MarkFiledRequest":{"type":"object","properties":{"filingDate":{"type":"string","format":"date"}}},"GenerateFormRequest":{"type":"object","properties":{"year":{"type":"integer","format":"int32","maximum":2099,"minimum":2020},"quarter":{"type":"integer","format":"int32","maximum":4,"minimum":1},"formType":{"type":"string","enum":["MODELO_303","MODELO_130","MODELO_390","MODELO_349","MODELO_347","MODELO_111","MODELO_190"]}},"required":["formType","quarter","year"]},"CreateRecurringInvoiceScheduleRequest":{"type":"object","properties":{"clientId":{"type":"string","format":"uuid"},"templateId":{"type":"string","format":"uuid"},"name":{"type":"string","maxLength":255,"minLength":0},"frequency":{"type":"string","enum":["MONTHLY","QUARTERLY","YEARLY"]},"dayOfMonth":{"type":"integer","format":"int32","maximum":28,"minimum":1},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"notesTemplate":{"type":"string","maxLength":1000,"minLength":0},"sendEmailOnRegister":{"type":"boolean"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/CreateRecurringScheduleLineRequest"}}},"required":["clientId","dayOfMonth","frequency","lines","name","startDate"]},"InvoiceSummaryDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"invoiceNumber":{"type":"string"},"draftIdentifier":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PENDING","PAID","ERROR","CANCELLED"]},"totalAmount":{"type":"number"},"issueDate":{"type":"string","format":"date"},"verifactuStatus":{"type":"string"}}},"OnboardingRequest":{"type":"object","description":"Request para completar el onboarding creando un negocio","properties":{"businessName":{"type":"string","description":"Nombre de la empresa","maxLength":200,"minLength":0},"businessTaxId":{"type":"string","description":"CIF/NIF de la empresa","maxLength":20,"minLength":0},"businessEmail":{"type":"string","description":"Email de contacto de la empresa"},"businessPhone":{"type":"string","description":"Telefono de la empresa"},"businessWebsite":{"type":"string","description":"Sitio web de la empresa","maxLength":200,"minLength":0},"addressLine1":{"type":"string","description":"Direccion linea 1","maxLength":200,"minLength":0},"addressLine2":{"type":"string","description":"Direccion linea 2","maxLength":200,"minLength":0},"city":{"type":"string","description":"Ciudad","maxLength":100,"minLength":0},"province":{"type":"string","description":"Provincia","maxLength":100,"minLength":0},"postalCode":{"type":"string","description":"Codigo postal","maxLength":10,"minLength":0},"catalogMode":{"type":"string","description":"Qué vende el negocio (nombre del catálogo). Opcional: SERVICES por defecto.","enum":["SERVICES","PRODUCTS","BOTH"],"example":"SERVICES"}},"required":["addressLine1","businessName","businessTaxId","city","postalCode","province"]},"OnboardingResponse":{"type":"object","description":"Respuesta del onboarding con datos del negocio creado","properties":{"businessId":{"type":"string","format":"uuid","description":"ID del negocio creado"},"businessName":{"type":"string","description":"Nombre del negocio creado"},"message":{"type":"string","description":"Mensaje de exito"}}},"CreateNotificationRequest":{"type":"object","description":"Request to create a system notification","properties":{"title":{"type":"string","description":"Notification title","example":"Facturas vencidas detectadas","maxLength":100,"minLength":0},"message":{"type":"string","description":"Notification message body","example":"Se han detectado 3 facturas vencidas sin cobrar","maxLength":1000,"minLength":0},"type":{"type":"string","description":"Notification type","enum":["AUDIT_SEQUENCE_GAP","AUDIT_STATUS_CHANGE","SECURITY_LOGIN","SECURITY_PERMISSION","SYSTEM_MAINTENANCE","SYSTEM_UPDATE","INVOICE_OVERDUE","PAYMENT_REMINDER_SENT","AGENT_ANOMALY","AGENT_INSIGHT","INVOICE_RECURRING_GENERATED","INVOICE_RECURRING_FAILED"],"example":"AGENT_ANOMALY"},"severity":{"type":"string","description":"Notification severity (defaults to INFO)","enum":["INFO","WARNING","ERROR","SUCCESS"],"example":"WARNING"},"actionUrl":{"type":"string","description":"Deep link URL for the notification action","example":"/invoices?status=overdue"},"referenceId":{"type":"string","description":"Reference ID for deduplication","example":"anomaly-overdue-2026-03-13"},"referenceType":{"type":"string","description":"Reference type for categorization","example":"ANOMALY"},"metadata":{"type":"object","additionalProperties":{},"description":"Additional metadata as key-value pairs"}},"required":["message","title","type"]},"NotificationDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"message":{"type":"string"},"type":{"type":"string","enum":["AUDIT_SEQUENCE_GAP","AUDIT_STATUS_CHANGE","SECURITY_LOGIN","SECURITY_PERMISSION","SYSTEM_MAINTENANCE","SYSTEM_UPDATE","INVOICE_OVERDUE","PAYMENT_REMINDER_SENT","AGENT_ANOMALY","AGENT_INSIGHT","INVOICE_RECURRING_GENERATED","INVOICE_RECURRING_FAILED"]},"severity":{"type":"string","enum":["INFO","WARNING","ERROR","SUCCESS"]},"isRead":{"type":"boolean"},"readAt":{"type":"string","format":"date-time"},"referenceId":{"type":"string"},"referenceType":{"type":"string"},"actionUrl":{"type":"string"},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string","format":"date-time"},"unread":{"type":"boolean"},"severityColor":{"type":"string"}}},"CreateInvoiceLineRequest":{"type":"object","properties":{"description":{"type":"string","maxLength":500,"minLength":0},"quantity":{"type":"number","minimum":0.01},"unitPrice":{"type":"number","minimum":0},"taxRate":{"type":"number","maximum":100,"minimum":0},"irpfRate":{"type":"number","maximum":100,"minimum":0},"discount":{"type":"number","maximum":100,"minimum":0}},"required":["description","quantity","unitPrice"]},"CreateInvoiceRequest":{"type":"object","properties":{"clientId":{"type":"string","format":"uuid"},"issueDate":{"type":"string","format":"date"},"dueDate":{"type":"string","format":"date"},"notes":{"type":"string","maxLength":1000,"minLength":0},"statusId":{"type":"string","format":"uuid"},"templateId":{"type":"string","format":"uuid"},"sendEmailOnRegister":{"type":"boolean"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/CreateInvoiceLineRequest"}}},"required":["clientId","lines"]},"StoreBothPdfsRequest":{"type":"object","description":"Request para almacenar ambos PDFs (borrador y final) de una factura registrada","properties":{"draftPdfData":{"type":"string","description":"Datos del PDF borrador (sin QR) codificados en base64","example":"JVBERi0xLjQ..."},"draftFilename":{"type":"string","description":"Nombre del archivo PDF borrador","example":"borrador_FAC-2026-001.pdf","maxLength":255,"minLength":0},"finalPdfData":{"type":"string","description":"Datos del PDF final (con QR) codificados en base64","example":"JVBERi0xLjQ..."},"finalFilename":{"type":"string","description":"Nombre del archivo PDF final","example":"factura_FAC-2026-001.pdf","maxLength":255,"minLength":0}},"required":["draftFilename","draftPdfData","finalFilename","finalPdfData"]},"StorePdfRequest":{"type":"object","description":"Request para almacenar PDF de factura","properties":{"pdfData":{"type":"string","description":"Datos del PDF codificados en base64","example":"JVBERi0xLjQ..."},"filename":{"type":"string","description":"Nombre del archivo PDF","example":"factura-FAC-001-20241224.pdf","maxLength":255,"minLength":0},"size":{"type":"integer","format":"int64","description":"Tamaño del archivo en bytes","example":245760}},"required":["filename","pdfData","size"]},"StorePdfResponse":{"type":"object","description":"Response del almacenamiento de PDF","properties":{"success":{"type":"boolean","description":"Indica si la operación fue exitosa","example":true},"fileId":{"type":"string","format":"uuid","description":"Identificador único del archivo almacenado"},"downloadUrl":{"type":"string","description":"URL para descargar el PDF","example":"/api/invoices/123e4567-e89b-12d3-a456-426614174000/download-pdf/456e7890-e89b-12d3-a456-426614174001"},"storedAt":{"type":"string","format":"date-time","description":"Timestamp de cuando se almacenó el archivo"},"filename":{"type":"string","description":"Nombre del archivo almacenado","example":"factura-FAC-001-20241224.pdf"},"size":{"type":"integer","format":"int64","description":"Tamaño del archivo en bytes","example":245760},"message":{"type":"string","description":"Mensaje adicional","example":"PDF almacenado correctamente"}}},"ResendEmailResponse":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}},"CreateRectificationRequest":{"type":"object","description":"Payload para emitir una factura rectificativa R1 sobre una factura original","properties":{"rectificationReason":{"type":"string","description":"Motivo de la rectificación (mín. 10 chars)","example":"Error en la base imponible, se corrige IVA aplicado","maxLength":500,"minLength":10},"lines":{"type":"array","description":"Líneas finales deseadas tras la rectificación (máx. 200)","items":{"$ref":"#/components/schemas/CreateInvoiceLineRequest"},"maxItems":200,"minItems":0}},"required":["lines","rectificationReason"]},"RectificationResponseDto":{"type":"object","description":"Rectificativa emitida y advertencias no bloqueantes asociadas","properties":{"invoice":{"$ref":"#/components/schemas/InvoiceDto","description":"Factura rectificativa recién emitida"},"warnings":{"type":"array","description":"Claves i18n de advertencias (legales, temporales, etc.)","items":{"type":"string"}}}},"CancelInvoiceRequest":{"type":"object","description":"Payload para anular una factura ya registrada en AEAT","properties":{"cancellationReason":{"type":"string","description":"Motivo interno (no se transmite a AEAT)","maxLength":500,"minLength":0},"acknowledgedQuarterDeclared":{"type":"boolean","description":"Confirmación explícita cuando el trimestre ya está declarado"}}},"BulkOperationRequest":{"type":"object","description":"Solicitud para operaciones masivas","properties":{"invoiceIds":{"type":"array","description":"Lista de IDs de facturas a procesar","items":{"type":"string","format":"uuid"}},"operation":{"type":"string","description":"Tipo de operación a realizar","enum":["MARK_AS_PAID","SEND_REMINDERS","CHANGE_STATUS","DELETE","EXPORT_PDF","SEND_INVOICES"]},"parameters":{"description":"Parámetros adicionales para la operación"}},"required":["invoiceIds","operation"]},"BulkOperationResponse":{"type":"object","description":"Respuesta de operación masiva","properties":{"success":{"type":"boolean","description":"Indica si la operación fue exitosa"},"message":{"type":"string","description":"Mensaje descriptivo del resultado"},"totalProcessed":{"type":"integer","format":"int32","description":"Número total de elementos procesados","example":10},"successCount":{"type":"integer","format":"int32","description":"Número de elementos procesados exitosamente","example":8},"errorCount":{"type":"integer","format":"int32","description":"Número de elementos que fallaron","example":2},"successfulIds":{"type":"array","description":"Lista de IDs procesados exitosamente","items":{"type":"string","format":"uuid"}},"errors":{"type":"array","description":"Lista de errores ocurridos","items":{"$ref":"#/components/schemas/OperationErrorDto"}}}},"OperationErrorDto":{"type":"object","description":"Error individual en operación masiva","properties":{"resourceId":{"type":"string","format":"uuid","description":"ID del elemento que falló"},"errorCode":{"type":"string","description":"Código de error","example":"INVOICE_NOT_FOUND"},"errorMessage":{"type":"string","description":"Mensaje de error","example":"La factura no fue encontrada"}}},"ExportRequest":{"type":"object","description":"Solicitud para exportar datos","properties":{"exportType":{"type":"string","description":"Tipo de datos a exportar","enum":["INVOICES","CLIENTS","INVOICE_LINES","TAX_SUMMARY","REVENUE_REPORT","CLIENT_STATEMENTS"]},"format":{"type":"string","description":"Formato del archivo de salida","enum":["CSV","EXCEL","PDF"]},"startDate":{"type":"string","format":"date","description":"Fecha de inicio del rango de datos"},"endDate":{"type":"string","format":"date","description":"Fecha de fin del rango de datos"},"specificIds":{"type":"array","description":"Lista de IDs específicos a exportar (opcional)","items":{"type":"string","format":"uuid"}},"clientId":{"type":"string","format":"uuid","description":"ID del cliente para filtrar (opcional)"},"status":{"type":"string","description":"Estado de facturas a incluir (opcional)"},"onlyPaid":{"type":"boolean","description":"Incluir solo facturas pagadas"},"includeLineDetails":{"type":"boolean","description":"Incluir detalles de líneas de factura"},"includeTaxDetails":{"type":"boolean","description":"Incluir datos fiscales detallados"},"includePdfs":{"type":"boolean","description":"Empaquetar el export junto con los PDF de las facturas en un ZIP (solo para exportType=INVOICES). Se incluyen los PDF ya generados; las facturas sin PDF se listan en invoices/_SIN_PDF.txt"}},"required":["exportType","format"]},"AcceptRequest":{"type":"object","properties":{"password":{"type":"string"},"name":{"type":"string"}}},"AcceptResponse":{"type":"object","properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"tokenType":{"type":"string"},"expiresIn":{"type":"integer","format":"int64"},"businessId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"}}},"WhatsappTokenRequest":{"type":"object","description":"Request for internal WhatsApp token generation","properties":{"phoneNumber":{"type":"string","description":"WhatsApp phone number in E.164 format","example":"+34612345678","pattern":"^\\+[1-9]\\d{7,14}$"}},"required":["phoneNumber"]},"WhatsappTokenResponse":{"type":"object","description":"Internal WhatsApp token response","properties":{"accessToken":{"type":"string","description":"JWT access token for authenticated operations"},"businessId":{"type":"string","format":"uuid","description":"Primary business ID for the user"}}},"GdprExportRequestDTO":{"type":"object","description":"GDPR data export request status and download details","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the export request"},"status":{"type":"string","description":"Current status: PENDING, PROCESSING, READY, EXPIRED, FAILED"},"requestedAt":{"type":"string","format":"date-time","description":"When the export was requested"},"completedAt":{"type":"string","format":"date-time","description":"When the export was completed (null if still processing)"},"downloadUrl":{"type":"string","description":"URL to download the export (available when status = READY)"},"expiresAt":{"type":"string","format":"date-time","description":"When the download link expires (24 h after completion)"},"fileSizeBytes":{"type":"integer","format":"int64","description":"Size of the exported file in bytes (populated on completion)"}}},"GdprErasureRequest":{"type":"object","description":"Request to initiate a GDPR data erasure","properties":{"scope":{"type":"string","description":"Erasure scope: FULL (all personal data + AI memory) or AGENT_ONLY (AI memory only)","enum":["FULL","AGENT_ONLY"],"example":"AGENT_ONLY"}},"required":["scope"]},"GdprDeletionRequestDTO":{"type":"object","description":"GDPR erasure request status and result details","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the erasure request"},"status":{"type":"string","description":"Current status: PENDING, IN_PROGRESS, COMPLETED, FAILED"},"scope":{"type":"string","description":"Erasure scope: FULL or AGENT_ONLY"},"requestedAt":{"type":"string","format":"date-time","description":"When the erasure was requested"},"completedAt":{"type":"string","format":"date-time","description":"When the erasure was completed (null if still in progress)"},"itemsDeleted":{"type":"object","additionalProperties":{"type":"integer","format":"int32"},"description":"Count of items deleted per category (populated on completion)"},"anonymizedFiscalData":{"type":"boolean","description":"Whether fiscal data was anonymized (true only for FULL scope)"}}},"IssueConfirmationTokenRequest":{"type":"object","description":"Request to mint a single-use confirmation token for an irreversible action","properties":{"action":{"type":"string","description":"Acción irreversible para la que se solicita el token","enum":["DELETE_CLIENT","REGISTER_INVOICE","RECTIFY_INVOICE","CANCEL_INVOICE"],"example":"REGISTER_INVOICE"},"resourceId":{"type":"string","format":"uuid","description":"UUID del recurso al que aplica (clientId, invoiceId)"},"source":{"type":"string","description":"Origen del token; null equivale a HUMAN_CLICK (compatibilidad con clientes antiguos)","enum":["HUMAN_CLICK","AUTO_PREF"],"example":"HUMAN_CLICK"}},"required":["action","resourceId"]},"ConfirmationTokenResponse":{"type":"object","description":"Single-use confirmation token (plaintext only returned once)","properties":{"token":{"type":"string","description":"Token plaintext (single-use, send via X-Confirmation-Token header)"},"action":{"type":"string","description":"Acción para la que es válido","enum":["DELETE_CLIENT","REGISTER_INVOICE","RECTIFY_INVOICE","CANCEL_INVOICE"]},"resourceId":{"type":"string","format":"uuid","description":"Recurso al que está atado"},"expiresAt":{"type":"string","format":"date-time","description":"Momento en que el token expira (UTC)"},"source":{"type":"string","description":"Origen del token (HUMAN_CLICK o AUTO_PREF)","enum":["HUMAN_CLICK","AUTO_PREF"]}}},"CreateClientRequest":{"type":"object","description":"Request to create a new client","properties":{"name":{"type":"string","description":"Client name","example":"ACME Corp","maxLength":255,"minLength":2},"cifNif":{"type":"string","description":"Tax identification number (CIF/NIF)","example":"B12345678","maxLength":20,"minLength":0},"taxIdType":{"type":"string","description":"Type of tax identification document. Values: NIF, CIF, NIE, VAT, PASSPORT, OTHER. Null means auto-detect from cifNif format.","example":"NIF"},"email":{"type":"string","description":"Client email","example":"contact@acmecorp.com","maxLength":255,"minLength":0},"phone":{"type":"string","description":"Client phone","example":"+34 612 345 678","maxLength":20,"minLength":0},"address":{"$ref":"#/components/schemas/Address","description":"Client address (optional)"},"defaultTaxRate":{"type":"number","description":"Default tax rate for this client","example":21},"isTaxExempt":{"type":"boolean","description":"Whether this client is tax exempt","example":false},"taxExemptionCode":{"type":"string","description":"VAT exemption reason code (E1-E6), required when client is tax exempt","enum":["ARTICLE_20","ARTICLE_21","ARTICLE_22","ARTICLE_23_24","ARTICLE_25","OTHER"],"example":"ARTICLE_20"},"notes":{"type":"string","description":"Optional notes about the client. Can be included in invoice templates.","example":"Pago a 30 días. Descuento del 5% en pedidos superiores a 1000€.","maxLength":500,"minLength":0}},"required":["name"]},"CreateCheckoutSessionRequest":{"type":"object","description":"Create Stripe Checkout Session request","properties":{"plan":{"type":"string","description":"Plan code — starter or pro","example":"starter","pattern":"(?i)^(starter|pro)$"}},"required":["plan"]},"CreateCheckoutSessionResponse":{"type":"object","description":"Stripe Checkout Session response","properties":{"checkout_url":{"type":"string","description":"Stripe-hosted Checkout URL"}}},"CreateTemplateRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"minLength":0},"templateJson":{"$ref":"#/components/schemas/JsonNode"},"isDefault":{"type":"boolean"}},"required":["name","templateJson"]},"CreateRequest":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string","enum":["OWNER","ADMIN","ACCOUNTANT","VIEWER"]}},"required":["email"]},"InvitationSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string","enum":["OWNER","ADMIN","ACCOUNTANT","VIEWER"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REVOKED","EXPIRED"]},"expiresAt":{"type":"string","format":"date-time"}}},"ValidateOtpRequest":{"type":"object","description":"Request to validate a WhatsApp linking OTP","properties":{"otpCode":{"type":"string","description":"6-digit OTP code","example":123456,"pattern":"^\\d{6}$"},"phoneNumber":{"type":"string","description":"WhatsApp phone number in E.164 format","example":"+34612345678","pattern":"^\\+[1-9]\\d{7,14}$"}},"required":["otpCode","phoneNumber"]},"InitiateLinkingRequest":{"type":"object","description":"Request to initiate WhatsApp linking via OTP","properties":{"email":{"type":"string","description":"User email address","example":"user@example.com"},"phoneNumber":{"type":"string","description":"WhatsApp phone number in E.164 format","example":"+34612345678","pattern":"^\\+[1-9]\\d{7,14}$"}},"required":["email","phoneNumber"]},"CreateTopupSessionRequest":{"type":"object","description":"AI credit top-up Checkout Session request","properties":{"amountEur":{"type":"integer","format":"int32","description":"Top-up pack amount in EUR (one of 10, 20, 30, 50)","example":20}},"required":["amountEur"]},"CreateTopupSessionResponse":{"type":"object","description":"AI credit top-up Checkout Session response","properties":{"checkout_url":{"type":"string","description":"Stripe-hosted Checkout URL"}}},"PortalSessionResponse":{"type":"object","description":"Stripe Billing Portal Session response","properties":{"portal_url":{"type":"string","description":"Stripe-hosted Billing Portal URL"}}},"ResetPasswordRequest":{"type":"object","description":"Set a new password using a reset token","properties":{"token":{"type":"string","description":"Single-use reset token received by email","maxLength":255,"minLength":0},"newPassword":{"type":"string","description":"New password","maxLength":100,"minLength":8,"pattern":"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).*$"}},"required":["newPassword","token"]},"CreateUserRequest":{"type":"object","properties":{"email":{"type":"string"},"fullName":{"type":"string","maxLength":100,"minLength":2},"password":{"type":"string","maxLength":2147483647,"minLength":8}},"required":["email","fullName","password"]},"RefreshTokenRequest":{"type":"object","description":"Refresh token request","properties":{"refreshToken":{"type":"string","description":"Refresh token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}},"required":["refreshToken"]},"ResendRequest":{"type":"object","properties":{"email":{"type":"string"}},"required":["email"]},"ConsumeRequest":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]},"MagicLinkConsumeResponse":{"type":"object","properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"tokenType":{"type":"string"},"expiresIn":{"type":"integer","format":"int64"},"requiresOnboarding":{"type":"boolean"},"userId":{"type":"string"},"businessId":{"type":"string"},"planCode":{"type":"string"}}},"LoginRequest":{"type":"object","description":"Login request","properties":{"email":{"type":"string","description":"User email","example":"user@example.com"},"password":{"type":"string","description":"User password","example":"password123"}},"required":["email","password"]},"AuthResponse":{"type":"object","description":"Authentication response","properties":{"accessToken":{"type":"string","description":"JWT access token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"refreshToken":{"type":"string","description":"JWT refresh token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"tokenType":{"type":"string","description":"Token type","example":"Bearer"},"expiresIn":{"type":"integer","format":"int64","description":"Token expiration time in seconds","example":3600},"user":{"$ref":"#/components/schemas/UserDto","description":"User information"},"businessId":{"type":"string","format":"uuid","description":"Primary business ID","example":"123e4567-e89b-12d3-a456-426614174000"},"businessName":{"type":"string","description":"Primary business name","example":"Mi Empresa S.L."}}},"ForgotPasswordRequest":{"type":"object","description":"Request a password reset link by email","properties":{"email":{"type":"string","description":"Account email","example":"user@example.com","maxLength":255,"minLength":0}},"required":["email"]},"ReconcileReportDTO":{"type":"object","description":"Reporte de reconciliación de una invoice Verifactu","properties":{"invoiceId":{"type":"string","format":"uuid","description":"ID de la factura reconciliada"},"previousStatus":{"type":"string","description":"Estado verifactu_status anterior al reconcile"},"newStatus":{"type":"string","description":"Estado verifactu_status posterior al reconcile"},"newErrorType":{"type":"string","description":"Tipo de error verifactu posterior (si aplica)"},"decision":{"type":"string","description":"Decisión tomada (FLIPPED_TO_REGISTERED, FLIPPED_TO_CANCELLED, FLIPPED_TO_ERROR, KEPT_NUMBER_DUPLICATE_AT_AEAT, NO_OP)"},"csv":{"type":"string","description":"CSV recuperado/persistido si aplica"},"providerReferenceId":{"type":"string","description":"Provider reference id si aplica"},"source":{"type":"string","description":"Fuente de la decisión (siempre LOCAL_AUDIT en este rollout)"},"rationale":{"type":"string","description":"Razón legible de la decisión"},"actorUserId":{"type":"string","format":"uuid","description":"User id que ejecutó el reconcile"},"reconciledAt":{"type":"string","format":"date-time","description":"Timestamp del reconcile"}}},"AdminCreateUserRequest":{"type":"object","properties":{"email":{"type":"string"},"fullName":{"type":"string","maxLength":100,"minLength":2},"password":{"type":"string","maxLength":50,"minLength":8},"businessName":{"type":"string","maxLength":255,"minLength":2},"businessTaxId":{"type":"string"},"businessEmail":{"type":"string"},"businessPhone":{"type":"string","maxLength":20,"minLength":0},"businessWebsite":{"type":"string","maxLength":255,"minLength":0},"businessDescription":{"type":"string","maxLength":1000,"minLength":0},"addressLine1":{"type":"string","maxLength":255,"minLength":5},"addressLine2":{"type":"string","maxLength":255,"minLength":0},"city":{"type":"string","maxLength":100,"minLength":2},"province":{"type":"string","maxLength":100,"minLength":2},"postalCode":{"type":"string","pattern":"^\\d{5}$"}},"required":["addressLine1","businessName","businessTaxId","city","email","fullName","postalCode","province"]},"AdminUserCreationResponse":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"email":{"type":"string"},"businessId":{"type":"string","format":"uuid"},"businessName":{"type":"string"},"passwordConfigured":{"type":"boolean"},"loginUrl":{"type":"string"},"message":{"type":"string"},"emailSent":{"type":"boolean"}}},"BulkImportRequest":{"type":"object","description":"Request para importar usuarios en lote desde lista de emails","properties":{"emails":{"type":"array","description":"Lista de emails a importar","example":["user1@example.com","user2@example.com"],"items":{"type":"string"}}},"required":["emails"]},"BulkImportResponse":{"type":"object","description":"Resultado de la importación en lote de usuarios","properties":{"totalRequested":{"type":"integer","format":"int32","description":"Total de emails enviados en el request"},"created":{"type":"integer","format":"int32","description":"Usuarios creados exitosamente"},"skipped":{"type":"integer","format":"int32","description":"Emails omitidos (ya existentes o inválidos)"},"failed":{"type":"integer","format":"int32","description":"Emails que fallaron al procesar"},"results":{"type":"array","description":"Resultados detallados por email","items":{"$ref":"#/components/schemas/BulkImportResult"}}}},"BulkImportResult":{"type":"object","description":"Resultado individual de importación de un email","properties":{"email":{"type":"string","description":"Email procesado"},"status":{"type":"string","description":"Estado del resultado","enum":["CREATED","ALREADY_EXISTS","INVALID_EMAIL","ERROR"]},"message":{"type":"string","description":"Mensaje descriptivo del resultado"}}},"BatchSummary":{"type":"object","properties":{"processed":{"type":"integer","format":"int32"},"succeeded":{"type":"integer","format":"int32"},"failed":{"type":"integer","format":"int32"}}},"LegacyNoticeRequest":{"type":"object","properties":{"cutoffDate":{"type":"string","format":"date"},"userIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["cutoffDate","userIds"]},"WhatsappLinkingStatusResponse":{"type":"object","description":"WhatsApp linking status for the authenticated user","properties":{"status":{"type":"string","description":"Current linking status","example":"LINKED"},"maskedPhone":{"type":"string","description":"Masked phone number when linked","example":"+34 *** *** 5678"},"hasPendingOtp":{"type":"boolean","description":"Whether there is a pending OTP verification","example":true},"otpCode":{"type":"string","description":"The OTP code to display to the user (only while PENDING)"},"otpExpiresAt":{"type":"string","format":"date-time","description":"OTP expiration time"},"botPhone":{"type":"string","description":"Bot phone number for WhatsApp deep links","example":"+56920403095"}}},"PageUserDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/UserDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"Pageablenull":{"type":"object","properties":{"pageNumber":{"type":"integer","format":"int32"},"unpaged":{"type":"boolean"},"paged":{"type":"boolean"},"pageSize":{"type":"integer","format":"int32"},"offset":{"type":"integer","format":"int64"},"sort":{"$ref":"#/components/schemas/Sortnull"}}},"Sortnull":{"type":"object","properties":{"sorted":{"type":"boolean"},"unsorted":{"type":"boolean"},"empty":{"type":"boolean"}}},"TemplateFieldsDTO":{"type":"object","properties":{"requiredFields":{"type":"array","items":{"type":"string"},"uniqueItems":true},"availableFields":{"type":"array","items":{"type":"string"},"uniqueItems":true},"requiredFieldAliases":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"brandRequiredFields":{"type":"array","items":{"type":"string"},"uniqueItems":true}}},"IvaRateBucketDto":{"type":"object","properties":{"vatRate":{"type":"number"},"taxBase":{"type":"number"},"vatAmount":{"type":"number"}}},"QuarterlyIvaSummaryDto":{"type":"object","properties":{"year":{"type":"integer","format":"int32"},"quarter":{"type":"integer","format":"int32"},"repercutido":{"type":"array","items":{"$ref":"#/components/schemas/IvaRateBucketDto"}},"soportadoDeducible":{"type":"array","items":{"$ref":"#/components/schemas/IvaRateBucketDto"}},"soportadoInversion":{"type":"array","items":{"$ref":"#/components/schemas/IvaRateBucketDto"}},"totalRepercutido":{"type":"number"},"totalSoportadoDeducible":{"type":"number"},"totalSoportadoInversion":{"type":"number"},"resultado":{"type":"number"}}},"AnnualIvaSummaryDto":{"type":"object","properties":{"year":{"type":"integer","format":"int32"},"quarters":{"type":"array","items":{"$ref":"#/components/schemas/QuarterlyIvaSummaryDto"}},"totalRepercutido":{"type":"array","items":{"$ref":"#/components/schemas/IvaRateBucketDto"}},"totalSoportadoDeducible":{"type":"array","items":{"$ref":"#/components/schemas/IvaRateBucketDto"}},"grandTotalRepercutido":{"type":"number"},"grandTotalSoportadoDeducible":{"type":"number"},"resultado":{"type":"number"}}},"QuarterlyIrpfSummaryDto":{"type":"object","properties":{"year":{"type":"integer","format":"int32"},"quarter":{"type":"integer","format":"int32"},"totalIngresos":{"type":"number"},"totalGastosDeducibles":{"type":"number"},"rendimientoNeto":{"type":"number"},"retencionesIrpf":{"type":"number"}}},"FiscalDashboardDto":{"type":"object","properties":{"currentYear":{"type":"integer","format":"int32"},"currentQuarter":{"type":"integer","format":"int32"},"ivaRepercutido":{"type":"number"},"ivaSoportadoDeducible":{"type":"number"},"ivaResultado":{"type":"number"},"irpfIngresos":{"type":"number"},"irpfGastos":{"type":"number"},"irpfRendimientoNeto":{"type":"number"},"nextFilingDeadline":{"type":"string","format":"date"},"nextFormType":{"type":"string"},"daysUntilDeadline":{"type":"integer","format":"int32"}}},"FiscalBreakdownDto":{"type":"object","properties":{"formId":{"type":"string","format":"uuid"},"formType":{"type":"string"},"year":{"type":"integer","format":"int32"},"quarter":{"type":"integer","format":"int32"},"snapshotAvailable":{"type":"boolean"},"macros":{"type":"array","items":{"$ref":"#/components/schemas/MacroBreakdownDto"}}}},"MacroBreakdownDto":{"type":"object","properties":{"macroAmount":{"type":"string","enum":["FACTURADO","IVA_REPERCUTIDO","IVA_SOPORTADO","RETENIDO","GASTOS_DEDUCIBLES"]},"casillas":{"type":"array","items":{"type":"string"}},"total":{"type":"number"},"manualDelta":{"type":"number"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/SourceLineDto"}},"notApplicable":{"type":"boolean"}}},"SourceLineDto":{"type":"object","properties":{"documentType":{"type":"string","enum":["INVOICE","EXPENSE","MANUAL_DELTA","CALCULATED"]},"documentId":{"type":"string","format":"uuid"},"documentNumber":{"type":"string"},"issueDate":{"type":"string","format":"date"},"counterpartyName":{"type":"string"},"taxBase":{"type":"number"},"appliedRate":{"type":"number"},"contributedAmount":{"type":"number"},"originQuarter":{"type":"integer","format":"int32"},"manualReason":{"type":"string"},"manualDelta":{"type":"boolean"}}},"PageRecurringInvoiceScheduleDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/RecurringInvoiceScheduleDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"PageInvoiceSummaryDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceSummaryDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"PageProductDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/ProductDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"PagedResponseNotificationDto":{"type":"object","description":"Paginated response wrapper","properties":{"content":{"type":"array","description":"List of items for current page","items":{"$ref":"#/components/schemas/NotificationDto"}},"page":{"type":"integer","format":"int32","description":"Current page number (0-indexed)","example":0},"size":{"type":"integer","format":"int32","description":"Number of items per page","example":20},"totalPages":{"type":"integer","format":"int32","description":"Total number of pages","example":5},"totalElements":{"type":"integer","format":"int64","description":"Total number of elements","example":100},"first":{"type":"boolean","description":"Whether this is the first page","example":true},"last":{"type":"boolean","description":"Whether this is the last page","example":false},"empty":{"type":"boolean","description":"Whether the page is empty","example":false}}},"UnreadCountResponse":{"type":"object","description":"Response containing unread notification count","properties":{"unreadCount":{"type":"integer","format":"int64","description":"Number of unread notifications","example":5}}},"MySubscriptionResponse":{"type":"object","description":"Current subscription summary for the authenticated user","properties":{"planCode":{"type":"string","description":"Plan code; null without a covering subscription","example":"STARTER"},"status":{"type":"string","description":"Mirror of Stripe Subscription.status; null without a covering subscription","example":"trialing"},"lockState":{"type":"string","description":"Local billing lock verdict: ok | grace | locked","example":"grace"},"graceEndsAt":{"type":"string","format":"date-time","description":"End of the running grace window, ISO-8601 UTC; null when no grace is tracked or no subscription exists","example":"2026-09-18T10:00:00Z"},"trialEnd":{"type":"string","format":"date-time","description":"Trial end; null when not trialing or no subscription exists"},"currentPeriodEnd":{"type":"string","format":"date-time","description":"Current billing period end; null without a covering subscription"},"cancelAtPeriodEnd":{"type":"boolean","description":"Whether the subscription will not renew at period end"},"aiUsedPercent":{"type":"integer","format":"int32","description":"Percentage of the monthly AI allowance consumed (0-100; uncapped for quota-exempt accounts, null without a covering subscription or plan AI cap)","example":40},"aiQuotaUnlimited":{"type":"boolean","description":"Whether this account is exempt from the AI quota and is never blocked by it","example":false},"aiTopupCentsRemaining":{"type":"integer","format":"int32","description":"Remaining prepaid AI top-up balance in cents (survives monthly reset)","example":2000},"monthlyPriceCents":{"type":"integer","format":"int32","description":"Base monthly price in cents, excluding IVA; null without a covering subscription","example":1999},"ivaRatePercent":{"type":"integer","format":"int32","description":"IVA rate; null without a covering subscription","example":21}}},"PagedResponseInvoiceDto":{"type":"object","description":"Paginated response wrapper","properties":{"content":{"type":"array","description":"List of items for current page","items":{"$ref":"#/components/schemas/InvoiceDto"}},"page":{"type":"integer","format":"int32","description":"Current page number (0-indexed)","example":0},"size":{"type":"integer","format":"int32","description":"Number of items per page","example":20},"totalPages":{"type":"integer","format":"int32","description":"Total number of pages","example":5},"totalElements":{"type":"integer","format":"int64","description":"Total number of elements","example":100},"first":{"type":"boolean","description":"Whether this is the first page","example":true},"last":{"type":"boolean","description":"Whether this is the last page","example":false},"empty":{"type":"boolean","description":"Whether the page is empty","example":false}}},"SignedUrlResponse":{"type":"object","description":"Respuesta con URL pre-firmada de S3","properties":{"url":{"type":"string","description":"URL pre-firmada para acceso temporal al archivo","example":"https://bucket.s3.region.amazonaws.com/path/file.pdf?X-Amz-Algorithm=..."},"expiresInMinutes":{"type":"integer","format":"int32","description":"Tiempo en minutos hasta que expire la URL","example":15}}},"PdfDownloadResponse":{"type":"object","properties":{"pdfBase64":{"type":"string"},"filename":{"type":"string"},"size":{"type":"integer","format":"int64"},"contentType":{"type":"string"}}},"HasFinalPdfResponse":{"type":"object","properties":{"hasPdf":{"type":"boolean"}}},"InvoiceStatsDto":{"type":"object","description":"Estadísticas de facturas del negocio","properties":{"total":{"type":"integer","format":"int32","description":"Total de facturas","example":150},"draft":{"type":"integer","format":"int32","description":"Facturas en borrador (DRAFT)","example":5},"registered":{"type":"integer","format":"int32","description":"Facturas registradas en AEAT (REGISTERED)","example":45},"error":{"type":"integer","format":"int32","description":"Facturas con error (ERROR)","example":2},"paid":{"type":"integer","format":"int32","description":"Facturas pagadas (PAID)","example":90},"unpaid":{"type":"integer","format":"int32","description":"Facturas pendientes de pago (UNPAID)","example":15},"overdue":{"type":"integer","format":"int32","description":"Facturas vencidas (OVERDUE)","example":10},"cancelled":{"type":"integer","format":"int32","description":"Facturas canceladas (CANCELLED)","example":5},"voidCount":{"type":"integer","format":"int32","description":"Facturas anuladas sin enviar (VOID)","example":3},"totalAmount":{"type":"number","description":"Monto total de todas las facturas","example":125000},"paidAmount":{"type":"number","description":"Monto total pagado","example":95000},"pendingAmount":{"type":"number","description":"Monto pendiente de pago","example":30000},"overdueAmount":{"type":"number","description":"Suma de total_amount de facturas vencidas (PENDING con due_date pasada)","example":5000}}},"PreviewResponse":{"type":"object","properties":{"email":{"type":"string"},"businessName":{"type":"string"},"role":{"type":"string","enum":["OWNER","ADMIN","ACCOUNTANT","VIEWER"]},"needsPassword":{"type":"boolean"}}},"BillingLockResponse":{"type":"object","description":"Billing lock verdict for a business (agent-facing)","properties":{"lockState":{"type":"string","description":"Local lock verdict: ok | grace | locked","example":"grace"},"graceEndsAt":{"type":"string","format":"date-time","description":"End of the running 24 h grace window, ISO-8601 UTC; null when no grace is tracked","example":"2026-09-18T10:00:00Z"}}},"AiQuotaStatusResponse":{"type":"object","description":"AI quota status of a business, as seen by the agent's pre-LLM gate","properties":{"businessId":{"type":"string","format":"uuid","description":"Business the status refers to"},"allowed":{"type":"boolean","description":"false only when the monthly cap AND the prepaid balance are exhausted"},"reason":{"type":"string","description":"ENFORCEMENT_DISABLED | EXEMPT | NO_PLAN | WITHIN_QUOTA | EXHAUSTED | USER_NOT_FOUND | OWNER_UNRESOLVED"},"enforcementEnabled":{"type":"boolean","description":"Whether ai.quota.enforcement-enabled is on for this deployment"}}},"PageGdprDeletionRequestDTO":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/GdprDeletionRequestDTO"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"FiscalCalendarResponseDto":{"type":"object","description":"Respuesta del calendario fiscal: próximos plazos + contexto","properties":{"currentQuarter":{"type":"string","description":"Trimestre actual","example":"T2"},"currentYear":{"type":"integer","format":"int32","description":"Año fiscal actual","example":2026},"upcomingDeadlines":{"type":"array","description":"Próximos plazos ordenados por proximidad","items":{"$ref":"#/components/schemas/FiscalDeadlineDto"}}}},"FiscalDeadlineDto":{"type":"object","description":"Plazo fiscal AEAT resuelto a fecha concreta","properties":{"model":{"type":"string","description":"Código del modelo","example":303},"name":{"type":"string","description":"Nombre del modelo","example":"IVA trimestral"},"description":{"type":"string","description":"Descripción legible","example":"Autoliquidación trimestral del IVA"},"period":{"type":"string","description":"Etiqueta del periodo","example":"T1"},"periodRange":{"type":"string","description":"Rango del periodo","example":"Enero - Marzo"},"deadline":{"type":"string","format":"date","description":"Fecha límite de presentación (ISO yyyy-MM-dd)","example":"2026-04-20"},"daysUntilDeadline":{"type":"integer","format":"int64","description":"Días restantes hasta el vencimiento (negativo si ya pasó)","example":7}}},"ExecutiveSummaryDto":{"type":"object","description":"Resumen ejecutivo del dashboard","properties":{"totalRevenue":{"type":"number","description":"Ingresos totales del mes"},"totalInvoices":{"type":"integer","format":"int32","description":"Total de facturas"},"totalClients":{"type":"integer","format":"int32","description":"Total de clientes activos"},"pendingAmount":{"type":"number","description":"Monto pendiente de cobro"},"monthlyGrowth":{"type":"number","format":"double","description":"Crecimiento mensual en porcentaje"},"averagePaymentDays":{"type":"number","format":"double","description":"Días promedio de cobro"},"generatedAt":{"type":"string","format":"date-time","description":"Timestamp de generación"}}},"ActivityItemDto":{"type":"object","description":"Item de actividad individual","properties":{"id":{"type":"string","description":"ID único de la actividad"},"type":{"type":"string","description":"Tipo de actividad","enum":["INVOICE_CREATED","INVOICE_SENT","INVOICE_PAID","CLIENT_CREATED","CLIENT_UPDATED","PDF_GENERATED","PAYMENT_OVERDUE"],"example":"INVOICE_CREATED"},"description":{"type":"string","description":"Descripción de la actividad","example":"Factura #FAC-2024-001 creada"},"resourceId":{"type":"string","description":"ID del recurso relacionado"},"resourceName":{"type":"string","description":"Nombre del recurso","example":"FAC-2024-001"},"timestamp":{"type":"string","format":"date-time","description":"Fecha y hora de la actividad"},"userEmail":{"type":"string","description":"Usuario que realizó la actividad","example":"juan@empresa.com"},"metadata":{"type":"string","description":"Información adicional"}}},"RecentActivityDto":{"type":"object","description":"Actividad reciente del sistema","properties":{"activities":{"type":"array","description":"Lista de actividades recientes","items":{"$ref":"#/components/schemas/ActivityItemDto"}},"timestamp":{"type":"string","format":"date-time","description":"Timestamp de consulta"}}},"ClientStatsDto":{"type":"object","description":"Estadísticas de clientes","properties":{"totalActiveClients":{"type":"integer","format":"int32","description":"Total de clientes activos","example":45},"newClientsThisMonth":{"type":"integer","format":"int32","description":"Nuevos clientes este mes","example":3},"clientsWithPendingInvoices":{"type":"integer","format":"int32","description":"Clientes con facturas pendientes","example":12},"topClientName":{"type":"string","description":"Cliente con mayor facturación"},"topClientAmount":{"type":"number","description":"Monto facturado al cliente principal","example":25000}}},"DashboardMetricsDto":{"type":"object","description":"Métricas y KPIs del dashboard principal","properties":{"invoiceStats":{"$ref":"#/components/schemas/InvoiceStatsDto","description":"Estadísticas generales de facturas"},"clientStats":{"$ref":"#/components/schemas/ClientStatsDto","description":"Estadísticas de clientes"},"financialMetrics":{"$ref":"#/components/schemas/FinancialMetricsDto","description":"Métricas financieras"},"trendData":{"$ref":"#/components/schemas/TrendDataDto","description":"Datos para gráficos de tendencias"},"generatedAt":{"type":"string","format":"date-time","description":"Timestamp de generación de métricas"}}},"FinancialMetricsDto":{"type":"object","description":"Métricas financieras del negocio","properties":{"monthlyRevenue":{"type":"number","description":"Ingresos del mes actual","example":45000},"monthlyGrowthPercentage":{"type":"number","format":"double","description":"Crecimiento mensual en porcentaje","example":15.5},"averageInvoiceAmount":{"type":"number","description":"Ingresos promedio por factura","example":1250.5},"averagePaymentDays":{"type":"number","format":"double","description":"Días promedio de cobro","example":28.5},"monthlyTaxCollection":{"type":"number","description":"Total de impuestos recaudados este mes","example":9450},"quarterlyProjection":{"type":"number","description":"Proyección de ingresos trimestre","example":135000}}},"MonthlyRevenueDto":{"type":"object","description":"Ingresos mensuales","properties":{"month":{"type":"string","description":"Mes y año","example":"2024-01"},"revenue":{"type":"number","description":"Ingresos del mes","example":42500},"invoiceCount":{"type":"integer","format":"int32","description":"Número de facturas","example":34}}},"StatusDistributionDto":{"type":"object","description":"Distribución de estados de facturas","properties":{"status":{"type":"string","description":"Estado de la factura","example":"PAID"},"statusName":{"type":"string","description":"Nombre del estado en español","example":"Pagada"},"count":{"type":"integer","format":"int32","description":"Cantidad de facturas","example":45},"percentage":{"type":"number","format":"double","description":"Porcentaje del total","example":65.2},"amount":{"type":"number","description":"Monto total del estado","example":56750}}},"TopClientDto":{"type":"object","description":"Cliente principal por facturación","properties":{"clientId":{"type":"string","description":"ID del cliente"},"name":{"type":"string","description":"Nombre del cliente","example":"Empresa ABC S.L."},"totalAmount":{"type":"number","description":"Total facturado","example":25000},"invoiceCount":{"type":"integer","format":"int32","description":"Número de facturas","example":8},"percentageOfTotal":{"type":"number","format":"double","description":"Porcentaje del total de facturación","example":18.5}}},"TrendDataDto":{"type":"object","description":"Datos de tendencias para gráficos","properties":{"monthlyRevenue":{"type":"array","description":"Ingresos por mes (últimos 12 meses)","items":{"$ref":"#/components/schemas/MonthlyRevenueDto"}},"invoiceStatusDistribution":{"type":"array","description":"Distribución de estados de facturas","items":{"$ref":"#/components/schemas/StatusDistributionDto"}},"topClients":{"type":"array","description":"Top 5 clientes por facturación","items":{"$ref":"#/components/schemas/TopClientDto"}}}},"CategoryExpenseDto":{"type":"object","description":"Gasto desglosado por categoría","properties":{"categoryId":{"type":"string","description":"ID de la categoría"},"categoryName":{"type":"string","description":"Nombre de la categoría"},"color":{"type":"string","description":"Color de la categoría (hex)"},"amount":{"type":"number","description":"Importe total en esta categoría"},"percentage":{"type":"number","format":"double","description":"Porcentaje sobre el total"},"count":{"type":"integer","format":"int32","description":"Número de gastos en esta categoría"}}},"ExpenseMetricsDto":{"type":"object","description":"Métricas de gastos para el dashboard","properties":{"monthlyTotal":{"type":"number","description":"Total de gastos del mes actual"},"monthlyVat":{"type":"number","description":"IVA deducible del mes actual"},"monthlyGrowthPercentage":{"type":"number","format":"double","description":"Porcentaje de crecimiento vs mes anterior"},"totalExpenses":{"type":"integer","format":"int32","description":"Número total de gastos validados"},"pendingValidation":{"type":"integer","format":"int32","description":"Número de gastos pendientes de validación"},"categoryBreakdown":{"type":"array","description":"Desglose de gastos por categoría","items":{"$ref":"#/components/schemas/CategoryExpenseDto"}},"monthlyTrend":{"type":"array","description":"Tendencia mensual de gastos (últimos 6 meses)","items":{"$ref":"#/components/schemas/MonthlyExpenseDto"}},"topSuppliers":{"type":"array","description":"Top proveedores por importe","items":{"$ref":"#/components/schemas/TopSupplierDto"}},"generatedAt":{"type":"string","format":"date-time","description":"Timestamp de generación"}}},"MonthlyExpenseDto":{"type":"object","description":"Gasto mensual para tendencias","properties":{"month":{"type":"string","description":"Mes en formato YYYY-MM"},"total":{"type":"number","description":"Total de gastos del mes"},"vatAmount":{"type":"number","description":"IVA del mes"}}},"TopSupplierDto":{"type":"object","description":"Proveedor con mayor facturación","properties":{"name":{"type":"string","description":"Nombre del proveedor"},"nif":{"type":"string","description":"NIF del proveedor"},"totalAmount":{"type":"number","description":"Importe total facturado"},"invoiceCount":{"type":"integer","format":"int32","description":"Número de facturas"}}},"AnomalyDto":{"type":"object","description":"Anomalía individual (grupo de items)","properties":{"type":{"type":"string","description":"Tipo","enum":["OVERDUE_INVOICES","STALE_DRAFTS","UNVALIDATED_EXPENSES"],"example":"OVERDUE_INVOICES"},"severity":{"type":"string","description":"Severidad","enum":["INFO","WARNING","CRITICAL"],"example":"WARNING"},"message":{"type":"string","description":"Mensaje legible"},"items":{"type":"array","description":"Items afectados","items":{"$ref":"#/components/schemas/AnomalyItemDto"}},"count":{"type":"integer","format":"int32","description":"Recuento total (puede superar items.size por truncado)","example":25},"totalAmount":{"type":"number","description":"Importe total agregado","example":12500}}},"AnomalyItemDto":{"type":"object","description":"Item individual dentro de una anomalía (factura, borrador o gasto)","properties":{"invoiceNumber":{"type":"string"},"draftIdentifier":{"type":"string"},"clientName":{"type":"string"},"issuerName":{"type":"string"},"dueDate":{"type":"string","format":"date"},"createdAt":{"type":"string","format":"date-time"},"uploadedAt":{"type":"string","format":"date-time"},"totalAmount":{"type":"number"},"description":{"type":"string"}}},"AnomalyReportDto":{"type":"object","description":"Anomalías detectadas en el negocio","properties":{"anomaliesFound":{"type":"integer","format":"int32","description":"Número total de tipos de anomalía detectados (0-3)"},"anomalies":{"type":"array","description":"Lista de anomalías detectadas","items":{"$ref":"#/components/schemas/AnomalyDto"}},"checkedAt":{"type":"string","format":"date-time","description":"Timestamp ISO de la generación"},"summary":{"type":"string","description":"Resumen legible"}}},"DashboardAlertsDto":{"type":"object","description":"Alertas del dashboard","properties":{"overdueInvoicesCount":{"type":"integer","format":"int32","description":"Número de facturas vencidas"},"pendingAmount":{"type":"number","description":"Monto pendiente total"},"newClientsThisMonth":{"type":"integer","format":"int32","description":"Nuevos clientes este mes"},"monthlyGrowthPercentage":{"type":"number","format":"double","description":"Porcentaje de crecimiento mensual"},"averagePaymentDelayDays":{"type":"number","format":"double","description":"Días promedio de retraso en pagos"},"criticalAlerts":{"type":"array","description":"Lista de alertas críticas","items":{"type":"string"}},"generatedAt":{"type":"string","format":"date-time","description":"Timestamp de generación"}}},"PageClientDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/ClientDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"MemberSummary":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["OWNER","ADMIN","ACCOUNTANT","VIEWER"]}}},"MembersResponse":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/MemberSummary"}},"invitations":{"type":"array","items":{"$ref":"#/components/schemas/InvitationSummary"}}}},"PageExpenseDocumentDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseDocumentDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"StatusResponse":{"type":"object","properties":{"consentGiven":{"type":"boolean"}}},"AdminUserListDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"email":{"type":"string"},"fullName":{"type":"string"},"isActive":{"type":"boolean"},"systemRole":{"type":"string","enum":["SYSTEM_ADMIN","REGULAR"]},"businessCount":{"type":"integer","format":"int32"},"createdAt":{"type":"string","format":"date-time"}}},"PagedResponseAdminUserListDto":{"type":"object","description":"Paginated response wrapper","properties":{"content":{"type":"array","description":"List of items for current page","items":{"$ref":"#/components/schemas/AdminUserListDto"}},"page":{"type":"integer","format":"int32","description":"Current page number (0-indexed)","example":0},"size":{"type":"integer","format":"int32","description":"Number of items per page","example":20},"totalPages":{"type":"integer","format":"int32","description":"Total number of pages","example":5},"totalElements":{"type":"integer","format":"int64","description":"Total number of elements","example":100},"first":{"type":"boolean","description":"Whether this is the first page","example":true},"last":{"type":"boolean","description":"Whether this is the last page","example":false},"empty":{"type":"boolean","description":"Whether the page is empty","example":false}}},"AdminSubscriptionListItemDto":{"type":"object","description":"Single subscription summary for admin listing","properties":{"id":{"type":"string","format":"uuid"},"stripeSubscriptionId":{"type":"string"},"stripeCustomerId":{"type":"string"},"userEmail":{"type":"string"},"businessName":{"type":"string"},"planCode":{"type":"string"},"status":{"type":"string"},"currentPeriodEnd":{"type":"string","format":"date-time"},"cancelAtPeriodEnd":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"PageAdminSubscriptionListItemDto":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/Pageablenull"},"numberOfElements":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/AdminSubscriptionListItemDto"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/Sortnull"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"AdminSubscriptionDetailDto":{"type":"object","description":"Detailed subscription view for admin panel","properties":{"id":{"type":"string","format":"uuid"},"stripeSubscriptionId":{"type":"string"},"stripeCustomerId":{"type":"string"},"stripeDashboardUrl":{"type":"string"},"userEmail":{"type":"string"},"userId":{"type":"string","format":"uuid"},"businessName":{"type":"string"},"businessId":{"type":"string","format":"uuid"},"planCode":{"type":"string"},"planMonthlyPriceCents":{"type":"integer","format":"int32"},"planAiCapCents":{"type":"integer","format":"int32"},"status":{"type":"string"},"trialEnd":{"type":"string","format":"date-time"},"currentPeriodStart":{"type":"string","format":"date-time"},"currentPeriodEnd":{"type":"string","format":"date-time"},"cancelAtPeriodEnd":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookLogDto":{"type":"object","description":"Single webhook event log entry","properties":{"eventId":{"type":"string"},"eventType":{"type":"string"},"receivedAt":{"type":"string","format":"date-time"},"processedAt":{"type":"string","format":"date-time"},"attemptCount":{"type":"integer","format":"int32"},"lastError":{"type":"string"}}},"ReconciliationRowDto":{"type":"object","description":"Stripe ↔ Verifactu reconciliation row","properties":{"stripeInvoiceId":{"type":"string","deprecated":true,"description":"Always null since stripe-java 33 (charge.invoice removed); join key is stripeChargeId"},"stripeChargeId":{"type":"string"},"stripeAmountCents":{"type":"integer","format":"int64"},"stripeCreatedAt":{"type":"string","format":"date-time"},"verifactuInvoiceNumber":{"type":"string"},"verifactuAmountCents":{"type":"integer","format":"int64"},"status":{"type":"string"}}},"AiModelConfigResponse":{"type":"object","properties":{"tiers":{"$ref":"#/components/schemas/AiModelTiers"},"catalog":{"type":"array","items":{"type":"string"}}}},"ErrorResponse":{"description":"Structured error body: stable errorCode, message and resolution hint.","properties":{"timestamp":{"type":"string","format":"date-time"},"status":{"type":"integer","format":"int32"},"errorCode":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"},"path":{"type":"string"},"resolution":{"type":"string"},"field":{"type":"string"},"validationErrors":{"type":"object","additionalProperties":{"type":"string"}},"debugMessage":{"type":"string"}}}},"securitySchemes":{"bearerAuth":{"type":"http","description":"Token JWT obtenido del endpoint /api/auth/login","name":"bearerAuth","scheme":"bearer","bearerFormat":"JWT"}}}}