{
  "openapi": "3.0.3",
  "info": {
    "title": "Documentación API Shards (Greenter)",
    "description": "Emite facturas, boletas, notas y guías de remisión electrónicas a SUNAT desde tu ERP con una sola llamada POST.\n\n## Flujo de integración\n\n1. **Emite** — `POST /generate-invoice` (o `/generate-note`, `/generate-despatch`). Recibes un `transaction_id` con `202 Accepted`.\n2. **Consulta** — `POST /transactions/sync-status` con tus `invoice_ids`. Devuelve el estado de cada uno.\n3. **Descarga** — `GET /download/pdf/{file}` o `/download/xml/{file}` cuando el documento esté aceptado.\n\nUsa `external_reference.invoice_id` en cada emisión para mapear tus IDs con los nuestros.\n\n## Estados (`normalized_state`)\n\n| Estado | Significado |\n|--------|-------------|\n| `pending` | En proceso — espera el CDR de SUNAT |\n| `accepted` | Aceptado por SUNAT — CDR disponible en `cdr_path` |\n| `rejected` | Rechazado por SUNAT — revisa `sunat_response_code` |\n| `expired` | Fuera del plazo normativo — no se reenviará |\n| `error` | Fallo transitorio — reintento automático programado |\n\n## Notas por tipo\n\n- **Facturas (01) y Notas (07/08)**: CDR disponible en segundos.\n- **Boletas (03)**: se consolidan en un Resumen Diario automático cada noche. El estado pasa a `accepted` cuando SUNAT confirma el resumen.\n- **Guías de Remisión (09)**: flujo asíncrono vía API GRE. El CDR llega en minutos.\n- **Comunicaciones de Baja**: `POST /generate-voided` — válidas hasta 7 días después de la emisión.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://{shard_host}",
      "description": "Usa el shard asignado por la Central, no una URL fija",
      "variables": {
        "shard_host": {
          "default": "api.factuflash.pe"
        }
      }
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key o JWT",
        "description": "API key ff_test_… para beta o ff_live_… para producción. Las llaves anteriores siguen admitidas por compatibilidad. La URL es el shard devuelto al seleccionar la empresa."
      }
    }
  },
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/api/sunat/{ruc}/generate-invoice": {
      "post": {
        "tags": [
          "Comprobantes de Pago"
        ],
        "summary": "Emitir Factura o Boleta",
        "description": "Genera una Factura Electrónica (01) o Boleta de Venta (03). \n\n**Selecciona abajo en el menú 'Examples' el caso que deseas examinar:**\n1. Modelo para enviar una Factura (1 Sol).\n2. Modelo para enviar una Boleta (1 Sol).\n\n### Operaciones gratuitas\n\nEl importe por cobrar puede ser cero si existe una transferencia gratuita válida. No se acepta una venta ordinaria (`tipo_afe_igv=10`) con precio cero. Use la afectación del catálogo 07 que corresponde a su operación: gravadas gratuitas 11–16; exonerada gratuita 21; inafectas gratuitas 31–36. Una cortesía por retiro gravado usa 13; no suponga que toda cortesía está exonerada.\n\n- `items[].valor_gratuito`: valor referencial unitario **sin IGV**, positivo.\n- En el ítem gratuito, `valor_unitario` y `precio_unitario` son cero; `valor_venta` y `base_igv` son cantidad × valor_gratuito. `igv` y `total_impuestos` reflejan su impuesto.\n- `mto_oper_gratuitas` suma los valores referenciales de los ítems gratuitos; `mto_igv_gratuitas` suma su IGV. Ambos campos son requeridos cuando hay ítems gratuitos.\n- `mto_oper_gravadas`, `mto_igv`, `total_impuestos`, `valor_venta`, `sub_total` y `mto_imp_venta` de cabecera corresponden a la parte onerosa, sin sumar el valor ni el IGV de las gratuitas. En una cortesía completa son cero.\n- El XML incluye precio referencial tipo 02 y leyenda 1002. El IGV del retiro gravado no se cobra al cliente. La tasa se informa en `porcentaje_igv`; el ejemplo usa 18%.\n- Para una operación mixta, mantenga sus líneas cobradas y gratuitas separadas. FactuFlash también conserva estos campos en notas y resúmenes diarios.\n\n### Validación y correlativos\n\n`422` con `error.code=VALIDATION_ERROR` o `BUSINESS_VALIDATION_ERROR` indica que esta solicitud no se encoló: lea `error.message` y `error.details` (validación de entrada) o `error.validation_errors` (negocio). No equivale a un CDR rechazado por SUNAT. FactuFlash recibe el correlativo del integrador; no incrementa su serie. El integrador debe validar antes de reservar el número y conservar el intento. Corregir una solicitud rechazada antes del registro no exige por sí solo otro número: conserve su identidad y compruebe que no exista previamente. Nunca retroceda un contador ni rellene huecos con otras ventas automáticamente. Ante timeout, 5xx o resultado incierto, concilie la misma serie y número antes de volver a emitir. Un `202` solo confirma recepción interna: espere el estado SUNAT.\n\n### Anticipos (adelantos)\n\n1. Emita el adelanto con `es_anticipo=true`, pago al contado y operación 0101. Espere aceptación SUNAT.\n2. En la venta final declare los ítems completos y las referencias en `anticipos`, más `total_anticipos`. Catálogo 12: 02 factura de anticipo, 03 boleta.\n3. `valor_venta` y `sub_total` conservan el importe original; las bases de cabecera y los impuestos deducen lo anticipado. `mto_imp_venta = sub_total - total_anticipos`. Una venta de 118 con adelanto 59 lleva base neta 50, IGV neto 9, valor_venta 100, sub_total 118 y saldo 59. Puede quedar saldo cero sin convertir las líneas en gratuitas.\n\nSe admiten múltiples anticipos propios, aceptados, del mismo cliente, moneda y ambiente, afectaciones 10/20/30 y una sola tasa gravada. No se admiten documentos externos, detracciones ni mezcla con gratuitas. El panel ofrece soles/18% al contado.\n\nEl saldo se reserva antes de encolar. Un reintento conserva los mismos datos y no duplica la reserva. Un error o timeout no libera automáticamente anticipos. Las notas/bajas sobre adelantos aplicados se bloquean; la reversión y devolución requieren conciliación, sin liberación automática.\n\nLos ejemplos de aplicación parcial y total son alternativas: no consuma dos veces el mismo adelanto. El ejemplo de recepción debe estar aceptado antes de aplicar su referencia.\n",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "description": "El RUC de la empresa emisora.",
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "UUID estable por operación. Conserva exactamente la llave y JSON al reintentar. 409 si cambian los datos o sigue en proceso.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mto_imp_venta": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Importe por pagar. Cero con operaciones gratuitas válidas o una venta totalmente cubierta por anticipos validados."
                  },
                  "mto_oper_gratuitas": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Suma de valores referenciales sin IGV. Requerido cuando hay ítems gratuitos."
                  },
                  "mto_igv_gratuitas": {
                    "type": "number",
                    "minimum": 0,
                    "description": "IGV de las operaciones gratuitas; separado del impuesto cobrado. Requerido cuando hay ítems gratuitos."
                  },
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 200,
                    "items": {
                      "type": "object",
                      "properties": {
                        "valor_gratuito": {
                          "type": "number",
                          "exclusiveMinimum": true,
                          "minimum": 0,
                          "description": "Valor referencial unitario sin IGV, obligatorio solo en ítems gratuitos."
                        },
                        "tipo_afe_igv": {
                          "type": "string",
                          "description": "Catálogo 07. Gratuitas: 11–16, 21, 31–36."
                        }
                      }
                    }
                  },
                  "es_anticipo": {
                    "type": "boolean",
                    "default": false,
                    "description": "Marca el comprobante de recepción de un adelanto. Al contado, cliente identificado, operación 0101. No puede aplicar otros anticipos."
                  },
                  "anticipos": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 99,
                    "description": "Comprobantes de anticipo aceptados, emitidos por esta empresa en FactuFlash. Mismo cliente, moneda y ambiente; saldo suficiente. No se repiten referencias.",
                    "items": {
                      "type": "object",
                      "required": [
                        "tipo_doc_rel",
                        "nro_doc_rel",
                        "total",
                        "tipo_afe_igv",
                        "porcentaje_igv"
                      ],
                      "properties": {
                        "tipo_doc_rel": {
                          "type": "string",
                          "enum": [
                            "02",
                            "03"
                          ],
                          "description": "Catálogo 12: 02 factura de anticipo; 03 boleta de anticipo."
                        },
                        "nro_doc_rel": {
                          "type": "string",
                          "pattern": "^[FB][A-Z0-9]{3}-[0-9]{1,8}$",
                          "example": "FT01-00001001"
                        },
                        "total": {
                          "type": "number",
                          "minimum": 0.01,
                          "multipleOf": 0.01,
                          "description": "Importe bruto aplicado, incluidos impuestos."
                        },
                        "tipo_afe_igv": {
                          "type": "string",
                          "enum": [
                            "10",
                            "20",
                            "30"
                          ]
                        },
                        "porcentaje_igv": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Tasa original: positiva para 10; cero para 20/30."
                        }
                      }
                    }
                  },
                  "total_anticipos": {
                    "type": "number",
                    "minimum": 0,
                    "multipleOf": 0.01,
                    "description": "Suma bruta de anticipos aplicados. Obligatorio con anticipos; no basta enviarlo sin referencias."
                  }
                }
              },
              "examples": {
                "Factura (01)": {
                  "summary": "Modelo: Factura S/ 1.00",
                  "value": {
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20100454523",
                      "rzn_social": "EMPRESA DE PRUEBA SAC"
                    },
                    "tipo_operacion": "0101",
                    "tipo_doc": "01",
                    "serie": "F012",
                    "correlativo": "2519",
                    "fecha_emision": "2026-03-25",
                    "tipo_moneda": "PEN",
                    "mto_oper_gravadas": 0.85,
                    "mto_igv": 0.15,
                    "total_impuestos": 0.15,
                    "valor_venta": 0.85,
                    "sub_total": 1.0,
                    "mto_imp_venta": 1.0,
                    "legend_value": "UNO Y 00/100 SOLES",
                    "items": [
                      {
                        "cod_producto": "P001",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 0.85,
                        "descripcion": "Producto Prueba Factura 1 Sol",
                        "base_igv": 0.85,
                        "porcentaje_igv": 18,
                        "igv": 0.15,
                        "tipo_afe_igv": "10",
                        "total_impuestos": 0.15,
                        "valor_venta": 0.85,
                        "precio_unitario": 1.0
                      }
                    ]
                  }
                },
                "Boleta (03)": {
                  "summary": "Modelo: Boleta S/ 1.00",
                  "value": {
                    "client": {
                      "tipo_doc": "1",
                      "num_doc": "12345678",
                      "rzn_social": "CLIENTE FINAL PRUEBA"
                    },
                    "tipo_operacion": "0101",
                    "tipo_doc": "03",
                    "serie": "B012",
                    "correlativo": "2520",
                    "fecha_emision": "2026-03-25",
                    "tipo_moneda": "PEN",
                    "mto_oper_gravadas": 0.85,
                    "mto_igv": 0.15,
                    "total_impuestos": 0.15,
                    "valor_venta": 0.85,
                    "sub_total": 1.0,
                    "mto_imp_venta": 1.0,
                    "legend_value": "UNO Y 00/100 SOLES",
                    "items": [
                      {
                        "cod_producto": "B001",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 0.85,
                        "descripcion": "Producto Prueba Boleta 1 Sol",
                        "base_igv": 0.85,
                        "porcentaje_igv": 18,
                        "igv": 0.15,
                        "tipo_afe_igv": "10",
                        "total_impuestos": 0.15,
                        "valor_venta": 0.85,
                        "precio_unitario": 1.0
                      }
                    ]
                  }
                },
                "Factura": {
                  "summary": "Factura — cambia fecha y correlativo",
                  "value": {
                    "tipo_doc": "01",
                    "tipo_operacion": "0101",
                    "serie": "FT01",
                    "correlativo": "1",
                    "fecha_emision": "2026-11-07",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 100,
                    "mto_igv": 18,
                    "total_impuestos": 18,
                    "valor_venta": 100,
                    "sub_total": 118,
                    "mto_imp_venta": 118,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Servicio de prueba beta",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 100,
                        "precio_unitario": 118,
                        "valor_venta": 100,
                        "base_igv": 100,
                        "igv": 18,
                        "total_impuestos": 18,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ]
                  }
                },
                "Boleta": {
                  "summary": "Boleta — cambia fecha y correlativo",
                  "value": {
                    "tipo_doc": "03",
                    "tipo_operacion": "0101",
                    "serie": "BT01",
                    "correlativo": "1",
                    "fecha_emision": "2026-11-07",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "1",
                      "num_doc": "12345678",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 100,
                    "mto_igv": 18,
                    "total_impuestos": 18,
                    "valor_venta": 100,
                    "sub_total": 118,
                    "mto_imp_venta": 118,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Servicio de prueba beta",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 100,
                        "precio_unitario": 118,
                        "valor_venta": 100,
                        "base_igv": 100,
                        "igv": 18,
                        "total_impuestos": 18,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ]
                  }
                },
                "Operación gratuita": {
                  "summary": "Cortesía: referencia S/ 12 con IGV, cobro S/ 0",
                  "value": {
                    "tipo_doc": "03",
                    "tipo_operacion": "0101",
                    "serie": "BT01",
                    "correlativo": "2",
                    "fecha_emision": "2026-11-12",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "0",
                      "num_doc": "00000000",
                      "rzn_social": "CLIENTE FINAL"
                    },
                    "mto_oper_gravadas": 0,
                    "mto_igv": 0,
                    "total_impuestos": 0,
                    "valor_venta": 0,
                    "sub_total": 0,
                    "mto_imp_venta": 0,
                    "items": [
                      {
                        "cod_producto": "CORTESIA",
                        "descripcion": "Cortesía de cumpleaños",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 0,
                        "precio_unitario": 0,
                        "valor_gratuito": 10.17,
                        "valor_venta": 10.17,
                        "base_igv": 10.17,
                        "igv": 1.83,
                        "total_impuestos": 1.83,
                        "tipo_afe_igv": "13",
                        "porcentaje_igv": 18
                      }
                    ],
                    "mto_oper_gratuitas": 10.17,
                    "mto_igv_gratuitas": 1.83,
                    "legend_value": "CERO Y 00/100 SOLES"
                  }
                },
                "Venta mixta": {
                  "summary": "Venta S/ 11.80 + cortesía (referencia S/ 12)",
                  "value": {
                    "tipo_doc": "03",
                    "tipo_operacion": "0101",
                    "serie": "BT01",
                    "correlativo": "3",
                    "fecha_emision": "2026-11-12",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "0",
                      "num_doc": "00000000",
                      "rzn_social": "CLIENTE FINAL"
                    },
                    "mto_oper_gravadas": 10,
                    "mto_igv": 1.8,
                    "total_impuestos": 1.8,
                    "valor_venta": 10,
                    "sub_total": 11.8,
                    "mto_imp_venta": 11.8,
                    "items": [
                      {
                        "cod_producto": "CORTESIA",
                        "descripcion": "Cortesía de cumpleaños",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 0,
                        "precio_unitario": 0,
                        "valor_gratuito": 10.17,
                        "valor_venta": 10.17,
                        "base_igv": 10.17,
                        "igv": 1.83,
                        "total_impuestos": 1.83,
                        "tipo_afe_igv": "13",
                        "porcentaje_igv": 18
                      },
                      {
                        "cod_producto": "VENTA",
                        "descripcion": "Producto vendido",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 10,
                        "precio_unitario": 11.8,
                        "valor_venta": 10,
                        "base_igv": 10,
                        "igv": 1.8,
                        "total_impuestos": 1.8,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ],
                    "mto_oper_gratuitas": 10.17,
                    "mto_igv_gratuitas": 1.83,
                    "legend_value": "ONCE Y 80/100 SOLES"
                  }
                },
                "Recepción de anticipo": {
                  "summary": "Recepción de anticipo",
                  "value": {
                    "tipo_doc": "01",
                    "tipo_operacion": "0101",
                    "serie": "FT01",
                    "correlativo": "1001",
                    "fecha_emision": "2026-11-12",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 50,
                    "mto_igv": 9,
                    "total_impuestos": 9,
                    "valor_venta": 50,
                    "sub_total": 59,
                    "mto_imp_venta": 59,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Anticipo del servicio contratado",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 50,
                        "precio_unitario": 59,
                        "valor_venta": 50,
                        "base_igv": 50,
                        "igv": 9,
                        "total_impuestos": 9,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ],
                    "es_anticipo": true,
                    "legend_value": "CINCUENTA Y NUEVE Y 00/100 SOLES"
                  }
                },
                "Venta con anticipo y saldo": {
                  "summary": "Venta con anticipo y saldo",
                  "value": {
                    "tipo_doc": "01",
                    "tipo_operacion": "0101",
                    "serie": "FT01",
                    "correlativo": "1002",
                    "fecha_emision": "2026-11-12",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 50,
                    "mto_igv": 9,
                    "total_impuestos": 9,
                    "valor_venta": 100,
                    "sub_total": 118,
                    "mto_imp_venta": 59,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Servicio de prueba beta",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 100,
                        "precio_unitario": 118,
                        "valor_venta": 100,
                        "base_igv": 100,
                        "igv": 18,
                        "total_impuestos": 18,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ],
                    "legend_value": "CINCUENTA Y NUEVE Y 00/100 SOLES",
                    "total_anticipos": 59,
                    "anticipos": [
                      {
                        "tipo_doc_rel": "02",
                        "nro_doc_rel": "FT01-00001001",
                        "total": 59,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ]
                  }
                },
                "Venta cubierta por anticipo (alternativa)": {
                  "summary": "Venta cubierta por anticipo (alternativa)",
                  "value": {
                    "tipo_doc": "01",
                    "tipo_operacion": "0101",
                    "serie": "FT01",
                    "correlativo": "1002",
                    "fecha_emision": "2026-11-12",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 0,
                    "mto_igv": 0,
                    "total_impuestos": 0,
                    "valor_venta": 50,
                    "sub_total": 59,
                    "mto_imp_venta": 0,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Servicio contratado cubierto por el anticipo",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 50,
                        "precio_unitario": 59,
                        "valor_venta": 50,
                        "base_igv": 50,
                        "igv": 9,
                        "total_impuestos": 9,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ],
                    "legend_value": "CERO Y 00/100 SOLES",
                    "total_anticipos": 59,
                    "anticipos": [
                      {
                        "tipo_doc_rel": "02",
                        "nro_doc_rel": "FT01-00001001",
                        "total": 59,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Documento aceptado internamente y encolado para SUNAT (asíncrono).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "status": {
                      "type": "string",
                      "example": "ACCEPTED_INTERNAL"
                    },
                    "message": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "integer",
                      "example": 1234
                    },
                    "performance": {
                      "type": "object",
                      "properties": {
                        "total_time_ms": {
                          "type": "number",
                          "example": 75.58
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "El documento ya existe en SUNAT (enviado previamente). Se devuelven los datos del original.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "transaction_id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "xml_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "response": {
                      "type": "object",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "nullable": true,
                          "description": "VALIDATION_ERROR: mapa campo → mensajes. BUSINESS_VALIDATION_ERROR: lista de objetos con field, code y message.",
                          "oneOf": [
                            {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            {
                              "type": "array",
                              "items": {
                                "type": "object"
                              }
                            }
                          ]
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Monto cero inválido": {
                    "value": {
                      "success": false,
                      "error": {
                        "code": "VALIDATION_ERROR",
                        "message": "Datos de entrada inválidos",
                        "details": {
                          "mto_imp_venta": [
                            "El importe debe ser al menos 0.01, salvo operaciones gratuitas con valor referencial válido."
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite mensual de documentos alcanzado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "LIMIT_EXCEEDED"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Llave de idempotencia en uso o contenido distinto."
          }
        }
      }
    },
    "/api/sunat/{ruc}/generate-note": {
      "post": {
        "tags": [
          "Notas de Crédito / Débito"
        ],
        "summary": "Emitir Nota (07 o 08)",
        "description": "Genera una Nota de Crédito (07) o Débito (08). Se vinculará a la serie y número de un documento enviado previamente de forma obligatoria.\n\n### Operaciones gratuitas\n\nEl importe por cobrar puede ser cero si existe una transferencia gratuita válida. No se acepta una venta ordinaria (`tipo_afe_igv=10`) con precio cero. Use la afectación del catálogo 07 que corresponde a su operación: gravadas gratuitas 11–16; exonerada gratuita 21; inafectas gratuitas 31–36. Una cortesía por retiro gravado usa 13; no suponga que toda cortesía está exonerada.\n\n- `items[].valor_gratuito`: valor referencial unitario **sin IGV**, positivo.\n- En el ítem gratuito, `valor_unitario` y `precio_unitario` son cero; `valor_venta` y `base_igv` son cantidad × valor_gratuito. `igv` y `total_impuestos` reflejan su impuesto.\n- `mto_oper_gratuitas` suma los valores referenciales de los ítems gratuitos; `mto_igv_gratuitas` suma su IGV. Ambos campos son requeridos cuando hay ítems gratuitos.\n- `mto_oper_gravadas`, `mto_igv`, `total_impuestos`, `valor_venta`, `sub_total` y `mto_imp_venta` de cabecera corresponden a la parte onerosa, sin sumar el valor ni el IGV de las gratuitas. En una cortesía completa son cero.\n- El XML incluye precio referencial tipo 02 y leyenda 1002. El IGV del retiro gravado no se cobra al cliente. La tasa se informa en `porcentaje_igv`; el ejemplo usa 18%.\n- Para una operación mixta, mantenga sus líneas cobradas y gratuitas separadas. FactuFlash también conserva estos campos en notas y resúmenes diarios.\n\n### Validación y correlativos\n\n`422` con `error.code=VALIDATION_ERROR` o `BUSINESS_VALIDATION_ERROR` indica que esta solicitud no se encoló: lea `error.message` y `error.details` (mapa por campo o lista de errores). No equivale a un CDR rechazado por SUNAT. FactuFlash recibe el correlativo del integrador; no incrementa su serie. El integrador debe validar antes de reservar el número y conservar el intento. Corregir una solicitud rechazada antes del registro no exige por sí solo otro número: conserve su identidad y compruebe que no exista previamente. Nunca retroceda un contador ni rellene huecos con otras ventas automáticamente. Ante timeout, 5xx o resultado incierto, concilie la misma serie y número antes de volver a emitir. Un `202` solo confirma recepción interna: espere el estado SUNAT.\n",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "UUID estable por operación. Conserva exactamente la llave y JSON al reintentar. 409 si cambian los datos o sigue en proceso.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mto_imp_venta": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Importe por cobrar. Cero solo con operaciones gratuitas válidas."
                  },
                  "mto_oper_gratuitas": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Suma de valores referenciales sin IGV. Requerido cuando hay ítems gratuitos."
                  },
                  "mto_igv_gratuitas": {
                    "type": "number",
                    "minimum": 0,
                    "description": "IGV de las operaciones gratuitas; separado del impuesto cobrado. Requerido cuando hay ítems gratuitos."
                  },
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 200,
                    "items": {
                      "type": "object",
                      "properties": {
                        "valor_gratuito": {
                          "type": "number",
                          "exclusiveMinimum": true,
                          "minimum": 0,
                          "description": "Valor referencial unitario sin IGV, obligatorio solo en ítems gratuitos."
                        },
                        "tipo_afe_igv": {
                          "type": "string",
                          "description": "Catálogo 07. Gratuitas: 11–16, 21, 31–36."
                        }
                      }
                    }
                  }
                }
              },
              "examples": {
                "Nota de Credito": {
                  "summary": "Anulación de Factura vía Nota Crédito",
                  "value": {
                    "tipo_doc": "07",
                    "serie": "FC01",
                    "correlativo": "1",
                    "fecha_emision": "2026-03-25",
                    "tipo_doc_afectado": "01",
                    "num_doc_afectado": "F012-2519",
                    "cod_motivo": "01",
                    "des_motivo": "Anulacion de la operacion",
                    "tipo_moneda": "PEN",
                    "mto_oper_gravadas": 0.85,
                    "mto_igv": 0.15,
                    "total_impuestos": 0.15,
                    "valor_venta": 0.85,
                    "sub_total": 1.0,
                    "mto_imp_venta": 1.0,
                    "legend_value": "UNO Y 00/100 SOLES",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20100454523",
                      "rzn_social": "EMPRESA DE PRUEBA SAC"
                    },
                    "items": [
                      {
                        "cod_producto": "P001",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 0.85,
                        "descripcion": "Producto Prueba Factura 1 Sol",
                        "base_igv": 0.85,
                        "porcentaje_igv": 18,
                        "igv": 0.15,
                        "tipo_afe_igv": "10",
                        "total_impuestos": 0.15,
                        "valor_venta": 0.85,
                        "precio_unitario": 1.0
                      }
                    ]
                  }
                },
                "Nota de crédito": {
                  "summary": "Nota de crédito — cambia fecha y correlativo",
                  "value": {
                    "tipo_doc": "07",
                    "tipo_operacion": "0101",
                    "serie": "FC01",
                    "correlativo": "1",
                    "fecha_emision": "2026-11-07",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 100,
                    "mto_igv": 18,
                    "total_impuestos": 18,
                    "valor_venta": 100,
                    "sub_total": 118,
                    "mto_imp_venta": 118,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Servicio de prueba beta",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 100,
                        "precio_unitario": 118,
                        "valor_venta": 100,
                        "base_igv": 100,
                        "igv": 18,
                        "total_impuestos": 18,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ],
                    "tipo_doc_afectado": "01",
                    "num_doc_afectado": "FT01-1",
                    "cod_motivo": "01",
                    "des_motivo": "Ajuste de prueba"
                  }
                },
                "Nota de débito": {
                  "summary": "Nota de débito — cambia fecha y correlativo",
                  "value": {
                    "tipo_doc": "08",
                    "tipo_operacion": "0101",
                    "serie": "FD01",
                    "correlativo": "1",
                    "fecha_emision": "2026-11-07",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "CLIENTE DE PRUEBA"
                    },
                    "mto_oper_gravadas": 100,
                    "mto_igv": 18,
                    "total_impuestos": 18,
                    "valor_venta": 100,
                    "sub_total": 118,
                    "mto_imp_venta": 118,
                    "items": [
                      {
                        "cod_producto": "TEST",
                        "descripcion": "Servicio de prueba beta",
                        "unidad": "ZZ",
                        "cantidad": 1,
                        "valor_unitario": 100,
                        "precio_unitario": 118,
                        "valor_venta": 100,
                        "base_igv": 100,
                        "igv": 18,
                        "total_impuestos": 18,
                        "tipo_afe_igv": "10",
                        "porcentaje_igv": 18
                      }
                    ],
                    "tipo_doc_afectado": "01",
                    "num_doc_afectado": "FT01-1",
                    "cod_motivo": "03",
                    "des_motivo": "Ajuste de prueba"
                  }
                },
                "Operación gratuita": {
                  "summary": "Cortesía: referencia S/ 12 con IGV, cobro S/ 0",
                  "value": {
                    "tipo_doc": "07",
                    "tipo_operacion": "0101",
                    "serie": "BC01",
                    "correlativo": "1",
                    "fecha_emision": "2026-11-12",
                    "tipo_moneda": "PEN",
                    "client": {
                      "tipo_doc": "0",
                      "num_doc": "00000000",
                      "rzn_social": "CLIENTE FINAL"
                    },
                    "mto_oper_gravadas": 0,
                    "mto_igv": 0,
                    "total_impuestos": 0,
                    "valor_venta": 0,
                    "sub_total": 0,
                    "mto_imp_venta": 0,
                    "items": [
                      {
                        "cod_producto": "CORTESIA",
                        "descripcion": "Cortesía de cumpleaños",
                        "unidad": "NIU",
                        "cantidad": 1,
                        "valor_unitario": 0,
                        "precio_unitario": 0,
                        "valor_gratuito": 10.17,
                        "valor_venta": 10.17,
                        "base_igv": 10.17,
                        "igv": 1.83,
                        "total_impuestos": 1.83,
                        "tipo_afe_igv": "13",
                        "porcentaje_igv": 18
                      }
                    ],
                    "mto_oper_gratuitas": 10.17,
                    "mto_igv_gratuitas": 1.83,
                    "legend_value": "CERO Y 00/100 SOLES",
                    "tipo_doc_afectado": "03",
                    "num_doc_afectado": "BT01-2",
                    "cod_motivo": "01",
                    "des_motivo": "ANULACION DE LA OPERACION GRATUITA"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Documento aceptado internamente y encolado para SUNAT (asíncrono).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "status": {
                      "type": "string",
                      "example": "ACCEPTED_INTERNAL"
                    },
                    "message": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "integer",
                      "example": 1234
                    },
                    "performance": {
                      "type": "object",
                      "properties": {
                        "total_time_ms": {
                          "type": "number",
                          "example": 75.58
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "El documento ya existe en SUNAT (enviado previamente). Se devuelven los datos del original.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "transaction_id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "xml_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "response": {
                      "type": "object",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "nullable": true,
                          "description": "VALIDATION_ERROR: mapa campo → mensajes. BUSINESS_VALIDATION_ERROR: lista de objetos con field, code y message.",
                          "oneOf": [
                            {
                              "type": "object",
                              "additionalProperties": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            {
                              "type": "array",
                              "items": {
                                "type": "object"
                              }
                            }
                          ]
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "Monto cero inválido": {
                    "value": {
                      "success": false,
                      "error": {
                        "code": "VALIDATION_ERROR",
                        "message": "Datos de entrada inválidos",
                        "details": {
                          "mto_imp_venta": [
                            "El importe debe ser al menos 0.01, salvo operaciones gratuitas con valor referencial válido."
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite mensual de documentos alcanzado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "LIMIT_EXCEEDED"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Llave de idempotencia en uso o contenido distinto."
          }
        }
      }
    },
    "/api/sunat/{ruc}/generate-voided": {
      "post": {
        "tags": [
          "Anulaciones y Bajas"
        ],
        "summary": "Comunicación de Baja",
        "description": "Da de baja documentos comunicados a SUNAT (RA). Aplica típicamente a Facturas (01) en SUNAT. Simplemente se envía la referencia pura.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "UUID estable por operación. Conserva exactamente la llave y JSON al reintentar. 409 si cambian los datos o sigue en proceso.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "documents",
                  "date"
                ],
                "properties": {
                  "documents": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "tipo_doc",
                        "serie",
                        "correlativo",
                        "motivo_baja"
                      ],
                      "properties": {
                        "tipo_doc": {
                          "type": "string",
                          "example": "01"
                        },
                        "serie": {
                          "type": "string",
                          "example": "F001"
                        },
                        "correlativo": {
                          "type": "string",
                          "example": "2519"
                        },
                        "motivo_baja": {
                          "type": "string",
                          "example": "ERROR EN LA OPERACION"
                        }
                      }
                    }
                  },
                  "date": {
                    "type": "string",
                    "format": "date",
                    "description": "Fecha de la comunicación (día en que se informa la baja)."
                  },
                  "reference_date": {
                    "type": "string",
                    "format": "date",
                    "nullable": true,
                    "description": "Fecha de emisión de los documentos dados de baja (fecha de generación). Si se omite se usa `date`, lo que solo es correcto si la baja se comunica el mismo día en que se emitió el documento. Debe ser menor o igual a `date`."
                  },
                  "external_reference": {
                    "type": "object",
                    "nullable": true,
                    "description": "Referencias libres para mapear con tus propios IDs (ej. invoice_id)."
                  }
                }
              },
              "examples": {
                "Baja": {
                  "summary": "Baja de Factura Previa",
                  "value": {
                    "date": "2026-03-25",
                    "documents": [
                      {
                        "tipo_doc": "01",
                        "serie": "F012",
                        "correlativo": "2519",
                        "motivo_baja": "ERROR VENTA CANCELADA POR CLIENTE"
                      }
                    ]
                  }
                },
                "Comunicación de baja": {
                  "summary": "Comunicación de baja — cambia fecha y correlativo",
                  "value": {
                    "date": "2026-11-07",
                    "documents": [
                      {
                        "tipo_doc": "01",
                        "serie": "FT01",
                        "correlativo": "1",
                        "motivo_baja": "Error en datos del cliente"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Documento aceptado internamente y encolado para SUNAT (asíncrono).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "status": {
                      "type": "string",
                      "example": "ACCEPTED_INTERNAL"
                    },
                    "message": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "integer",
                      "example": 1234
                    },
                    "performance": {
                      "type": "object",
                      "properties": {
                        "total_time_ms": {
                          "type": "number",
                          "example": 75.58
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "El documento ya existe en SUNAT (enviado previamente). Se devuelven los datos del original.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "transaction_id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "xml_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "response": {
                      "type": "object",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "object",
                          "nullable": true,
                          "description": "Sólo presente en errores de validación de entrada."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite mensual de documentos alcanzado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "LIMIT_EXCEEDED"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Llave de idempotencia en uso o contenido distinto."
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions": {
      "get": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Historial de Transacciones",
        "description": "Devuelve la lista paginada de todos los documentos y su rastreo en el Shard, sus estados (`success`, `pending_summary`, `error`), XML y CDR vinculados.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listado obtenido correctamente"
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions/force-summaries": {
      "post": {
        "tags": [
          "Resúmenes Diarios (Boletas)"
        ],
        "summary": "Forzar cierre del día actual (esta empresa)",
        "description": "**Atajo del botón \"Cerrar día y enviar\" del panel.**\n\nCierra el día corriente SOLO para esta empresa: consolida TODAS las boletas pendientes (`status=pending_summary`) del día en UN solo Resumen Diario y lo envía a SUNAT al instante.\n\nUtilidad: cuando el hotel cierra caja antes de las 23:55 y quiere que sus boletas aparezcan en SUNAT el mismo día sin esperar al schedule automático.\n\n### Idempotente y seguro\n- Si no hay pendientes → no toca SUNAT, solo verifica tickets en curso.\n- Si lo invocas varias veces el mismo día → solo el primer call consolida; los siguientes responden `pending_count: 0`.\n- Múltiples RCs el mismo día están bien — cada uno con correlativo único (ej. `RC-20260522-1`, `RC-20260522-2`).\n\n### Diferencia con `/close-day-summary`\nEste endpoint cierra **HOY** automáticamente y además dispara polling de tickets en curso. `/close-day-summary` permite especificar otra fecha. Usa este si querés el caso típico \"cerrar lo de hoy ya mismo\".",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cierre disparado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string",
                      "example": "Cierre del día disparado para 10738832090: 6 boletas pendientes consolidadas en 1 Resumen Diario."
                    },
                    "pending_count": {
                      "type": "integer",
                      "example": 6
                    },
                    "date": {
                      "type": "string",
                      "format": "date"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/generate-daily-summary": {
      "post": {
        "tags": [
          "Resúmenes Diarios (Boletas)"
        ],
        "summary": "Generar Resumen Diario (Modo Manual)",
        "description": "**Casos Lógicos de SUNAT integrados:**\n\nPermite enviar a SUNAT un agrupamiento personalizado de boletas o notas relacionadas, cumpliendo las reglas tributarias de enviar la data consolidada. Deben reportarse **antes de las 12 PM del día siguiente**.\n\n### Casos Lógicos SUNAT Soportados:\n1. **Emisión Normal (estado=1):** Agrupa decenas de boletas válidas en una sola llamada.\n2. **Anulación de Boleta (estado=3):** Se usa para declarar que una boleta que **ya se comunicó en un resumen previo** o en este mismo, fue dada de baja el mismo día.\n3. **Operaciones Mixtas:** El resumen soporta sumar boletas que tienen Inafectaciones o Exoneraciones separando las bases imponibles adecuadamente.\n\n**Operaciones gratuitas:** informe `documents[].gratuitas_gravadas`, `gratuitas_exoneradas`, `gratuitas_inafectas` y `igv_gratuitas` por separado. El XML usa códigos 06/07/08 y tributo 9996. `igv` contiene solo el impuesto de ventas cobradas y `total` el importe por cobrar (cero en cortesía completa). Informe la tasa original en `porcentaje_igv`. No agregue el IGV gratuito a `igv`. Los resúmenes automáticos calculan este desglose desde los ítems originales.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "UUID estable por operación. Conserva exactamente la llave y JSON al reintentar. 409 si cambian los datos o sigue en proceso.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "examples": {
                "Caso 1: Resumen Básico": {
                  "summary": "Boletas Normales (Estado 1)",
                  "value": {
                    "date": "2023-10-15",
                    "documents": [
                      {
                        "tipo_doc": "03",
                        "serie_numero": "B001-1",
                        "estado": "1",
                        "cliente_tipo_doc": "1",
                        "cliente_numero": "12345678",
                        "total": 100.0,
                        "gravadas": 84.75,
                        "igv": 15.25
                      }
                    ]
                  }
                },
                "Caso 2: Resumen con Anulación": {
                  "summary": "Anular Boleta (Estado 3)",
                  "value": {
                    "date": "2023-10-15",
                    "documents": [
                      {
                        "tipo_doc": "03",
                        "serie_numero": "B001-4",
                        "estado": "3",
                        "cliente_tipo_doc": "1",
                        "cliente_numero": "11223344",
                        "total": 0.0,
                        "gravadas": 0.0,
                        "igv": 0.0
                      }
                    ]
                  }
                },
                "Resumen diario": {
                  "summary": "Resumen diario — cambia fecha y correlativo",
                  "value": {
                    "date": "2026-11-07",
                    "documents": [
                      {
                        "tipo_doc": "03",
                        "serie_numero": "BT01-1",
                        "estado": "1",
                        "cliente_tipo_doc": "1",
                        "cliente_numero": "12345678",
                        "total": 118,
                        "gravadas": 100,
                        "igv": 18,
                        "porcentaje_igv": 18
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "El documento ha sido enviado y SUNAT retorna un 'ticket'. \n**OJO:** La respuesta indica 'success: true' y el 'ticket'. El proceso en SUNAT es asíncrono."
          },
          "409": {
            "description": "Llave de idempotencia en uso o contenido distinto."
          }
        }
      }
    },
    "/api/sunat/{ruc}/get-status-summary": {
      "post": {
        "tags": [
          "Resúmenes Diarios (Boletas)"
        ],
        "summary": "Consultar Ticket de Resumen (Asíncrono)",
        "description": "**Caso Lógico: Verificación Asíncrona Ticket RC**\n\nSUNAT nunca responde inmediatamente al enviar un Resumen Diario, sino que te entrega un N° Ticket. SUNAT tarda entre **5 minutos y 2 horas** en terminar de procesarlo.\nEste endpoint verifica el estado del Ticket. Retornará el CDR si ya fue procesado a tiempo, o un Error 98 de 'Procesamiento en progreso'.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "examples": {
                "Consultar Ticket": {
                  "summary": "Chequear estado en SUNAT",
                  "value": {
                    "ticket": "202310150001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estado del documento consultado. Si está en proceso, `pending: true`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "pending": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "true si SUNAT aún está procesando (código 98)."
                    },
                    "response": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "integer",
                          "example": 0,
                          "description": "0 = aceptado, 99 = rechazado, 98 = en proceso."
                        },
                        "status": {
                          "type": "string",
                          "example": "ACEPTADA"
                        },
                        "description": {
                          "type": "string"
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Observaciones SUNAT (no invalidan el documento)."
                        }
                      }
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "error": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "SUNAT aún está procesando el documento (código 98, pending: true).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "pending": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "true si SUNAT aún está procesando (código 98)."
                    },
                    "response": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "integer",
                          "example": 0,
                          "description": "0 = aceptado, 99 = rechazado, 98 = en proceso."
                        },
                        "status": {
                          "type": "string",
                          "example": "ACEPTADA"
                        },
                        "description": {
                          "type": "string"
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Observaciones SUNAT (no invalidan el documento)."
                        }
                      }
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "error": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "object",
                          "nullable": true,
                          "description": "Sólo presente en errores de validación de entrada."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/generate-despatch": {
      "post": {
        "tags": [
          "Guías de Remisión"
        ],
        "summary": "Emitir Guía de Remisión Remitente",
        "description": "Genera una Guía de Remisión Remitente Electrónica (GRE) y la envía a SUNAT.\n\n**Modalidades de traslado (`mod_traslado`):**\n- `01` — Transporte Público: el traslado lo hace una empresa de transporte contratada. Requiere `envio.transportista` (RUC real). NO lleva `vehiculo` ni `choferes`.\n- `02` — Transporte Privado: el remitente traslada con vehículo propio. Requiere `envio.vehiculo` y `envio.choferes`. NO lleva `transportista`.\n\n**Destinatario:** debe identificarse con DNI (`tipo_doc=1`), Carnet de Extranjería (`tipo_doc=4`) o RUC real (`tipo_doc=6`). No se permite consumidor final ni RUCs inválidos (error SUNAT 2758).\n\nEl envío es asíncrono: recibirás un `transaction_id`. El estado final (`ticket_received` → `success`) se actualiza automáticamente cada 5 minutos.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "description": "El RUC de la empresa emisora.",
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "UUID estable por operación. Conserva exactamente la llave y JSON al reintentar. 409 si cambian los datos o sigue en proceso.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "examples": {
                "Transporte Público (mod_traslado 01)": {
                  "summary": "Guía con empresa de transporte contratada",
                  "value": {
                    "serie": "T001",
                    "correlativo": "00000001",
                    "fecha_emision": "2026-05-30",
                    "destinatario": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "EMPRESA DESTINATARIA S.A.C."
                    },
                    "envio": {
                      "cod_traslado": "01",
                      "mod_traslado": "01",
                      "fec_traslado": "2026-05-30",
                      "des_traslado": "Venta",
                      "peso_total": 150.5,
                      "und_peso_total": "KGM",
                      "llegada": {
                        "ubigueo": "150101",
                        "direccion": "AV. LIMA 123, LIMA"
                      },
                      "partida": {
                        "ubigueo": "150101",
                        "direccion": "AV. AREQUIPA 456, LIMA"
                      },
                      "transportista": {
                        "tipo_doc": "6",
                        "num_doc": "20300000003",
                        "rzn_social": "TRANSPORTES NACIONAL S.A.C.",
                        "nro_mtc": "2025-MTC-001234"
                      }
                    },
                    "items": [
                      {
                        "codigo": "PROD001",
                        "descripcion": "Cajas de producto terminado",
                        "unidad": "NIU",
                        "cantidad": 10
                      }
                    ]
                  }
                },
                "Transporte Privado (mod_traslado 02)": {
                  "summary": "Guía con vehículo y chofer propio",
                  "value": {
                    "serie": "T002",
                    "correlativo": "00000001",
                    "fecha_emision": "2026-05-30",
                    "destinatario": {
                      "tipo_doc": "1",
                      "num_doc": "12345678",
                      "rzn_social": "JUAN CARLOS PEREZ GOMEZ"
                    },
                    "envio": {
                      "cod_traslado": "01",
                      "mod_traslado": "02",
                      "fec_traslado": "2026-05-30",
                      "des_traslado": "Venta",
                      "peso_total": 50.0,
                      "und_peso_total": "KGM",
                      "llegada": {
                        "ubigueo": "180302",
                        "direccion": "JR. COMERCIO 100, TRUJILLO"
                      },
                      "partida": {
                        "ubigueo": "130101",
                        "direccion": "AV. INDUSTRIAL 200, LIMA"
                      },
                      "vehiculo": {
                        "placa": "ABC123"
                      },
                      "choferes": [
                        {
                          "tipo": "Principal",
                          "tipo_doc": "1",
                          "nro_doc": "45678901",
                          "nombres": "PEDRO ANTONIO",
                          "apellidos": "SILVA MARTINEZ",
                          "licencia": "Q45678901"
                        }
                      ]
                    },
                    "items": [
                      {
                        "codigo": "VIGA001",
                        "descripcion": "Viga de acero 8m",
                        "unidad": "NIU",
                        "cantidad": 5
                      }
                    ]
                  }
                },
                "Transporte Privado - Múltiples Choferes": {
                  "summary": "Guía privada con chofer principal y secundario (relevo)",
                  "value": {
                    "serie": "T002",
                    "correlativo": "00000002",
                    "fecha_emision": "2026-05-30",
                    "destinatario": {
                      "tipo_doc": "6",
                      "num_doc": "20602284523",
                      "rzn_social": "EMPRESA RECEPTORA E.I.R.L."
                    },
                    "envio": {
                      "cod_traslado": "01",
                      "mod_traslado": "02",
                      "fec_traslado": "2026-05-30",
                      "des_traslado": "Venta",
                      "peso_total": 2500.0,
                      "und_peso_total": "KGM",
                      "num_bultos": 20,
                      "llegada": {
                        "ubigueo": "040101",
                        "direccion": "AV. EJERCITO 300, AREQUIPA"
                      },
                      "partida": {
                        "ubigueo": "130101",
                        "direccion": "AV. INDUSTRIAL 200, LIMA"
                      },
                      "vehiculo": {
                        "placa": "XYZ789"
                      },
                      "choferes": [
                        {
                          "tipo": "Principal",
                          "tipo_doc": "1",
                          "nro_doc": "45678901",
                          "nombres": "PEDRO ANTONIO",
                          "apellidos": "SILVA MARTINEZ",
                          "licencia": "Q45678901"
                        },
                        {
                          "tipo": "Secundario",
                          "tipo_doc": "1",
                          "nro_doc": "56789012",
                          "nombres": "ROBERTO JESUS",
                          "apellidos": "DIAZ FERNANDEZ",
                          "licencia": "Q56789012"
                        }
                      ]
                    },
                    "items": [
                      {
                        "codigo": "MAT001",
                        "descripcion": "Materiales de construcción",
                        "unidad": "KGM",
                        "cantidad": 2500
                      }
                    ]
                  }
                },
                "Guía de remisión": {
                  "summary": "Guía de remisión — cambia fecha y correlativo",
                  "value": {
                    "serie": "T001",
                    "correlativo": "00000001",
                    "fecha_emision": "2026-11-07",
                    "destinatario": {
                      "tipo_doc": "6",
                      "num_doc": "20123456789",
                      "rzn_social": "EMPRESA DESTINATARIA S.A.C."
                    },
                    "envio": {
                      "cod_traslado": "01",
                      "mod_traslado": "01",
                      "fec_traslado": "2026-11-07",
                      "des_traslado": "Venta",
                      "peso_total": 150.5,
                      "und_peso_total": "KGM",
                      "llegada": {
                        "ubigueo": "150101",
                        "direccion": "AV. LIMA 123, LIMA"
                      },
                      "partida": {
                        "ubigueo": "150101",
                        "direccion": "AV. AREQUIPA 456, LIMA"
                      },
                      "transportista": {
                        "tipo_doc": "6",
                        "num_doc": "20300000003",
                        "rzn_social": "TRANSPORTES NACIONAL S.A.C.",
                        "nro_mtc": "2025-MTC-001234"
                      }
                    },
                    "items": [
                      {
                        "codigo": "PROD001",
                        "descripcion": "Cajas de producto terminado",
                        "unidad": "NIU",
                        "cantidad": 10
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Documento aceptado internamente y encolado para SUNAT (asíncrono).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "status": {
                      "type": "string",
                      "example": "ACCEPTED_INTERNAL"
                    },
                    "message": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "integer",
                      "example": 1234
                    },
                    "performance": {
                      "type": "object",
                      "properties": {
                        "total_time_ms": {
                          "type": "number",
                          "example": 75.58
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "El documento ya existe en SUNAT (enviado previamente). Se devuelven los datos del original.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "transaction_id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "xml_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "response": {
                      "type": "object",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "object",
                          "nullable": true,
                          "description": "Sólo presente en errores de validación de entrada."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite mensual de documentos alcanzado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "LIMIT_EXCEEDED"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Llave de idempotencia en uso o contenido distinto."
          }
        }
      }
    },
    "/api/sunat/{ruc}/get-status-despatch": {
      "post": {
        "tags": [
          "Guías de Remisión"
        ],
        "summary": "Consultar Ticket de Guía (Asíncrono)",
        "description": "Permite consultar el estado de una Guía de Remisión utilizando el número de Ticket retornado por SUNAT tras enviar la guía. \n\n* Si el ticket ya finalizó de procesarse en SUNAT, retornamos el estado de validación.\n* Si SUNAT aún lo está procesando, devuelves un estatus indicando que esperes.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "examples": {
                "Consultar Guía": {
                  "value": {
                    "ticket": "164283819-20260401"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estado del documento consultado. Si está en proceso, `pending: true`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "pending": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "true si SUNAT aún está procesando (código 98)."
                    },
                    "response": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "integer",
                          "example": 0,
                          "description": "0 = aceptado, 99 = rechazado, 98 = en proceso."
                        },
                        "status": {
                          "type": "string",
                          "example": "ACEPTADA"
                        },
                        "description": {
                          "type": "string"
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Observaciones SUNAT (no invalidan el documento)."
                        }
                      }
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "error": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "SUNAT aún está procesando el documento (código 98, pending: true).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "pending": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "true si SUNAT aún está procesando (código 98)."
                    },
                    "response": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "integer",
                          "example": 0,
                          "description": "0 = aceptado, 99 = rechazado, 98 = en proceso."
                        },
                        "status": {
                          "type": "string",
                          "example": "ACEPTADA"
                        },
                        "description": {
                          "type": "string"
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Observaciones SUNAT (no invalidan el documento)."
                        }
                      }
                    },
                    "cdr_path": {
                      "type": "string",
                      "nullable": true
                    },
                    "error": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "object",
                          "nullable": true,
                          "description": "Sólo presente en errores de validación de entrada."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/download/xml/{filename}": {
      "get": {
        "tags": [
          "Panel de Descargas de Archivos"
        ],
        "summary": "Descargar XML Firmado",
        "description": "Descarga el archivo XML tributario canónico, incluyendo la firma digital, que fue enviado a SUNAT para el comprobante especificado por su *filename* (ej. `20123456789-01-F001-1`).",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789-01-F001-1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El archivo XML se transfiere como Attachment."
          }
        }
      }
    },
    "/api/sunat/{ruc}/download/cdr/{filename}": {
      "get": {
        "tags": [
          "Panel de Descargas de Archivos"
        ],
        "summary": "Descargar CDR (Constancia SUNAT)",
        "description": "Descarga el archivo ZIP original que contiene el CDR (Constancia de Recepción) emitido por SUNAT en respuesta al comprobante.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789-01-F001-1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "El archivo ZIP se transfiere como Attachment."
          }
        }
      }
    },
    "/api/sunat/{ruc}/download/pdf/{filename}": {
      "get": {
        "tags": [
          "Panel de Descargas de Archivos"
        ],
        "summary": "Descargar PDF A4/Ticket",
        "description": "💡 **Nota:** Esta característica requiere que el módulo de Generación de PDFs (`pdf.feature`) esté activado para tu plan en el Facturador.\n\nRetorna la representación impresa oficial del comprobante. Puede configurarse el formato de salida mediante query params (según implementación).",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789-01-F001-1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Retorna el stream del PDF."
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions/{id}/retry": {
      "post": {
        "tags": [
          "Operaciones Auxiliares y Recuperación ante Fallos"
        ],
        "summary": "Reintentar Transacción",
        "description": "Si SUNAT tuvo una caída global (Errores 500) o un timeout repentino al momento de emitir tu comprobante, su estado en el Shard quedó como `error_retryable`. Usa este endpoint para decirle al motor que trate de reenviar el XML pre-firmado. \nSi reintentar un documento no es viable sintácticamente (ej. Error de RUC no existe), el Shard rechazará la petición.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID interno de la transacción UUID/Numeric en el Shard.",
            "schema": {
              "type": "string",
              "example": "123"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resultado del reintento. `success: true` si el documento fue aceptado por SUNAT o encolado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "description": "Objeto transacción actualizado."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación (estructura inválida o reglas de negocio SUNAT).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "object",
                          "nullable": true,
                          "description": "Sólo presente en errores de validación de entrada."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions/sync-status": {
      "post": {
        "tags": [
          "Sincronización Pull (Reemplaza Webhooks)"
        ],
        "summary": "Consultar estado de N documentos en batch",
        "description": "**El endpoint principal del nuevo flujo.** En lugar de esperar webhooks, tu ERP llama acá cuando quiere reconciliar.\n\nAcepta hasta 500 IDs por request. Devuelve el estado actual de cada uno incluyendo CDR, ticket y un `normalized_state` apto para mapear directo a tu campo `status` local.\n\n**Cuándo llamarlo (recomendado):**\n- Cada 5 min vía cron de tu ERP.\n- Cuando el operador presiona \"Sincronizar con SUNAT\" en tu UI.\n- Después de cerrar caja.\n- Al arrancar tu app después de un downtime para recuperar lo que se procesó mientras estabas caído.\n\nIdempotente: llámalo tantas veces como quieras, sin efectos secundarios.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "invoice_ids": {
                    "type": "array",
                    "description": "IDs de tu lado (los que enviaste como external_reference.invoice_id al generate-*).",
                    "items": {
                      "type": "integer"
                    },
                    "maxItems": 500
                  },
                  "transaction_ids": {
                    "type": "array",
                    "description": "IDs internos del facturador (sunat_transactions.id). Alternativo a invoice_ids.",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "document_numbers": {
                    "type": "array",
                    "description": "Buscar por número visible (ej. BE01-00001851). Alternativo.",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "examples": {
                "Sync típico por invoice_ids": {
                  "summary": "Pasando tus IDs locales",
                  "value": {
                    "invoice_ids": [
                      2031,
                      2032,
                      2033
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lista con el estado actual de cada documento.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "transaction_id": {
                            "type": "integer"
                          },
                          "invoice_id": {
                            "type": "integer",
                            "description": "Tu ID original (eco)"
                          },
                          "hotel_id": {
                            "type": "integer"
                          },
                          "document_type": {
                            "type": "string"
                          },
                          "document_number": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "Estado interno: pending|processing|summary_sent|success|failed|expired|error"
                          },
                          "normalized_state": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "accepted",
                              "observed",
                              "rejected",
                              "expired",
                              "error"
                            ],
                            "description": "observed: SUNAT emitió CDR pero con observaciones — el documento no queda registrado limpio; corrige los datos y reenvía. error: revisa will_retry antes de reemitir."
                          },
                          "will_retry": {
                            "type": "boolean",
                            "description": "true cuando normalized_state es error pero el motor lo reintentará solo (error temporal de SUNAT o de red). En ese caso NO reemitas el comprobante: si el reintento prospera quedarían dos para la misma venta. Solo con will_retry=false el error es definitivo."
                          },
                          "sunat_response_code": {
                            "type": "string"
                          },
                          "sunat_response_description": {
                            "type": "string"
                          },
                          "ticket": {
                            "type": "string",
                            "description": "Ticket de SUNAT para RC/RA (asincrónicos)."
                          },
                          "cdr_path": {
                            "type": "string"
                          },
                          "xml_path": {
                            "type": "string"
                          },
                          "processed_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/close-day-summary": {
      "post": {
        "tags": [
          "Resúmenes Diarios (Boletas)"
        ],
        "summary": "Cerrar el día y consolidar boletas en UN Resumen Diario",
        "description": "Fuerza el cierre del día indicado: consolida TODAS las boletas pendientes de la fecha en UN solo Resumen Diario por empresa.\n\nEl facturador igual lo ejecuta automáticamente a las 23:55 hora Perú, pero este endpoint permite forzar el cierre antes (ej. cuando tu hotel cierra caja a las 22:00).\n\nIdempotente: si no hay boletas pendientes responde `pending_count: 0` sin llamar a SUNAT.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "date": {
                    "type": "string",
                    "format": "date",
                    "description": "Y-m-d. Default: hoy en America/Lima."
                  }
                }
              },
              "examples": {
                "Cerrar el día corriente": {
                  "value": {}
                },
                "Cerrar una fecha específica": {
                  "value": {
                    "date": "2026-05-21"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Cierre disparado. La consolidación corre síncrona y devuelve cuántas boletas se incluyeron.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "pending_count": {
                      "type": "integer"
                    },
                    "date": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/status": {
      "get": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Estado de la Empresa",
        "description": "Consulta en tiempo real si la empresa puede emitir comprobantes electrónicos: si tiene certificado vigente, credenciales SOL configuradas y está activa. Úsalo antes de facturar para mostrarle al operador por qué la emisión podría estar bloqueada (`emission_blocked_reasons`).",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estado obtenido correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "description": "Estado completo de la empresa para emisión de comprobantes.",
                      "properties": {
                        "ruc": {
                          "type": "string",
                          "example": "20123456789"
                        },
                        "name": {
                          "type": "string"
                        },
                        "commercial_name": {
                          "type": "string",
                          "nullable": true
                        },
                        "address": {
                          "type": "string"
                        },
                        "sol_user": {
                          "type": "string",
                          "nullable": true
                        },
                        "sunat_client_id": {
                          "type": "string",
                          "nullable": true
                        },
                        "notification_email": {
                          "type": "string",
                          "nullable": true
                        },
                        "notify_days_before_expiry": {
                          "type": "integer",
                          "nullable": true
                        },
                        "monthly_document_limit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "is_active": {
                          "type": "boolean"
                        },
                        "is_production": {
                          "type": "boolean"
                        },
                        "status": {
                          "type": "string",
                          "example": "active"
                        },
                        "has_certificate": {
                          "type": "boolean"
                        },
                        "certificate_expires_at": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "is_certificate_expired": {
                          "type": "boolean"
                        },
                        "is_certificate_expiring_soon": {
                          "type": "boolean"
                        },
                        "days_until_certificate_expires": {
                          "type": "integer",
                          "nullable": true
                        },
                        "has_sol_credentials": {
                          "type": "boolean"
                        },
                        "can_emit_invoices": {
                          "type": "boolean"
                        },
                        "emission_blocked_reasons": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Lista de razones legibles por las que la empresa no puede emitir (vacía si puede)."
                        },
                        "api_key": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "RUC_MISMATCH"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno al obtener el estado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "STATUS_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/settings": {
      "put": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Actualizar Configuración de la Empresa",
        "description": "Actualiza credenciales SOL, datos de contacto, el ambiente (producción/sandbox) o límites de la empresa, sin pasar por soporte. Solo se modifican los campos enviados. Si actualizas `sol_password`, `sol_user` o `sunat_client_secret`, también se limpia cualquier bloqueo previo por error de autenticación con SUNAT (asumiendo que corregiste el problema).",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Todos los campos son opcionales; se actualizan solo los presentes en el body.",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "commercial_name": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "address": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "sol_user": {
                    "type": "string",
                    "maxLength": 50,
                    "nullable": true
                  },
                  "sol_password": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "is_production": {
                    "type": "boolean"
                  },
                  "notification_email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "sunat_client_id": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "sunat_client_secret": {
                    "type": "string",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "notify_days_before_expiry": {
                    "type": "integer",
                    "minimum": 1,
                    "nullable": true
                  },
                  "monthly_document_limit": {
                    "type": "integer",
                    "minimum": 0,
                    "nullable": true
                  },
                  "certificate_expires_at": {
                    "type": "string",
                    "format": "date",
                    "nullable": true
                  }
                }
              },
              "examples": {
                "Actualizar credenciales SOL": {
                  "value": {
                    "sol_user": "MODDATOS",
                    "sol_password": "moddatos"
                  }
                },
                "Pasar a producción": {
                  "value": {
                    "is_production": true,
                    "notification_email": "facturacion@miempresa.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Configuración actualizada correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Configuración actualizada correctamente"
                    },
                    "data": {
                      "type": "object",
                      "description": "Estado completo de la empresa para emisión de comprobantes.",
                      "properties": {
                        "ruc": {
                          "type": "string",
                          "example": "20123456789"
                        },
                        "name": {
                          "type": "string"
                        },
                        "commercial_name": {
                          "type": "string",
                          "nullable": true
                        },
                        "address": {
                          "type": "string"
                        },
                        "sol_user": {
                          "type": "string",
                          "nullable": true
                        },
                        "sunat_client_id": {
                          "type": "string",
                          "nullable": true
                        },
                        "notification_email": {
                          "type": "string",
                          "nullable": true
                        },
                        "notify_days_before_expiry": {
                          "type": "integer",
                          "nullable": true
                        },
                        "monthly_document_limit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "is_active": {
                          "type": "boolean"
                        },
                        "is_production": {
                          "type": "boolean"
                        },
                        "status": {
                          "type": "string",
                          "example": "active"
                        },
                        "has_certificate": {
                          "type": "boolean"
                        },
                        "certificate_expires_at": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "is_certificate_expired": {
                          "type": "boolean"
                        },
                        "is_certificate_expiring_soon": {
                          "type": "boolean"
                        },
                        "days_until_certificate_expires": {
                          "type": "integer",
                          "nullable": true
                        },
                        "has_sol_credentials": {
                          "type": "boolean"
                        },
                        "can_emit_invoices": {
                          "type": "boolean"
                        },
                        "emission_blocked_reasons": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Lista de razones legibles por las que la empresa no puede emitir (vacía si puede)."
                        },
                        "api_key": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación en los campos enviados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Validation error"
                    },
                    "errors": {
                      "type": "object",
                      "description": "Errores por campo, formato estándar de Laravel."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Internal error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/certificate": {
      "post": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Subir Certificado Digital",
        "description": "Sube el certificado digital `.p12`/`.pfx` (máximo 2MB) que la empresa usará para firmar sus comprobantes ante SUNAT. Si se sube correctamente, la empresa se activa automáticamente (`status: active`) y el Shard extrae la fecha de expiración del certificado para las alertas de vencimiento.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "certificate": {
                    "type": "string",
                    "format": "binary",
                    "description": "Archivo del certificado digital, extensión .p12 o .pfx."
                  },
                  "password": {
                    "type": "string",
                    "description": "Contraseña del certificado digital."
                  }
                },
                "required": [
                  "certificate",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Certificado subido y aplicado correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string",
                      "example": "Certificado subido correctamente"
                    },
                    "data": {
                      "type": "object",
                      "description": "Estado completo de la empresa para emisión de comprobantes.",
                      "properties": {
                        "ruc": {
                          "type": "string",
                          "example": "20123456789"
                        },
                        "name": {
                          "type": "string"
                        },
                        "commercial_name": {
                          "type": "string",
                          "nullable": true
                        },
                        "address": {
                          "type": "string"
                        },
                        "sol_user": {
                          "type": "string",
                          "nullable": true
                        },
                        "sunat_client_id": {
                          "type": "string",
                          "nullable": true
                        },
                        "notification_email": {
                          "type": "string",
                          "nullable": true
                        },
                        "notify_days_before_expiry": {
                          "type": "integer",
                          "nullable": true
                        },
                        "monthly_document_limit": {
                          "type": "integer",
                          "nullable": true
                        },
                        "is_active": {
                          "type": "boolean"
                        },
                        "is_production": {
                          "type": "boolean"
                        },
                        "status": {
                          "type": "string",
                          "example": "active"
                        },
                        "has_certificate": {
                          "type": "boolean"
                        },
                        "certificate_expires_at": {
                          "type": "string",
                          "format": "date",
                          "nullable": true
                        },
                        "is_certificate_expired": {
                          "type": "boolean"
                        },
                        "is_certificate_expiring_soon": {
                          "type": "boolean"
                        },
                        "days_until_certificate_expires": {
                          "type": "integer",
                          "nullable": true
                        },
                        "has_sol_credentials": {
                          "type": "boolean"
                        },
                        "can_emit_invoices": {
                          "type": "boolean"
                        },
                        "emission_blocked_reasons": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Lista de razones legibles por las que la empresa no puede emitir (vacía si puede)."
                        },
                        "api_key": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validación manual del archivo: falta el archivo, extensión inválida (no .p12/.pfx), pesa más de 2MB, o falta la contraseña.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Validation error"
                    },
                    "errors": {
                      "type": "object",
                      "description": "Ej. {\"certificate\": [\"El certificado debe ser un archivo .p12 o .pfx\"]} o {\"password\": [\"La contraseña del certificado es requerida\"]}."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "Internal error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/queue-voided": {
      "post": {
        "tags": [
          "Anulaciones y Bajas"
        ],
        "summary": "Pre-registrar Comunicación de Baja (En Cola)",
        "description": "Registra una Comunicación de Baja (RA) en estado `pending_summary` sin enviarla todavía a SUNAT: queda visible de inmediato en `/transactions`, pero recién se despacha en el cierre del día (`close-day-summary`) o al forzar el envío (`transactions/force-summaries`). Útil cuando quieres anular boletas ya emitidas sin disparar un envío inmediato a SUNAT.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "UUID estable por operación. Conserva exactamente la llave y JSON al reintentar. 409 si cambian los datos o sigue en proceso.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "documents": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "tipo_doc": {
                          "type": "string",
                          "description": "Tipo de documento a dar de baja (ej. \"01\" Factura)."
                        },
                        "serie": {
                          "type": "string"
                        },
                        "correlativo": {
                          "type": "string"
                        },
                        "motivo_baja": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "tipo_doc",
                        "serie",
                        "correlativo",
                        "motivo_baja"
                      ]
                    }
                  },
                  "date": {
                    "type": "string",
                    "format": "date",
                    "description": "Fecha de comunicación de la baja (YYYY-MM-DD)."
                  },
                  "external_reference": {
                    "type": "array",
                    "nullable": true,
                    "description": "Referencias externas libres para mapear con tus propios IDs."
                  }
                },
                "required": [
                  "documents",
                  "date"
                ]
              },
              "examples": {
                "Baja en cola": {
                  "value": {
                    "date": "2026-03-25",
                    "documents": [
                      {
                        "tipo_doc": "01",
                        "serie": "F012",
                        "correlativo": "2519",
                        "motivo_baja": "ERROR VENTA CANCELADA POR CLIENTE"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "RA pre-registrado y encolado — se enviará a SUNAT recién en el cierre del día.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "status": {
                      "type": "string",
                      "example": "QUEUED"
                    },
                    "message": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "integer"
                    },
                    "serie": {
                      "type": "string",
                      "example": "RA-20260325"
                    },
                    "correlativo": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Error de validación en los datos de entrada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "VALIDATION_ERROR"
                        },
                        "details": {
                          "type": "object"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INTERNAL_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Llave de idempotencia en uso o contenido distinto."
          }
        }
      }
    },
    "/api/sunat/{ruc}/pending-summary-dates": {
      "get": {
        "tags": [
          "Resúmenes Diarios (Boletas)"
        ],
        "summary": "Fechas con Boletas Pendientes de Resumen",
        "description": "Devuelve las fechas de emisión (con su conteo) de boletas y notas (03/07/08) que están en `pending_summary`, esperando ser consolidadas en un Resumen Diario. Pensado para que el panel de \"Cerrar Día\" sugiera la fecha correcta en vez de asumir \"hoy\" a ciegas.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fechas pendientes obtenidas correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total de documentos pendientes, sumando todas las fechas."
                    },
                    "dates": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "count": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/documents": {
      "get": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Listar Todos los Documentos",
        "description": "Lista los archivos generados para la empresa (XML, CDR, notas, resúmenes y comunicaciones de baja) agrupados por tipo, con su tamaño y URL de descarga cuando aplica. Útil para construir un explorador de archivos sin conocer de antemano cada nombre de archivo.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listado obtenido correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "ruc": {
                      "type": "string"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "production",
                        "sandbox"
                      ]
                    },
                    "documents": {
                      "type": "object",
                      "properties": {
                        "xmls": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "filename": {
                                "type": "string"
                              },
                              "path": {
                                "type": "string"
                              },
                              "environment": {
                                "type": "string",
                                "enum": [
                                  "production",
                                  "sandbox"
                                ]
                              },
                              "size": {
                                "type": "integer"
                              },
                              "last_modified": {
                                "type": "integer",
                                "description": "Timestamp UNIX de última modificación."
                              },
                              "download_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "Solo presente para tipo `xmls` o `cdrs`; null para el resto."
                              }
                            }
                          }
                        },
                        "cdrs": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "filename": {
                                "type": "string"
                              },
                              "path": {
                                "type": "string"
                              },
                              "environment": {
                                "type": "string",
                                "enum": [
                                  "production",
                                  "sandbox"
                                ]
                              },
                              "size": {
                                "type": "integer"
                              },
                              "last_modified": {
                                "type": "integer",
                                "description": "Timestamp UNIX de última modificación."
                              },
                              "download_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "Solo presente para tipo `xmls` o `cdrs`; null para el resto."
                              }
                            }
                          }
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "filename": {
                                "type": "string"
                              },
                              "path": {
                                "type": "string"
                              },
                              "environment": {
                                "type": "string",
                                "enum": [
                                  "production",
                                  "sandbox"
                                ]
                              },
                              "size": {
                                "type": "integer"
                              },
                              "last_modified": {
                                "type": "integer",
                                "description": "Timestamp UNIX de última modificación."
                              },
                              "download_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "Solo presente para tipo `xmls` o `cdrs`; null para el resto."
                              }
                            }
                          }
                        },
                        "summaries": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "filename": {
                                "type": "string"
                              },
                              "path": {
                                "type": "string"
                              },
                              "environment": {
                                "type": "string",
                                "enum": [
                                  "production",
                                  "sandbox"
                                ]
                              },
                              "size": {
                                "type": "integer"
                              },
                              "last_modified": {
                                "type": "integer",
                                "description": "Timestamp UNIX de última modificación."
                              },
                              "download_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "Solo presente para tipo `xmls` o `cdrs`; null para el resto."
                              }
                            }
                          }
                        },
                        "voided": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "filename": {
                                "type": "string"
                              },
                              "path": {
                                "type": "string"
                              },
                              "environment": {
                                "type": "string",
                                "enum": [
                                  "production",
                                  "sandbox"
                                ]
                              },
                              "size": {
                                "type": "integer"
                              },
                              "last_modified": {
                                "type": "integer",
                                "description": "Timestamp UNIX de última modificación."
                              },
                              "download_url": {
                                "type": "string",
                                "nullable": true,
                                "description": "Solo presente para tipo `xmls` o `cdrs`; null para el resto."
                              }
                            }
                          }
                        }
                      }
                    },
                    "total_files": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "No autorizado para acceder a este RUC.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "UNAUTHORIZED"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno al listar documentos.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "LIST_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/documents/{type}": {
      "get": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Listar Documentos por Tipo",
        "description": "Igual que `/documents`, pero filtrado a un solo tipo de archivo, con metadata legible adicional (`size_human`, `last_modified_date`). Ideal si tu integración solo necesita, por ejemplo, los CDRs.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "type",
            "in": "path",
            "required": true,
            "description": "Tipo de documento a listar.",
            "schema": {
              "type": "string",
              "enum": [
                "xmls",
                "cdrs",
                "notes",
                "summaries",
                "voided"
              ],
              "example": "cdrs"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listado obtenido correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "ruc": {
                      "type": "string"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "production",
                        "sandbox"
                      ]
                    },
                    "type": {
                      "type": "string",
                      "example": "cdrs"
                    },
                    "documents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "filename": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "environment": {
                            "type": "string",
                            "enum": [
                              "production",
                              "sandbox"
                            ]
                          },
                          "size": {
                            "type": "integer"
                          },
                          "size_human": {
                            "type": "string",
                            "example": "12.4 KB"
                          },
                          "last_modified": {
                            "type": "integer"
                          },
                          "last_modified_date": {
                            "type": "string",
                            "example": "2026-03-25 10:15:00"
                          },
                          "download_url": {
                            "type": "string",
                            "nullable": true
                          }
                        }
                      }
                    },
                    "total_files": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "El `type` de la ruta no es uno de los valores válidos.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "INVALID_TYPE"
                        },
                        "message": {
                          "type": "string",
                          "example": "Tipo de documento inválido. Válidos: xmls, cdrs, notes, summaries, voided"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "No autorizado para acceder a este RUC.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "UNAUTHORIZED"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno al listar documentos.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "example": "LIST_ERROR"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions/{id}": {
      "get": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Obtener Transacción por ID",
        "description": "Devuelve el detalle completo (incluyendo `request_data` y `sunat_response` crudos) de una transacción puntual del Shard por su ID interno. Útil para inspeccionar a fondo un documento específico sin traer el listado paginado completo de `/transactions`.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID interno de la transacción en el Shard.",
            "schema": {
              "type": "integer",
              "example": 1234
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transacción encontrada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "object",
                      "description": "Modelo completo de la transacción (todas las columnas de la tabla, incluyendo request_data y sunat_response)."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor. Nota: si el `id` no existe (o no pertenece a esta empresa), también cae acá con un mensaje tipo \"No query results for model [App\\\\Models\\\\SunatTransaction] {id}\" — el endpoint no distingue un 404 de un error real.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions/batch-status": {
      "post": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Estado de Múltiples Transacciones",
        "description": "Consulta el estado actual de varias transacciones a la vez pasando sus IDs internos, evitando N llamadas a `/transactions/{id}`. Ideal para refrescar de un tirón el estado de una tabla completa de documentos en tu ERP.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transaction_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "example": [
                      1234,
                      1235,
                      1236
                    ]
                  }
                },
                "required": [
                  "transaction_ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Estados obtenidos correctamente (IDs que no existen o no pertenecen a la empresa simplemente no aparecen en `data`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "transaction_id": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string"
                          },
                          "document_type": {
                            "type": "string"
                          },
                          "document_number": {
                            "type": "string"
                          },
                          "serie": {
                            "type": "string"
                          },
                          "correlativo": {
                            "type": "string"
                          },
                          "sunat_response": {
                            "type": "object",
                            "nullable": true
                          },
                          "xml_path": {
                            "type": "string",
                            "nullable": true
                          },
                          "cdr_path": {
                            "type": "string",
                            "nullable": true
                          },
                          "processed_at": {
                            "type": "string",
                            "nullable": true,
                            "format": "date-time"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor. Nota: si `transaction_ids` falta o no es válido, este endpoint no devuelve 422 — la excepción de validación cae en el mismo catch genérico y responde acá con `message: \"The given data was invalid.\"`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/summaries": {
      "get": {
        "tags": [
          "Resúmenes Diarios (Boletas)"
        ],
        "summary": "Listar Resúmenes Diarios (RC)",
        "description": "Lista los Resúmenes Diarios (RC) generados por el cierre del día, con el detalle completo de las boletas/notas que agrupó cada uno. A diferencia de `/transactions/sync-status`, este endpoint sirve para *descubrir* resúmenes que el Shard generó por su cuenta — el consumidor nunca tuvo un `transaction_id` propio para ellos.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Filtra resúmenes creados desde esta fecha (inclusive).",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-03-01"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Cantidad máxima de resúmenes a devolver. Se limita a 200 aunque se pida más.",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resúmenes obtenidos correctamente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "transaction_id": {
                            "type": "integer"
                          },
                          "document_number": {
                            "type": "string"
                          },
                          "ticket": {
                            "type": "string",
                            "nullable": true
                          },
                          "normalized_state": {
                            "type": "string",
                            "example": "accepted"
                          },
                          "sunat_response_code": {
                            "type": "string",
                            "nullable": true
                          },
                          "sunat_response_description": {
                            "type": "string",
                            "nullable": true
                          },
                          "fecha_resumen": {
                            "type": "string",
                            "format": "date",
                            "nullable": true
                          },
                          "documentos": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            },
                            "description": "Detalle de boletas/notas que agrupa este resumen."
                          },
                          "xml_path": {
                            "type": "string",
                            "nullable": true
                          },
                          "cdr_path": {
                            "type": "string",
                            "nullable": true
                          },
                          "processed_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/consult-cpe": {
      "post": {
        "tags": [
          "Consultas y Listados"
        ],
        "summary": "Consulta Integrada de Validez (CPE)",
        "description": "Consulta directamente a SUNAT si un comprobante (Factura, Boleta o Nota) existe y está aceptado, usando el servicio de Consulta de Validez de CPE. Útil cuando un cliente reporta no haber recibido su comprobante y quieres verificar su estado real en SUNAT antes de reenviarlo o de investigar más.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tipo_doc": {
                    "type": "string",
                    "enum": [
                      "01",
                      "03",
                      "07",
                      "08"
                    ],
                    "description": "01 Factura, 03 Boleta, 07 Nota de Crédito, 08 Nota de Débito."
                  },
                  "serie": {
                    "type": "string"
                  },
                  "correlativo": {
                    "type": "number"
                  }
                },
                "required": [
                  "tipo_doc",
                  "serie",
                  "correlativo"
                ]
              },
              "examples": {
                "Consultar una factura": {
                  "value": {
                    "tipo_doc": "01",
                    "serie": "F012",
                    "correlativo": 2519
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Consulta ejecutada (revisa `result.success` — SUNAT pudo responder que el comprobante no existe o fue rechazado sin que eso sea un error HTTP).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true,
                      "description": "Indica que la consulta a SUNAT se ejecutó, no que el comprobante sea válido."
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "success": {
                          "type": "boolean",
                          "description": "true si SUNAT confirmó el comprobante."
                        },
                        "status_code": {
                          "type": "string",
                          "example": "0001",
                          "description": "Solo si success=true."
                        },
                        "status_message": {
                          "type": "string",
                          "example": "El comprobante existe y está aceptado",
                          "description": "Solo si success=true."
                        },
                        "error": {
                          "type": "object",
                          "nullable": true,
                          "description": "Solo si success=false.",
                          "properties": {
                            "code": {
                              "type": "string"
                            },
                            "message": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor. Cubre tanto fallos de validación de entrada (mensaje genérico \"The given data was invalid.\") como errores de conexión con el WSDL de SUNAT — este endpoint no distingue uno de otro en el código de estado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/{ruc}/transactions/sync-pending-tickets": {
      "post": {
        "tags": [
          "Operaciones Auxiliares y Recuperación ante Fallos"
        ],
        "summary": "Sincronizar Tickets Pendientes",
        "description": "Dispara manualmente la verificación en SUNAT de los tickets de Resumen Diario y Comunicación de Baja que siguen en curso (`summary_sent` / `processing`), sin generar ni enviar nada nuevo. Útil si no quieres esperar al polling automático programado y necesitas saber ya si un ticket fue aceptado.",
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "20123456789"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verificación ejecutada (el conteo indica cuántos tickets se revisaron, no cuántos cambiaron de estado).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    },
                    "rc_checked": {
                      "type": "integer",
                      "description": "Tickets únicos de Resumen Diario (RC) en curso verificados."
                    },
                    "ra_checked": {
                      "type": "integer",
                      "description": "Comunicaciones de Baja (RA) en curso verificadas."
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El RUC de la ruta no coincide con la empresa asociada a las credenciales.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string",
                      "example": "RUC mismatch"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": false
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sunat/errors": {
      "get": {
        "summary": "Catálogo público de errores SUNAT",
        "security": [],
        "responses": {
          "200": {
            "description": "Códigos, causas y acciones en español."
          }
        }
      }
    },
    "/api/sunat/{ruc}/usage": {
      "get": {
        "summary": "Consumo mensual y pendientes",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{11}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consumo mensual y pendientes"
          },
          "401": {
            "description": "Token inválido"
          },
          "403": {
            "description": "RUC o ambiente no autorizado"
          }
        }
      }
    },
    "/api/sunat/{ruc}/onboarding": {
      "get": {
        "summary": "Progreso real de configuración asistida",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "ruc",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{11}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Progreso real de configuración asistida"
          },
          "401": {
            "description": "Token inválido"
          },
          "403": {
            "description": "RUC o ambiente no autorizado"
          }
        }
      }
    }
  }
}
