{
  "openapi": "3.0.3",
  "info": {
    "title": "API Facturación SUNAT",
    "description": "## Plataforma SaaS de Facturación Electrónica — Perú\n\nArquitectura **100% asíncrona**: las emisiones retornan `202 Accepted` inmediatamente y SUNAT se contacta en segundo plano vía workers Redis con reintentos automáticos.\n\n### Validaciones SUNAT obligatorias\n\nEl API aplica las siguientes reglas antes de encolar cualquier documento:\n\n- **Prefijo de serie**: `F___` para facturas, `B___` para boletas, `T___` para guías, `R___` para retenciones, `P___` para percepciones, `FC__`/`BC__` para NC, `FD__`/`BD__` para ND.\n- **Plazo de emisión**: Facturas máx. 3 días retroactivos, boletas máx. 7 días (R.S. 003-2023/SUNAT).\n- **Identificación receptor**: En boletas con monto ≥ S/700, el receptor debe estar identificado (no puede usarse tipo `-`).\n- **NC/ND sobre ACEPTADO**: Las Notas de Crédito y Débito solo pueden emitirse sobre comprobantes con estado `ACEPTADO`.\n- **Exportación**: Para facturas de exportación usar `tipo_operacion: \"0401\"`. El receptor no puede ser DNI (`\"1\"`) ni sin documento (`\"-\"`). El sistema aplica automáticamente IGV 0% y `tipo_afectacion_igv: \"40\"` a todos los ítems.\n\n### Reintentos automáticos\n\nCuando SUNAT está temporalmente caída, el worker reintenta con backoff exponencial:\n`2 min → 4 min → 8 min → 16 min → 32 min → marca ERROR definitivo`.\n\nSolo errores transitorios (SUNAT caída, timeout) se reintentan.\nErrores de datos (RUC inválido, XML malformado) se marcan `RECHAZADO` inmediatamente.",
    "version": "2.1.0",
    "contact": {
      "name": "Soporte Técnico",
      "email": "soporte@luxio.dev"
    }
  },
  "servers": [
    {
      "url": "/api/v1",
      "description": "Servidor de producción"
    },
    {
      "url": "https://api.tudominio.com/api/v1",
      "description": "URL completa de producción"
    }
  ],
  "tags": [
    { "name": "Emisión", "description": "Creación de comprobantes electrónicos. Todas las respuestas son `202 Accepted` (procesamiento asíncrono vía Redis)." },
    { "name": "Comprobantes", "description": "Consulta, descarga (XML/PDF/CDR) y gestión del ciclo de vida de comprobantes emitidos." },
    { "name": "Configuración", "description": "Autogestión de credenciales SOL, certificado P12 y URL de webhook. Sin intervención del administrador." },
    { "name": "Consultas", "description": "Consultas externas a SUNAT/RENIEC y verificación de CPE de terceros." },
    { "name": "Analíticas", "description": "Estadísticas de uso del día y cuota mensual del cliente." },
    { "name": "Público", "description": "Endpoints sin autenticación requerida." }
  ],
  "security": [{ "bearerAuth": [] }],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API Key del cliente. Formato: `Bearer sk_live_XXXXXXXX`. Se obtiene en el panel de administración. Cada key está vinculada a un único RUC y entorno (BETA/PRODUCCIÓN)."
      }
    },
    "schemas": {
      "ClienteReceptor": {
        "type": "object",
        "required": ["tipo_documento", "numero_documento", "razon_social"],
        "properties": {
          "tipo_documento": {
            "type": "string",
            "enum": ["1", "4", "6", "7", "-"],
            "description": "`1`=DNI, `4`=Carnet extranjería, `6`=RUC, `7`=Pasaporte, `-`=Sin documento (solo boletas < S/700)",
            "example": "6"
          },
          "numero_documento": {
            "type": "string",
            "example": "20123456789",
            "description": "RUC (11 dígitos), DNI (8 dígitos) o `00000000` para ventas sin identificar."
          },
          "razon_social": { "type": "string", "example": "EMPRESA CLIENTE SAC" },
          "direccion": { "type": "string", "example": "Av. Siempre Viva 123" }
        }
      },
      "EmisorDireccion": {
        "type": "object",
        "properties": {
          "ubigueo": { "type": "string", "example": "150101", "description": "Código UBIGEO INEI de 6 dígitos" },
          "departamento": { "type": "string", "example": "LIMA" },
          "provincia": { "type": "string", "example": "LIMA" },
          "distrito": { "type": "string", "example": "MIRAFLORES" },
          "direccion": { "type": "string", "example": "Av. Larco 100" }
        }
      },
      "ItemVenta": {
        "type": "object",
        "required": ["descripcion", "cantidad", "precio_unitario"],
        "properties": {
          "codigo": { "type": "string", "example": "PROD-001", "description": "Código interno del producto (opcional)" },
          "descripcion": { "type": "string", "example": "Servicio de Consultoría" },
          "unidad_medida": {
            "type": "string",
            "default": "NIU",
            "example": "NIU",
            "description": "`NIU`=Unidad, `KGM`=Kilogramo, `MTR`=Metro, `ZZ`=Servicio. Ver catálogo UN/CEFACT."
          },
          "cantidad": { "type": "number", "example": 2 },
          "precio_unitario": {
            "type": "number",
            "description": "Precio **con IGV incluido**. El sistema calcula automáticamente `valor_unitario` e `igv`. Alternativamente enviar `valor_unitario` (sin IGV).",
            "example": 118.00
          },
          "valor_unitario": {
            "type": "number",
            "description": "Precio **sin IGV**. Si se omite, se calcula como `precio_unitario / 1.18`.",
            "example": 100.00
          },
          "tipo_afectacion_igv": {
            "type": "string",
            "default": "10",
            "enum": ["10", "11", "20", "30", "40"],
            "description": "`10`=Gravado Onerosa, `11`=Gravado Retiro, `20`=Exonerado, `30`=Inafecto, `40`=Exportación",
            "example": "10"
          }
        }
      },
      "ComprobanteReferencia": {
        "type": "object",
        "required": ["tipo", "serie", "correlativo"],
        "description": "Referencia al comprobante original. El comprobante debe tener estado `ACEPTADO` en el sistema; de lo contrario se rechaza con `REFERENCE_NOT_ACCEPTED`.",
        "properties": {
          "tipo": { "type": "string", "example": "01", "description": "`01`=Factura, `03`=Boleta" },
          "serie": { "type": "string", "example": "F001" },
          "correlativo": { "type": "string", "example": "123" },
          "fecha": { "type": "string", "format": "date", "example": "2025-04-14" }
        }
      },
      "FacturaRequest": {
        "type": "object",
        "required": ["serie_solicitada", "cliente", "items"],
        "description": "La `serie_solicitada` debe empezar con `F` (ej. `F001`). La `fecha_emision` no puede ser más de **3 días** retroactiva.\n\n**Factura de Exportación**: Para emitir una factura de exportación enviar `tipo_operacion: \"0401\"`. En ese caso: (1) todos los ítems se marcan automáticamente con `tipo_afectacion_igv: \"40\"` e IGV = 0%, (2) el receptor **no puede** usar tipo `\"1\"` (DNI) ni `\"-\"`, debe identificarse con `\"6\"` (RUC extranjero), `\"7\"` (Pasaporte), `\"4\"` (Carnet de extranjería) o `\"0\"` (sin documento internacional), (3) el `precio_unitario` se trata como valor sin IGV.",
        "properties": {
          "serie_solicitada": {
            "type": "string",
            "pattern": "^F[A-Z0-9]{3}$",
            "example": "F001",
            "description": "Debe empezar con `F`. 4 caracteres alfanuméricos."
          },
          "tipo_operacion": {
            "type": "string",
            "default": "0101",
            "enum": ["0101", "0112", "0401"],
            "example": "0101",
            "description": "`0101`=Venta interna, `0112`=Venta itinerante, `0401`=Exportación (Catálogo 51 SUNAT). Al usar `0401` el sistema aplica automáticamente IGV 0% en todos los ítems."
          },
          "fecha_emision": {
            "type": "string",
            "format": "date",
            "example": "2025-04-14",
            "description": "Si se omite, usa la fecha actual. **Máximo 3 días retroactivos** (R.S. 003-2023/SUNAT)."
          },
          "moneda": {
            "type": "string",
            "default": "PEN",
            "enum": ["PEN", "USD", "EUR"],
            "example": "USD",
            "description": "Para exportaciones se recomienda usar `USD` o `EUR`. Las facturas de exportación pueden emitirse en cualquier moneda."
          },
          "forma_pago": { "type": "string", "default": "Contado", "enum": ["Contado", "Credito"], "example": "Contado" },
          "monto_pendiente": { "type": "number", "description": "Monto pendiente de pago. Solo si `forma_pago = Credito`.", "example": 118.00 },
          "cuotas": {
            "type": "array",
            "description": "Cuotas de crédito. Solo si `forma_pago = Credito`.",
            "items": {
              "type": "object",
              "properties": {
                "monto": { "type": "number", "example": 59.00 },
                "fecha_pago": { "type": "string", "format": "date", "example": "2025-05-14" }
              }
            }
          },
          "emisor": { "$ref": "#/components/schemas/EmisorDireccion" },
          "cliente": { "$ref": "#/components/schemas/ClienteReceptorExportacion" },
          "items": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/ItemVenta" } }
        }
      },
      "ClienteReceptorExportacion": {
        "type": "object",
        "required": ["tipo_documento", "numero_documento", "razon_social"],
        "description": "Receptor para facturas de exportación. El `tipo_documento` **no puede ser** `\"1\"` (DNI) ni `\"-\"`.",
        "properties": {
          "tipo_documento": {
            "type": "string",
            "enum": ["0", "4", "6", "7"],
            "description": "`0`=Sin doc. internacional, `4`=Carnet de extranjería, `6`=RUC/Tax ID extranjero, `7`=Pasaporte",
            "example": "7"
          },
          "numero_documento": {
            "type": "string",
            "example": "P123456789",
            "description": "Número de pasaporte, tax ID o documento equivalente del receptor extranjero."
          },
          "razon_social": { "type": "string", "example": "ACME CORP USA LLC" },
          "direccion": { "type": "string", "example": "123 Main St, New York, NY 10001" }
        }
      },
      "BoletaRequest": {
        "type": "object",
        "required": ["serie_solicitada", "cliente", "items"],
        "description": "La `serie_solicitada` debe empezar con `B` (ej. `B001`). Para ventas ≥ S/700, el receptor debe estar identificado (no puede usarse `tipo_documento: \"-\"`).",
        "properties": {
          "serie_solicitada": {
            "type": "string",
            "pattern": "^B[A-Z0-9]{3}$",
            "example": "B001",
            "description": "Debe empezar con `B`. 4 caracteres alfanuméricos."
          },
          "tipo_operacion": { "type": "string", "default": "0101", "example": "0101" },
          "fecha_emision": {
            "type": "string",
            "format": "date",
            "example": "2025-04-14",
            "description": "**Máximo 7 días retroactivos** para boletas."
          },
          "moneda": { "type": "string", "default": "PEN", "example": "PEN" },
          "forma_pago": { "type": "string", "default": "Contado", "example": "Contado" },
          "emisor": { "$ref": "#/components/schemas/EmisorDireccion" },
          "cliente": { "$ref": "#/components/schemas/ClienteReceptor" },
          "items": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/ItemVenta" } }
        }
      },
      "NotaCreditoRequest": {
        "type": "object",
        "required": ["serie_solicitada", "comprobante_referencia", "motivo_nota", "cliente", "items"],
        "description": "La `serie_solicitada` debe empezar con `F` (si referencia una factura) o `B` (si referencia una boleta). El comprobante referenciado **debe estar en estado ACEPTADO**.",
        "properties": {
          "serie_solicitada": {
            "type": "string",
            "example": "FC01",
            "description": "Empieza con `F` para NC de factura, `B` para NC de boleta."
          },
          "comprobante_referencia": { "$ref": "#/components/schemas/ComprobanteReferencia" },
          "motivo_nota": {
            "type": "string",
            "example": "02",
            "description": "`01`=Anulación, `02`=Error en RUC, `03`=Error en descripción, `04`=Descuento global, `06`=Devolución total, `07`=Bonificación, `13`=Ajuste IVAP"
          },
          "sustento_motivo": { "type": "string", "example": "Anulación por error en el RUC del receptor" },
          "fecha_emision": { "type": "string", "format": "date", "example": "2025-04-14" },
          "moneda": { "type": "string", "default": "PEN", "example": "PEN" },
          "emisor": { "$ref": "#/components/schemas/EmisorDireccion" },
          "cliente": { "$ref": "#/components/schemas/ClienteReceptor" },
          "items": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/ItemVenta" } }
        }
      },
      "NotaDebitoRequest": {
        "type": "object",
        "required": ["serie_solicitada", "comprobante_referencia", "motivo_nota", "cliente", "items"],
        "description": "El comprobante referenciado **debe estar en estado ACEPTADO**.",
        "properties": {
          "serie_solicitada": {
            "type": "string",
            "example": "FD01",
            "description": "Empieza con `F` para ND de factura, `B` para ND de boleta."
          },
          "comprobante_referencia": { "$ref": "#/components/schemas/ComprobanteReferencia" },
          "motivo_nota": {
            "type": "string",
            "example": "01",
            "description": "`01`=Intereses por mora, `02`=Aumento en valor, `03`=Penalidades"
          },
          "sustento_motivo": { "type": "string", "example": "Intereses por mora acumulada" },
          "fecha_emision": { "type": "string", "format": "date", "example": "2025-04-14" },
          "moneda": { "type": "string", "default": "PEN", "example": "PEN" },
          "emisor": { "$ref": "#/components/schemas/EmisorDireccion" },
          "cliente": { "$ref": "#/components/schemas/ClienteReceptor" },
          "items": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/ItemVenta" } }
        }
      },
      "BajaRequest": {
        "type": "object",
        "required": ["fecha", "comprobantes"],
        "properties": {
          "fecha": { "type": "string", "format": "date", "example": "2025-04-14" },
          "comprobantes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": ["tipo", "serie", "correlativo", "motivo"],
              "properties": {
                "tipo": { "type": "string", "example": "01" },
                "serie": { "type": "string", "example": "F001" },
                "correlativo": { "type": "string", "example": "123" },
                "motivo": { "type": "string", "example": "Error en datos del receptor" }
              }
            }
          }
        }
      },
      "ResumenRequest": {
        "type": "object",
        "required": ["fecha"],
        "properties": {
          "fecha": {
            "type": "string",
            "format": "date",
            "example": "2025-04-14",
            "description": "Fecha de las boletas a consolidar."
          },
          "comprobantes": {
            "type": "array",
            "description": "Si se omite o está vacío, el sistema busca automáticamente las boletas `ACEPTADO` del día.",
            "items": { "type": "object" }
          }
        }
      },
      "GuiaRequest": {
        "type": "object",
        "required": ["serie_solicitada", "fecha_traslado", "motivo_traslado", "modalidad_traslado", "destinatario", "punto_partida", "punto_llegada", "items"],
        "description": "La `serie_solicitada` debe empezar con `T` (ej. `T001`).",
        "properties": {
          "serie_solicitada": { "type": "string", "pattern": "^T[A-Z0-9]{3}$", "example": "T001" },
          "fecha_traslado": { "type": "string", "format": "date", "example": "2025-04-15" },
          "motivo_traslado": { "type": "string", "example": "01", "description": "`01`=Venta, `02`=Compra, `04`=Traslado entre establecimientos" },
          "modalidad_traslado": { "type": "string", "example": "01", "description": "`01`=Transporte público, `02`=Transporte privado" },
          "destinatario": { "$ref": "#/components/schemas/ClienteReceptor" },
          "punto_partida": { "type": "string", "example": "Av. Lima 100, Lima" },
          "punto_llegada": { "type": "string", "example": "Av. Arequipa 200, Arequipa" },
          "items": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/ItemVenta" } }
        }
      },
      "RetencionDetalleItem": {
        "type": "object",
        "required": ["tipo_documento", "serie_numero", "fecha_emision", "fecha_pago", "total_invoice", "moneda", "monto_retencion", "monto_pagado"],
        "properties": {
          "tipo_documento": { "type": "string", "example": "01" },
          "serie_numero": { "type": "string", "example": "F001-00000123", "description": "Serie y correlativo del comprobante retenido" },
          "fecha_emision": { "type": "string", "format": "date" },
          "fecha_pago": { "type": "string", "format": "date" },
          "total_invoice": { "type": "number", "example": 1000.00 },
          "moneda": { "type": "string", "default": "PEN" },
          "monto_retencion": { "type": "number", "example": 30.00 },
          "monto_pagado": { "type": "number", "example": 970.00 }
        }
      },
      "RetencionRequest": {
        "type": "object",
        "required": ["serie_solicitada", "proveedor", "total_retencion", "total_pagado", "detalles"],
        "description": "La `serie_solicitada` debe empezar con `R` (ej. `R001`).",
        "properties": {
          "serie_solicitada": { "type": "string", "pattern": "^R[A-Z0-9]{3}$", "example": "R001" },
          "proveedor": { "$ref": "#/components/schemas/ClienteReceptor" },
          "total_retencion": { "type": "number", "example": 30.00 },
          "total_pagado": { "type": "number", "example": 970.00 },
          "regimen": { "type": "string", "default": "01", "example": "01", "description": "`01`=Retención 3%" },
          "tasa": { "type": "number", "default": 3, "example": 3 },
          "detalles": { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/RetencionDetalleItem" } }
        }
      },
      "WebhookConfigRequest": {
        "type": "object",
        "required": ["webhook_url"],
        "properties": {
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "example": "https://mi-sistema.com/webhooks/sunat",
            "description": "Solo se permiten esquemas `https://` o `http://`. No se permiten IPs privadas (`192.168.x`, `10.x`, `localhost`)."
          }
        }
      },
      "CredencialesRequest": {
        "type": "object",
        "required": ["usuario_sol", "clave_sol", "certificado_p12_base64", "certificado_pass"],
        "properties": {
          "usuario_sol": { "type": "string", "example": "MODDATOS", "description": "Usuario SOL del contribuyente (no incluir el RUC)." },
          "clave_sol": { "type": "string", "example": "moddatos" },
          "certificado_p12_base64": {
            "type": "string",
            "description": "Contenido del archivo `.p12` codificado en Base64. Convertir con: `base64 -w 0 mi_cert.p12`"
          },
          "certificado_pass": {
            "type": "string",
            "description": "Contraseña del certificado P12. Se validará criptográficamente antes de guardarse."
          }
        }
      },
      "ConsultaCpeRequest": {
        "type": "object",
        "required": ["ruc_emisor", "tipo_comprobante", "serie", "correlativo"],
        "properties": {
          "ruc_emisor": { "type": "string", "example": "20100000001" },
          "tipo_comprobante": { "type": "string", "example": "01" },
          "serie": { "type": "string", "example": "F001" },
          "correlativo": { "type": "integer", "example": 123 },
          "fecha_emision": { "type": "string", "format": "date", "example": "2025-04-14" },
          "monto_total": { "type": "number", "example": 118.00 }
        }
      },
      "ComprobanteResponse": {
        "type": "object",
        "description": "Objeto de comprobante en su forma canónica v2.1. Siempre la misma estructura independientemente del tipo de emisión.",
        "properties": {
          "id": { "type": "integer", "example": 123 },
          "comprobante": {
            "type": "string",
            "example": "20100000000-01-F001-00000123",
            "description": "Identificador único del comprobante en formato SUNAT: `RUC-TIPO-SERIE-CORRELATIVO`."
          },
          "estado": {
            "type": "string",
            "enum": ["EN_PROCESO", "ACEPTADO", "RECHAZADO", "ERROR", "ANULADO"],
            "example": "ACEPTADO",
            "description": "`EN_PROCESO`: en cola Redis. `ACEPTADO`: CDR disponible. `RECHAZADO`: error de datos. `ERROR`: falló tras 5 reintentos. `ANULADO`: baja aceptada."
          },
          "ticket_sunat": { "type": "string", "nullable": true, "description": "Solo para Bajas (RA) y Resúmenes (RC). Usar con `GET /tickets/{ticket}`." },
          "hash": { "type": "string", "nullable": true, "example": "7a4f9c2e..." },
          "fecha_emision": { "type": "string", "format": "date" },
          "enlace": {
            "type": "object",
            "properties": {
              "xml": { "type": "string", "format": "uri" },
              "pdf": { "type": "string", "format": "uri" },
              "cdr": { "type": "string", "format": "uri" }
            }
          },
          "sunat": {
            "type": "object",
            "properties": {
              "codigo": { "type": "string", "nullable": true, "example": "0", "description": "`0`=Aceptado. `4xxx`=Observación (válido). `1xxx-3xxx`=Error." },
              "mensaje": { "type": "string", "nullable": true }
            }
          },
          "metadata": {
            "type": "object",
            "properties": {
              "serie": { "type": "string" },
              "correlativo": { "type": "integer" },
              "tipo_comprobante": { "type": "string" },
              "receptor_num_doc": { "type": "string" },
              "receptor_razon_social": { "type": "string" },
              "monto_total": { "type": "number" },
              "moneda": { "type": "string" },
              "created_at": { "type": "string", "format": "date-time" }
            }
          },
          "webhook_event": { "type": "string", "nullable": true, "example": "comprobante.aceptado" }
        }
      },
      "SuccessResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": true },
          "message": { "type": "string" },
          "data": {}
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "boolean", "example": true },
          "mensaje": { "type": "string", "example": "La serie de Factura debe empezar con F." },
          "codigo_interno": {
            "type": "string",
            "nullable": true,
            "example": "INVALID_SERIE",
            "description": "Códigos posibles: `INVALID_SERIE`, `FECHA_EMISION_VENCIDA`, `RECEPTOR_REQUERIDO`, `RECEPTOR_INVALIDO_EXPORTACION`, `REFERENCE_NOT_ACCEPTED`, `MISSING_REFERENCE`, `DOC_NOT_FOUND`, `QUOTA_EXCEEDED`, `ALREADY_ACCEPTED`, `DUPLICATE_REQUEST`, `SUNAT_ERROR`."
          },
          "codigo_sunat": { "type": "string", "nullable": true, "description": "Código de error SUNAT (solo cuando `codigo_interno = SUNAT_ERROR`)." },
          "status": { "type": "integer" }
        }
      },
      "ListadoResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean" },
          "data": {
            "type": "object",
            "properties": {
              "items": { "type": "array", "items": { "$ref": "#/components/schemas/ComprobanteResponse" } },
              "meta": {
                "type": "object",
                "properties": {
                  "total": { "type": "integer" },
                  "limit": { "type": "integer" },
                  "offset": { "type": "integer" }
                }
              }
            }
          }
        }
      },
      "DashboardStats": {
        "type": "object",
        "properties": {
          "resumen_hoy": {
            "type": "object",
            "properties": {
              "Aceptado": { "type": "integer" },
              "Rechazado": { "type": "integer" },
              "Pendiente": { "type": "integer" },
              "Excepcion": { "type": "integer" },
              "Total": { "type": "integer" }
            }
          },
          "alertas": {
            "type": "array",
            "description": "Últimos 5 comprobantes con estado `Excepcion`.",
            "items": { "$ref": "#/components/schemas/ComprobanteResponse" }
          },
          "timestamp": { "type": "string", "format": "date-time" }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "API Key ausente o inválida.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "NotFound": {
        "description": "Recurso no encontrado.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "UnprocessableEntity": {
        "description": "Error de validación. Revisar `codigo_interno` para el detalle exacto.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "examples": {
              "serie_invalida": {
                "summary": "Serie con prefijo incorrecto",
                "value": { "error": true, "mensaje": "La serie de Factura debe empezar con F (Ej. F001).", "codigo_interno": "INVALID_SERIE", "status": 422 }
              },
              "fecha_vencida": {
                "summary": "Fecha de emisión fuera del plazo SUNAT",
                "value": { "error": true, "mensaje": "La fecha de emisión supera el plazo máximo de 3 días calendario permitido por SUNAT (R.S. 003-2023).", "codigo_interno": "FECHA_EMISION_VENCIDA", "status": 422 }
              },
              "receptor_requerido": {
                "summary": "Boleta ≥ S/700 sin receptor identificado",
                "value": { "error": true, "mensaje": "Para boletas con monto mayor a S/700, el receptor debe estar identificado (tipo_documento distinto de \"-\").", "codigo_interno": "RECEPTOR_REQUERIDO", "status": 422 }
              },
              "reference_not_accepted": {
                "summary": "NC/ND sobre documento no ACEPTADO",
                "value": { "error": true, "mensaje": "El comprobante 'F001-00000123' tiene estado 'EN_PROCESO'. SUNAT solo acepta Notas sobre comprobantes ACEPTADOS.", "codigo_interno": "REFERENCE_NOT_ACCEPTED", "status": 422 }
              },
              "receptor_invalido_exportacion": {
                "summary": "Receptor inválido para exportación",
                "value": { "error": true, "mensaje": "Para facturas de exportación el receptor debe identificarse con Pasaporte (7), Carnet de Extranjería (4), RUC (6) u otro doc. internacional (0). No se permite DNI ni Sin Documento.", "codigo_interno": "RECEPTOR_INVALIDO_EXPORTACION", "status": 422 }
              },
              "p12_invalido": {
                "summary": "Certificado P12 o contraseña incorrecta",
                "value": { "error": true, "mensaje": "El certificado P12 no es válido o la contraseña del certificado es incorrecta.", "status": 422 }
              }
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit excedido. Esperar el tiempo indicado en `Retry-After`.",
        "headers": {
          "Retry-After": { "schema": { "type": "integer" }, "description": "Segundos hasta que se libera el límite" },
          "X-RateLimit-Limit": { "schema": { "type": "integer" }, "description": "Límite configurado por minuto" },
          "X-RateLimit-Remaining": { "schema": { "type": "integer" } }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "QuotaExceeded": {
        "description": "Cuota mensual del plan agotada.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": { "error": true, "mensaje": "Límite de cuota mensual excedido o suscripción inactiva.", "codigo_interno": "QUOTA_EXCEEDED", "status": 402 }
          }
        }
      },
      "EmisionAceptada": {
        "description": "Comprobante recibido. Se está procesando de forma asíncrona en Redis. Usar `GET /comprobantes/{id}/estado` para polling o configurar webhook.",
        "headers": {
          "X-Idempotency-Cache": { "schema": { "type": "string", "enum": ["HIT", "MISS"] }, "description": "`HIT`=Respuesta cacheada de una petición anterior. `MISS`=Nuevo procesamiento." }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                { "$ref": "#/components/schemas/SuccessResponse" },
                { "properties": { "data": { "$ref": "#/components/schemas/ComprobanteResponse" } } }
              ]
            }
          }
        }
      }
    },
    "parameters": {
      "ComprobanteId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": { "type": "integer" },
        "description": "ID interno del comprobante."
      },
      "LimitParam": {
        "name": "limit",
        "in": "query",
        "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 }
      },
      "OffsetParam": {
        "name": "offset",
        "in": "query",
        "schema": { "type": "integer", "default": 0, "minimum": 0 }
      }
    }
  },
  "paths": {
    "/facturas": {
      "post": {
        "operationId": "emitirFactura",
        "tags": ["Emisión"],
        "summary": "Emitir Factura Electrónica (Tipo 01)",
        "description": "**Reglas SUNAT:**\n- Serie debe empezar con `F` (ej. `F001`)\n- `fecha_emision` máx. 3 días retroactivos\n- Receptor con `tipo_documento: \"6\"` (RUC) para empresas peruanas\n\n**Factura de Exportación** (`tipo_operacion: \"0401\"`):\n- El receptor **no puede** usar `tipo_documento: \"1\"` (DNI) ni `\"-\"`. Usar `\"7\"` (Pasaporte), `\"4\"` (CE), `\"6\"` (Tax ID), o `\"0\"` (sin doc. internacional)\n- El sistema aplica automáticamente IGV 0% y `tipo_afectacion_igv: \"40\"` en todos los ítems\n- Se recomienda emitir en moneda extranjera (`USD`, `EUR`)\n- El `precio_unitario` se trata como valor **sin IGV** (igual al valor de exportación)\n\nRetorna `202 Accepted` inmediatamente. El envío a SUNAT ocurre en segundo plano.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FacturaRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/QuotaExceeded" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/boletas": {
      "post": {
        "operationId": "emitirBoleta",
        "tags": ["Emisión"],
        "summary": "Emitir Boleta de Venta (Tipo 03)",
        "description": "**Reglas SUNAT:**\n- Serie debe empezar con `B` (ej. `B001`)\n- `fecha_emision` máx. 7 días retroactivos\n- Si monto ≥ S/700 el receptor **debe** estar identificado (DNI o RUC)\n- Para ventas < S/700 sin identificar: `tipo_documento: \"-\"`, `numero_documento: \"00000000\"`\n\nLas boletas se consolidan vía Resumen Diario para enviar a SUNAT.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BoletaRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/QuotaExceeded" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/notas-credito": {
      "post": {
        "operationId": "emitirNotaCredito",
        "tags": ["Emisión"],
        "summary": "Emitir Nota de Crédito (Tipo 07)",
        "description": "**Reglas SUNAT:**\n- El `comprobante_referencia` debe tener estado `ACEPTADO` en el sistema\n- Serie empieza con `F` si referencia una factura, `B` si referencia una boleta\n- `motivo_nota`: `01`=Anulación, `02`=Error RUC, `03`=Error descripción, `04`=Descuento, `06`=Devolución, `07`=Bonificación",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotaCreditoRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/QuotaExceeded" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/notas-debito": {
      "post": {
        "operationId": "emitirNotaDebito",
        "tags": ["Emisión"],
        "summary": "Emitir Nota de Débito (Tipo 08)",
        "description": "**Reglas SUNAT:**\n- El `comprobante_referencia` debe tener estado `ACEPTADO` en el sistema\n- `motivo_nota`: `01`=Intereses mora, `02`=Aumento valor, `03`=Penalidades",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotaDebitoRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/QuotaExceeded" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/guias": {
      "post": {
        "operationId": "emitirGuia",
        "tags": ["Emisión"],
        "summary": "Emitir Guía de Remisión (Tipo 09)",
        "description": "**Reglas SUNAT:**\n- Serie debe empezar con `T` (ej. `T001`)\n- `motivo_traslado`: `01`=Venta, `02`=Compra, `04`=Entre establecimientos\n- `modalidad_traslado`: `01`=Transporte público, `02`=Transporte privado",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GuiaRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/bajas": {
      "post": {
        "operationId": "emitirBaja",
        "tags": ["Emisión"],
        "summary": "Comunicación de Baja (RA)",
        "description": "Anula uno o más comprobantes ya enviados a SUNAT. **El proceso es asíncrono**: SUNAT retorna un ticket que debe consultarse con `GET /tickets/{ticket}` para saber si la baja fue aceptada.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BajaRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/resumenes": {
      "post": {
        "operationId": "emitirResumen",
        "tags": ["Emisión"],
        "summary": "Resumen Diario de Boletas (RC)",
        "description": "Consolida boletas de un día específico en un solo envío a SUNAT. Si `comprobantes` está vacío o se omite, el sistema busca automáticamente todas las boletas con estado `ACEPTADO` de la fecha indicada.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResumenRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/retenciones": {
      "post": {
        "operationId": "emitirRetencion",
        "tags": ["Emisión"],
        "summary": "Comprobante de Retención (Tipo 20)",
        "description": "**Reglas SUNAT:**\n- Serie debe empezar con `R` (ej. `R001`)\n- Usa el endpoint SOAP de **Retenciones** (diferente al de Facturas)\n- `regimen: \"01\"` = Régimen de retención del 3%",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RetencionRequest" } } }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" }
        }
      }
    },
    "/percepciones": {
      "post": {
        "operationId": "emitirPercepcion",
        "tags": ["Emisión"],
        "summary": "Comprobante de Percepción (Tipo 40)",
        "description": "**Reglas SUNAT:**\n- Serie debe empezar con `P` (ej. `P001`)\n- Usa el endpoint SOAP de **Retenciones/Percepciones** (diferente al de Facturas)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["serie_solicitada", "cliente", "comprobantes"],
                "properties": {
                  "serie_solicitada": { "type": "string", "pattern": "^P[A-Z0-9]{3}$", "example": "P001" },
                  "cliente": { "$ref": "#/components/schemas/ClienteReceptor" },
                  "comprobantes": { "type": "array", "items": { "type": "object" } }
                }
              }
            }
          }
        },
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" }
        }
      }
    },
    "/comprobantes": {
      "get": {
        "operationId": "listarComprobantes",
        "tags": ["Comprobantes"],
        "summary": "Listar comprobantes con filtros y paginación",
        "description": "Retorna todos los comprobantes del cliente autenticado. Los datos están completamente aislados por tenant (empresa).",
        "parameters": [
          { "name": "estado", "in": "query", "schema": { "type": "string", "enum": ["EN_PROCESO", "ACEPTADO", "RECHAZADO", "ERROR", "ANULADO"] }, "description": "Estado del comprobante en el sistema." },
          { "name": "tipo", "in": "query", "schema": { "type": "string", "enum": ["01", "03", "07", "08", "09", "20", "40", "RA", "RC"] } },
          { "name": "fecha_desde", "in": "query", "schema": { "type": "string", "format": "date" }, "example": "2025-04-01" },
          { "name": "fecha_hasta", "in": "query", "schema": { "type": "string", "format": "date" }, "example": "2025-04-30" },
          { "name": "receptor", "in": "query", "description": "RUC o Razón Social parcial del receptor (búsqueda por LIKE).", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/LimitParam" },
          { "$ref": "#/components/parameters/OffsetParam" }
        ],
        "responses": {
          "200": { "description": "Lista paginada de comprobantes.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListadoResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/TooManyRequests" }
        }
      }
    },
    "/comprobantes/{id}": {
      "get": {
        "operationId": "verComprobante",
        "tags": ["Comprobantes"],
        "summary": "Detalle de un comprobante",
        "parameters": [{ "$ref": "#/components/parameters/ComprobanteId" }],
        "responses": {
          "200": { "description": "Detalle completo del comprobante.", "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ComprobanteResponse" } } }] } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/comprobantes/{id}/estado": {
      "get": {
        "operationId": "consultarEstadoComprobante",
        "tags": ["Comprobantes"],
        "summary": "Sincronizar estado con SUNAT en tiempo real",
        "description": "Consulta directamente los webservices de SUNAT y actualiza el estado local. Útil para **polling** en lugar de webhooks. No consultar más de 1 vez por segundo.",
        "parameters": [{ "$ref": "#/components/parameters/ComprobanteId" }],
        "responses": {
          "200": { "description": "Estado actualizado desde SUNAT.", "content": { "application/json": { "schema": { "allOf": [{ "$ref": "#/components/schemas/SuccessResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ComprobanteResponse" } } }] } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/comprobantes/{id}/xml": {
      "get": {
        "operationId": "descargarXml",
        "tags": ["Comprobantes"],
        "summary": "Descargar XML firmado (UBL 2.1)",
        "parameters": [{ "$ref": "#/components/parameters/ComprobanteId" }],
        "responses": {
          "200": { "description": "Archivo XML con firma digital.", "content": { "application/xml": { "schema": { "type": "string", "format": "binary" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/comprobantes/{id}/pdf": {
      "get": {
        "operationId": "descargarPdf",
        "tags": ["Comprobantes"],
        "summary": "Descargar representación impresa (PDF)",
        "description": "Si el PDF no existe, se genera al vuelo con los datos del comprobante y se almacena en caché.",
        "parameters": [{ "$ref": "#/components/parameters/ComprobanteId" }],
        "responses": {
          "200": { "description": "Archivo PDF.", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/comprobantes/{id}/cdr": {
      "get": {
        "operationId": "descargarCdr",
        "tags": ["Comprobantes"],
        "summary": "Descargar CDR de SUNAT (ZIP)",
        "description": "La Constancia de Recepción (CDR) es el comprobante oficial de que SUNAT aceptó el documento. Solo disponible cuando `estado = ACEPTADO`.",
        "parameters": [{ "$ref": "#/components/parameters/ComprobanteId" }],
        "responses": {
          "200": { "description": "Archivo ZIP con la Constancia de Recepción.", "content": { "application/zip": { "schema": { "type": "string", "format": "binary" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/comprobantes/{id}/reenviar": {
      "post": {
        "operationId": "reenviarComprobante",
        "tags": ["Comprobantes"],
        "summary": "Re-encolar para reintento a SUNAT",
        "description": "Encola el documento para un nuevo intento de envío a SUNAT. Solo disponible si `estado = ERROR`. Retorna `422 ALREADY_ACCEPTED` si el comprobante ya fue aceptado.",
        "parameters": [{ "$ref": "#/components/parameters/ComprobanteId" }],
        "responses": {
          "202": { "$ref": "#/components/responses/EmisionAceptada" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "422": {
            "description": "Comprobante ya aceptado o en proceso.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" },
                "example": { "error": true, "mensaje": "El comprobante ya fue aceptado por SUNAT.", "codigo_interno": "ALREADY_ACCEPTED", "status": 422 }
              }
            }
          }
        }
      }
    },
    "/config/webhook": {
      "patch": {
        "operationId": "actualizarWebhook",
        "tags": ["Configuración"],
        "summary": "Actualizar URL de webhook del cliente",
        "description": "Configura la URL donde el sistema enviará notificaciones cuando SUNAT procese un comprobante.\n\n**Restricciones de seguridad:**\n- Solo esquemas `https://` o `http://`\n- No se permiten IPs privadas (`192.168.x`, `10.x`, `localhost`, `127.0.0.1`)\n\nCada empresa tiene su propio `webhook_secret` para validar la firma HMAC-SHA256.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookConfigRequest" } } } },
        "responses": {
          "200": { "description": "URL de webhook actualizada.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "$ref": "#/components/responses/UnprocessableEntity" }
        }
      }
    },
    "/config/credenciales": {
      "post": {
        "operationId": "configurarCredenciales",
        "tags": ["Configuración"],
        "summary": "Configurar credenciales SOL y certificado P12",
        "description": "Permite al cliente configurar sus credenciales SUNAT sin intervención del administrador.\n\n**Proceso de validación:**\n1. El base64 del P12 se decodifica\n2. Se valida criptográficamente con la contraseña usando `openssl_pkcs12_read`\n3. Solo si la validación es exitosa se guarda en `storage/certs/{cliente_id}/`\n4. La `clave_sol` y `certificado_pass` se cifran con AES-256-CBC antes de almacenarse en BD\n\nConvertir P12 a base64: `base64 -w 0 mi_cert.p12`",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredencialesRequest" } } } },
        "responses": {
          "200": {
            "description": "Credenciales configuradas correctamente.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SuccessResponse" },
                "example": { "success": true, "message": "Credenciales y Certificado configurados con éxito.", "data": { "usuario_sol": "MODDATOS", "certificado_file": "cert_a1b2c3.p12", "status": "CONFIGURED" } }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Certificado P12 inválido o contraseña incorrecta.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      }
    },
    "/consultar/ruc/{ruc}": {
      "get": {
        "operationId": "consultarRuc",
        "tags": ["Consultas"],
        "summary": "Consultar datos de empresa por RUC (SUNAT)",
        "description": "Útil para autocompletar datos del receptor al emitir un comprobante.",
        "parameters": [{ "name": "ruc", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[0-9]{11}$" }, "example": "20100000001" }],
        "responses": {
          "200": { "description": "Datos de la empresa.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/consultar/dni/{dni}": {
      "get": {
        "operationId": "consultarDni",
        "tags": ["Consultas"],
        "summary": "Consultar datos de persona por DNI (RENIEC)",
        "parameters": [{ "name": "dni", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[0-9]{8}$" }, "example": "12345678" }],
        "responses": {
          "200": { "description": "Datos de la persona.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/consultar/comprobante": {
      "post": {
        "operationId": "consultarCpe",
        "tags": ["Consultas"],
        "summary": "Verificar validez de un CPE externo en SUNAT",
        "description": "Consulta si un comprobante de **otra empresa** es válido ante SUNAT. Útil para verificar facturas de proveedores.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConsultaCpeRequest" } } } },
        "responses": {
          "200": {
            "description": "Resultado de validez.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SuccessResponse" },
                "example": { "success": true, "data": { "estado_codigo": "1", "estado_label": "ACEPTADO", "sunat_response": "El comprobante existe y es válido." } }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/tickets/{ticket}": {
      "get": {
        "operationId": "consultarTicket",
        "tags": ["Consultas"],
        "summary": "Consultar resultado de ticket asíncrono de SUNAT",
        "description": "Las **Comunicaciones de Baja** (RA) y **Resúmenes Diarios** (RC) son documentos asíncronos: SUNAT devuelve un ticket en lugar de un CDR inmediato. Usar este endpoint para saber si SUNAT ya procesó el ticket.",
        "parameters": [{ "name": "ticket", "in": "path", "required": true, "schema": { "type": "string" }, "example": "2025123456789" }],
        "responses": {
          "200": { "description": "Estado del ticket de SUNAT.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/dashboard/stats": {
      "get": {
        "operationId": "dashboardStats",
        "tags": ["Analíticas"],
        "summary": "Estadísticas del día y cuota mensual",
        "description": "Retorna el resumen de comprobantes emitidos hoy, alertas de comprobantes con errores y el estado de la cuota mensual del plan.",
        "responses": {
          "200": {
            "description": "Estadísticas del cliente autenticado.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/SuccessResponse" },
                    { "properties": { "data": { "$ref": "#/components/schemas/DashboardStats" } } }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    }
  }
}
