swagger: '2.0'
info:
  title: API de Integración con SmartTax
  description: 'API pública de integración con SmartTax para libros electrónicos PLE/SIRE, comparación ERP vs SUNAT y declaración. Autenticación por API key (query "key"). Entornos: la integración se arma y se prueba en UAT (https://api-uat.smarttax.pe/api/v1/sire); producción (https://api.smarttax.pe/api/v1/sire) recién cuando esté validada. El host declarado es el de UAT a propósito, para que las pruebas no salgan contra producción.'
  version: V 1.0.0
host: api-uat.smarttax.pe
basePath: /api/v1/sire
schemes:
- https
consumes:
- application/json
produces:
- application/json
securityDefinitions:
  api_key:
    type: apiKey
    name: key
    in: query
security:
- api_key: []
tags:
- name: Subida de Comprobantes (Individual)
  description: Carga de XML/PDF/IMG/CDR para comprobantes individuales.
- name: Subir Formatos de ERP (PLE / SIRE)
  description: Flujo de signed URL + confirmación de subida + procesamiento.
- name: Comparación de Registros
  description: Ejecución, estado y consulta de la comparación ERP vs SUNAT.
- name: Declaración
  description: Preparación, estado, consulta y envío de declaración a SUNAT.
- name: Registros de ERP (Cliente)
  description: Consulta de registros importados desde ERP.
- name: Registros de SUNAT
  description: Consulta de registros obtenidos desde SUNAT.
- name: Tipo de Cambio
  description: Consulta de tipo de cambio por fecha.
- name: Descarga de Comprobantes (Individual)
  description: Descarga de XML/PDF desde SUNAT.
- name: Descarga de Comprobantes (Detalle)
  description: Detalle de un comprobante y listado de comprobantes recibidos.
x-tagGroups:
- name: Carga y Procesamiento
  tags:
  - Subida de Comprobantes (Individual)
  - Subir Formatos de ERP (PLE / SIRE)
- name: Operación Tributaria
  tags:
  - Comparación de Registros
  - Declaración
- name: Consultas
  tags:
  - Registros de ERP (Cliente)
  - Registros de SUNAT
  - Tipo de Cambio
  - Descarga de Comprobantes (Individual)
  - Descarga de Comprobantes (Detalle)
paths:
  /upload/file:
    post:
      summary: Subir comprobante individual.
      description: 'Servicio para subir comprobantes individuales, recibe: XML, IMG, PDF y CDR. Al menos uno de los campos xml, pdf o image debe estar presente.'
      tags:
      - Subida de Comprobantes (Individual)
      operationId: upload
      consumes:
      - multipart/form-data
      security:
      - api_key: []
      parameters:
      - name: xml
        in: formData
        description: XML file to upload (.xml, .zip)
        required: false
        type: string
        format: binary
      - name: pdf
        in: formData
        description: PDF file to upload (.pdf)
        required: false
        type: string
        format: binary
      - name: image
        in: formData
        description: Image file to upload (.jpg, .jpeg, .png, .bmp, .webp)
        required: false
        type: string
        format: binary
      - name: cdr
        in: formData
        description: ZIP file to upload
        required: false
        type: string
        format: binary
      - name: meta
        in: formData
        description: "{\n  \"number\": \"string\",\n  \"filename\": \"string\",\n  \"document_type_code\": \"string\",\n  \"document_state_code\": \"string\",\n  \"identifier\": \"string\"\n}"
        required: false
        type: string
      - name: elogia-supplier-ruc
        in: header
        required: true
        type: string
        description: RUC del contribuyente (emisor o receptor según el endpoint).
      responses:
        200:
          description: Subida de archivo procesado exitosamente.
          schema:
            $ref: '#/definitions/UploadResponse'
        400:
          description: Solicitud incorrecta. Datos incorrectos.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: No se pudo encontrar el registro.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /upload/generate-upload-url:
    post:
      summary: Genera una URL firmada para subir un archivo a GCS.
      description: Genera una signed URL de subida (PUT).
      tags:
      - Subir Formatos de ERP (PLE / SIRE)
      operationId: generate_upload_url
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/GenerateUploadUrlRequest'
      responses:
        200:
          description: Signed URL generada correctamente.
          schema:
            $ref: '#/definitions/GenerateUploadUrlResponse'
        400:
          description: Solicitud incorrecta (campos faltantes o inválidos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        401:
          description: No autorizado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Prohibido (cuota insuficiente o sin permisos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
        500:
          description: Error interno.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /upload/process-format:
    post:
      summary: Confirma la subida y envía el job a validación/procesamiento.
      description: Confirma que el archivo fue subido a GCS, actualiza el estado del ticket y publica un mensaje en Pub/Sub para iniciar el procesamiento.
      tags:
      - Subir Formatos de ERP (PLE / SIRE)
      operationId: process_format
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ProcessFormatRequest'
      responses:
        200:
          description: Confirmación registrada y procesamiento encolado correctamente.
          schema:
            $ref: '#/definitions/ProcessFormatResponse'
        400:
          description: Solicitud incorrecta (campos faltantes o inválidos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        401:
          description: No autorizado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Prohibido (cuota insuficiente o sin permisos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
        500:
          description: Error interno.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /upload/confirm-process-format:
    post:
      summary: Consulta el estado del procesamiento del archivo importado.
      description: Valida autenticación/cuotas, registra el request y retorna el estado actual del ImportJob (ticket) en base al campo state.
      tags:
      - Subir Formatos de ERP (PLE / SIRE)
      operationId: confirm_process_format
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ConfirmProcessFormatRequest'
      responses:
        200:
          description: Estado obtenido correctamente.
          schema:
            $ref: '#/definitions/ConfirmProcessFormatResponse'
        400:
          description: Solicitud incorrecta (campos faltantes o inválidos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        401:
          description: No autorizado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Prohibido (cuota insuficiente o sin permisos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
        500:
          description: Error interno.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/comparison/execution:
    post:
      tags:
      - Comparación de Registros
      summary: Execute comparison
      description: 'Compares customer records vs SUNAT records. Returns a ticket that can be used to check the execution status.

        '
      operationId: executeComparison
      parameters:
      - name: key
        in: query
        required: true
        type: string
        description: API Key required to access the endpoint.
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ExecuteComparisonRequest'
      security:
      - api_key: []
      responses:
        '200':
          description: Success
          schema:
            $ref: '#/definitions/ExecuteComparisonResponse'
          examples:
            application/json:
              ok: true
              status: 200
              message: success
              data:
                ticket: eea3180d-87ca-4748-befd-ba378c750707
                bookType: RCE
                period: 2026-01
  /taxpayer/comparison/execution/status:
    post:
      tags:
      - Comparación de Registros
      summary: Execution status
      description: 'Checks the execution status using the ticket returned by Execute comparison.

        '
      operationId: comparisonExecutionStatus
      parameters:
      - name: key
        in: query
        required: true
        type: string
        description: API Key required to access the endpoint.
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ExecutionStatusRequest'
      security:
      - api_key: []
      responses:
        '200':
          description: Success
          schema:
            $ref: '#/definitions/ExecutionStatusResponse'
          examples:
            application/json:
              ok: true
              status: 200
              message: Processed successfully.
              data:
                ticket: eea3180d-87ca-4748-befd-ba378c750707
                issuerId: '20123456789'
                period: 2026-01
                bookType: RCE
                state: '2'
  /taxpayer/comparison/execution/query:
    post:
      tags:
      - Comparación de Registros
      summary: Execution query
      description: 'Returns the list of documents and comparison results for the given ticket. Use view to filter the dataset (ALL, SUNAT, CLIENT, DIFF, MATCH). Pagination: do NOT send pageToken on the first request. If meta.hasNext is true, send meta.nextPageToken as pageToken in the next request until hasNext is false.

        '
      operationId: comparisonExecutionQuery
      parameters:
      - name: key
        in: query
        required: true
        type: string
        description: API Key required to access the endpoint.
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ExecutionQueryRequest'
      security:
      - api_key: []
      responses:
        '200':
          description: Success
          schema:
            $ref: '#/definitions/ExecutionQueryResponse'
  /taxpayer/declaration/process:
    post:
      tags:
      - Declaración
      summary: Prepare Declaration (Step 1 — comparison)
      description: 'Validates authentication/quotas, audits the request, resolves or creates the Declaracion record for the given ticket (Comparacion id), and publishes a Pub/Sub job to run the comparison and preliminary preparation (PREPARE_DECLARATION). Supported bookType: RVIE, RCE. Not applicable for RCE-ND (use /declaration/generate-file instead).

        '
      operationId: prepareDeclaration
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/PrepareDeclarationRequest'
      responses:
        200:
          description: Processed successfully.
          schema:
            $ref: '#/definitions/PrepareDeclarationResponse'
          examples:
            application/json:
              success: true
              status: 200
              message: Procesamiento iniciado
              data:
                ticket: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
                bookType: RCE
        400:
          description: Bad request (missing/invalid fields).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Active comparison not found for the given ticket.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Forbidden (quota exceeded / no permissions).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/status:
    post:
      tags:
      - Declaración
      summary: Declaration preparation status
      description: 'Returns the preliminary status for a declaration ticket. States: 0=registered, 1=in progress, 2=prepared successfully, 3=rejected.

        '
      operationId: declarationStatus
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/DeclarationStatusRequest'
      responses:
        200:
          description: Status fetched successfully.
          schema:
            $ref: '#/definitions/DeclarationStatusResponse'
          examples:
            application/json:
              ok: true
              status: 200
              message: success
              data:
                ticket: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
                issuerId: '20123456789'
                period: 2026-01
                bookType: RCE
                preliminary: '2'
                proposal: '1'
                declared: '0'
                active: '1'
                archivoPreliminar: '2'
        400:
          description: Bad request (missing/invalid fields).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Ticket not found.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Forbidden (quota exceeded / no permissions).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error (includes rejected state=3).
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/generate-file:
    post:
      tags:
      - Declaración
      summary: Generate Preliminary File (Step 2 — file generation)
      description: 'Triggers the generation of the preliminary flat file in SUNAT format. Supported bookType: RVIE, RCE, RCE-ND (no domiciliados). For RVIE/RCE: ticket (Declaracion id) is required; the Declaracion must already exist (created by /declaration/process). For RCE-ND: ticket is optional; a new Declaracion is created automatically if it does not exist. Publishes a Pub/Sub job (GENERATE_PRELIMINARY) to the corresponding worker.

        '
      operationId: generatePreliminaryFile
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/GeneratePreliminaryFileRequest'
      responses:
        200:
          description: File generation job enqueued successfully.
          schema:
            $ref: '#/definitions/GeneratePreliminaryFileResponse'
          examples:
            application/json:
              success: true
              status: 200
              message: Generación de archivo iniciada
              data:
                ticket: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
                bookType: RCE-ND
        400:
          description: Bad request (missing/invalid fields).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Declaracion not found for the given ticket (RVIE/RCE only).
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Forbidden (quota exceeded / no permissions).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/query:
    post:
      tags:
      - Declaración
      summary: Declaration query results
      description: 'Returns aggregated rows (documents) for the declaration. view: ALL | MATCH | FIX. Pagination: do NOT send pageToken on the first request. If meta.hasNext is true, send meta.nextPageToken as pageToken in the next request. For bookType RCE-ND, records are not available via this endpoint (returns empty data array).

        '
      operationId: declarationQuery
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/DeclarationQueryRequest'
      responses:
        200:
          description: Rows fetched successfully.
          schema:
            $ref: '#/definitions/DeclarationQueryResponse'
        400:
          description: Bad request (missing/invalid fields / invalid pageToken).
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Forbidden (quota exceeded / no permissions).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/sunat:
    post:
      tags:
      - Declaración
      summary: Send declaration to SUNAT
      description: 'Validates authentication/quotas, writes an audit record, validates that the declaration ticket exists and is active, updates proposal state to "in progress", and publishes a Pub/Sub job to execute SUNAT declaration (SUNAT_DECLARATION). Supports bookType RCE or RVIE.

        '
      operationId: sunatDeclaration
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/SunatDeclarationRequest'
      responses:
        200:
          description: Success
          schema:
            $ref: '#/definitions/SunatDeclarationResponse'
          examples:
            application/json:
              ok: true
              status: 200
              message: success
              data:
                ticket: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
                bookType: RVIE
                period: 2026-01
        400:
          description: Bad request (missing/invalid fields).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Active declaration not found / not prepared for declaration.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Forbidden (quota exceeded / no permissions).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/sunat/file:
    post:
      tags:
      - Declaración
      summary: Get signed URL for declaration file (RCE/RVIE)
      description: 'Returns a signed URL (valid 24 hours) to download the final declaration file stored in GCS. The file path is taken from Declaraciones.filepath using the given ticket (Declaraciones.id).

        '
      operationId: declarationSunatFile
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/DeclarationFileRequest'
      responses:
        200:
          description: Signed URL generated successfully.
          schema:
            $ref: '#/definitions/DeclarationFileResponse'
        400:
          description: Bad request (missing/invalid fields).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Ticket/file not found.
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/sunat/status:
    post:
      tags:
      - Declaración
      summary: SUNAT ticket status
      description: 'Returns the SUNAT response status for a declaration ticket. Looks up the Declaracion by ticket (Declaraciones.id) and returns both the declaration state and the SUNAT ticket result (success, error, connection timeout, etc).

        '
      operationId: sunatTicketStatus
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/SunatTicketStatusRequest'
      responses:
        200:
          description: Status fetched successfully.
          schema:
            $ref: '#/definitions/SunatTicketStatusResponse'
          examples:
            application/json:
              ok: true
              status: 200
              message: success
              data:
                ticket: bda8c472-d0da-4a46-abc9-60da4cccd848
                issuerId: '20123456789'
                period: 2026-04
                bookType: RCE
                preliminary: '2'
                proposal: '1'
                declared: '0'
                active: '1'
                sunatTicketId: 06105fed-b2a9-48a6-9602-c2f94a197a8e
                sunatTicket: null
                sunatState: '3'
                sunatServiceCode: null
                sunatStatusCode: '01'
                sunatProcessCode: '61'
                sunatDescription: 'connection timed out: /34.118.232.41:9091'
                sunatJsonResponse: null
                sunatErrorResponse: null
        400:
          description: Bad request (missing/invalid fields).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Declaration or SunatTicket not found.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Forbidden (quota exceeded / no permissions).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/rvie/{period}:
    get:
      summary: Registros Cliente de Ventas.
      description: Obtiene los registros del cliente con respecto a sus ventas.
      operationId: taxpayer_rvie_records
      tags:
      - Registros de ERP (Cliente)
      parameters:
      - name: period
        in: path
        description: Periodo en formato AAAA-MM.
        required: true
        type: string
        default: 2024-08
      - name: page
        in: query
        description: Pagina que se esta consultando.
        required: true
        type: string
        default: '1'
      - name: perPage
        in: query
        description: Número de registros por página.
        required: true
        type: string
        default: '10'
      - name: issuerId
        in: query
        description: RUC del contribuyente.
        required: true
        type: string
        default: '20123456789'
      - name: tipoDocumento
        in: query
        description: Filtra los registros por el código del tipo de documento. Ej. 01=Facturas, 03=Boletas, 07=Nota de Crédito, 08=Nota de Débito
        required: false
        type: string
      - name: currencyType
        in: query
        description: Filtra los registros por el código de moneda. Ej. PEN=Soles, USD=Dolares
        required: false
        type: string
      - name: textFilter
        in: query
        description: Filtra los registros por N° de receptor, razon social, serie y correlativo.
        required: false
        type: string
      - name: elogia-supplier-ruc
        in: header
        required: true
        type: string
        description: RUC del contribuyente (emisor o receptor según el endpoint).
      responses:
        200:
          description: Registros obtenidos exitosamente.
          schema:
            $ref: '#/definitions/TaxpayerRecordsResponse'
        400:
          description: Solicitud incorrecta. El formato del periodo es incorrecto.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Declaración no encontrada para el periodo especificado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /taxpayer/rce/{period}:
    get:
      summary: Registros Cliente de Compras.
      description: Obtiene los registros del cliente con respecto a sus compras.
      operationId: taxpayer_rce_records
      tags:
      - Registros de ERP (Cliente)
      parameters:
      - name: period
        in: path
        description: Periodo en formato AAAA-MM.
        required: true
        type: string
        default: 2024-08
      - name: page
        in: query
        description: Pagina que se esta consultando.
        required: true
        type: string
        default: '1'
      - name: perPage
        in: query
        description: Número de registros por página.
        required: true
        type: string
        default: '10'
      - name: issuerId
        in: query
        description: RUC del contribuyente.
        required: true
        type: string
        default: '20123456789'
      - name: tipoDocumento
        in: query
        description: Filtra los registros por el código del tipo de documento. Ej. 01=Facturas, 03=Boletas, 07=Nota de Crédito, 08=Nota de Débito
        required: false
        type: string
      - name: currencyType
        in: query
        description: Filtra los registros por el código de moneda. Ej. PEN=Soles, USD=Dolares
        required: false
        type: string
      - name: textFilter
        in: query
        description: Filtra los registros por N° de receptor, razon social, serie y correlativo.
        required: false
        type: string
      - name: elogia-supplier-ruc
        in: header
        required: true
        type: string
        description: RUC del contribuyente (emisor o receptor según el endpoint).
      responses:
        200:
          description: Registros obtenidos exitosamente.
          schema:
            $ref: '#/definitions/TaxpayerRecordsResponse'
        400:
          description: Solicitud incorrecta. El formato del periodo es incorrecto.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Declaración no encontrada para el periodo especificado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /taxpayer/exchange-rate:
    post:
      summary: Obtener tipo de cambio por fecha
      description: Retorna el tipo de cambio (compra/venta) para la fecha consultada y si es día laborable en Perú.
      tags:
      - Tipo de Cambio
      operationId: exchange_rate
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ExchangeRateRequest'
      responses:
        200:
          description: Tipo de cambio obtenido correctamente.
          schema:
            $ref: '#/definitions/ExchangeRateResponse'
        400:
          description: Solicitud incorrecta (campos faltantes o inválidos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        401:
          description: No autorizado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Prohibido (cuota insuficiente o sin permisos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Error interno.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/receipt/details:
    post:
      tags:
      - Descarga de Comprobantes (Detalle)
      summary: Detalle de comprobante
      description: 'Busca el comprobante en RegistrosCliente para devolver XML/PDF/CDR como base64.

        '
      operationId: receiptDetailsQuery
      consumes:
      - application/json
      produces:
      - application/json
      security:
      - api_key: []
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/ReceiptDetailsRequest'
      responses:
        200:
          description: Detalle obtenido correctamente.
          schema:
            $ref: '#/definitions/ReceiptDetailsResponse'
          examples:
            application/json:
              success: true
              status: 200
              message: success
              data:
                documentType: '01'
                series: E001
                number: '1002'
                issuerRuc: '10456789012'
                issuerName: EMPRESA DEMO S.A.C.
                customerRuc: '20000000001'
                customerName: DISTRIBUIDORA DEMO S.R.L.
                issueDate: '2026-01-26'
                period: 2026-01
                currency: PEN
                totalAmount: '118.00'
                taxableAmount: '100.00'
                igvAmount: '18.00'
                sunatStatus: '1'
                observation: ''
                files:
                  xml:
                    exists: true
                    filename: 10456789012-01-E001-00001002.xml
                    contentBase64: PHhtbD4uLi48L3htbD4=
                    contentType: application/xml
                    size: 1234
                    tooLarge: false
                    maxAllowedBytes: 8388608
                    source: gcs
                  pdf:
                    exists: true
                    filename: 10456789012-01-E001-00001002.pdf
                    contentBase64: JVBERi0xLjQKJc...
                    contentType: application/pdf
                    size: 45678
                    tooLarge: false
                    maxAllowedBytes: 8388608
                    source: gcs
                  cdr:
                    exists: false
                    filename: null
                    contentBase64: null
                    contentType: null
                    size: null
                    tooLarge: false
                    maxAllowedBytes: 8388608
                    source: gcs
        400:
          description: Solicitud incorrecta (campos faltantes o inválidos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        401:
          description: No autorizado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        403:
          description: Prohibido (cuota insuficiente o sin permisos).
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Comprobante no encontrado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
        500:
          description: Error interno.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /sunat/rvie/{period}:
    get:
      summary: Registros Sunat de Ventas.
      description: Obtiene los registros de SUNAT con respecto a sus ventas.
      operationId: sunat_rvie_records
      tags:
      - Registros de SUNAT
      parameters:
      - name: period
        in: path
        description: Periodo en formato AAAA-MM.
        required: true
        type: string
        default: 2024-08
      - name: page
        in: query
        description: Pagina que se esta consultando.
        required: true
        type: string
        default: '1'
      - name: perPage
        in: query
        description: Número de registros por página.
        required: true
        type: string
        default: '10'
      - name: issuerId
        in: query
        description: RUC del contribuyente.
        required: true
        type: string
        default: '20123456789'
      - name: tipoDocumento
        in: query
        description: Filtra los registros por el código del tipo de documento. Ej. 01=Facturas, 03=Boletas, 07=Nota de Crédito, 08=Nota de Débito
        required: false
        type: string
      - name: currencyType
        in: query
        description: Filtra los registros por el código de moneda. Ej. PEN=Soles, USD=Dolares
        required: false
        type: string
      - name: textFilter
        in: query
        description: Filtra los registros por N° de receptor, razon social, serie y correlativo.
        required: false
        type: string
      - name: elogia-supplier-ruc
        in: header
        required: true
        type: string
        description: RUC del contribuyente (emisor o receptor según el endpoint).
      responses:
        200:
          description: Registros obtenidos exitosamente.
          schema:
            $ref: '#/definitions/SunatRecordsResponse'
        400:
          description: Solicitud incorrecta. El formato del periodo es incorrecto.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Declaración no encontrada para el periodo especificado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /sunat/rce/{period}:
    get:
      summary: Registros Sunat de Compras.
      description: Obtiene los registros de SUNAT con respecto a sus compras.
      operationId: sunat_rce_records
      tags:
      - Registros de SUNAT
      parameters:
      - name: period
        in: path
        description: Periodo en formato AAAA-MM.
        required: true
        type: string
        default: 2024-08
      - name: page
        in: query
        description: Pagina que se esta consultando.
        required: true
        type: string
        default: '1'
      - name: perPage
        in: query
        description: Número de registros por página.
        required: true
        type: string
        default: '10'
      - name: issuerId
        in: query
        description: RUC del contribuyente.
        required: true
        type: string
        default: '20123456789'
      - name: tipoDocumento
        in: query
        description: Filtra los registros por el código del tipo de documento. Ej. 01=Facturas, 03=Boletas, 07=Nota de Crédito, 08=Nota de Débito
        required: false
        type: string
      - name: currencyType
        in: query
        description: Filtra los registros por el código de moneda. Ej. PEN=Soles, USD=Dolares
        required: false
        type: string
      - name: textFilter
        in: query
        description: Filtra los registros por N° de receptor, razon social, serie y correlativo.
        required: false
        type: string
      - name: elogia-supplier-ruc
        in: header
        required: true
        type: string
        description: RUC del contribuyente (emisor o receptor según el endpoint).
      responses:
        200:
          description: Registros obtenidos exitosamente.
          schema:
            $ref: '#/definitions/SunatRecordsResponse'
        400:
          description: Solicitud incorrecta. El formato del periodo es incorrecto.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: Declaración no encontrada para el periodo especificado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /sunat/rce/received-receipts:
    get:
      summary: Comprobantes recibidos con disponibilidad de archivos.
      description: 'Lista los comprobantes recibidos (RCE/SIRE) del RUC receptor autenticado, filtrando por rango de fecha de emisión (máximo 15 días). Solo incluye facturas y notas de crédito/débito que modifican facturas (excluye notas asociadas a boletas). Por cada comprobante indica si el JSON/PDF/XML ya está disponible para descargar vía /taxpayer/receipt/details.

        '
      operationId: received_receipts_query
      tags:
      - Registros de SUNAT
      parameters:
      - name: fechaDesde
        in: query
        description: Fecha de emisión inicial del rango (AAAA-MM-DD).
        required: true
        type: string
        default: '2024-08-01'
      - name: fechaHasta
        in: query
        description: Fecha de emisión final del rango (AAAA-MM-DD). Máximo 15 días desde fechaDesde.
        required: true
        type: string
        default: '2024-08-15'
      - name: page
        in: query
        description: Pagina que se esta consultando.
        required: false
        type: string
        default: '1'
      - name: perPage
        in: query
        description: Número de registros por página.
        required: false
        type: string
        default: '10'
      - name: issuerId
        in: query
        description: RUC del contribuyente (receptor).
        required: true
        type: string
        default: '20123456789'
      - name: rucProveedor
        in: query
        description: Filtra por RUC del proveedor/emisor.
        required: false
        type: string
      - name: moneda
        in: query
        description: Filtra por código de moneda. Ej. PEN=Soles, USD=Dolares
        required: false
        type: string
      - name: elogia-supplier-ruc
        in: header
        required: true
        type: string
        description: RUC del contribuyente (emisor o receptor según el endpoint).
      responses:
        200:
          description: Comprobantes recibidos obtenidos exitosamente.
          schema:
            $ref: '#/definitions/ReceivedReceiptsResponse'
        400:
          description: Solicitud incorrecta. fechaDesde/fechaHasta faltantes, con formato inválido, o rango mayor a 15 días.
          schema:
            $ref: '#/definitions/ErrorResponse'
        500:
          description: Error interno (token inválido/vencido, sin cuota, etc.).
          schema:
            $ref: '#/definitions/ErrorResponse'
  /sunat/download-xml/{identifier}:
    get:
      summary: Descarga de archivo XML.
      description: Descarga de archivo XML de SUNAT.
      operationId: sunat_download_xml
      tags:
      - Descarga de Comprobantes (Individual)
      produces:
      - application/octet-stream
      parameters:
      - name: identifier
        in: path
        description: 'ID de los registros obtenidos mediante la consulta. Se puede generar con el formato: {RUC}{Tipo Doc}{Serie}{Número}'
        required: true
        type: string
        default: 0000000000001F00100000001
      - name: issuerId
        in: query
        description: RUC del contribuyente.
        required: true
        type: string
        default: '20123456789'
      - name: elogia-supplier-ruc
        in: header
        required: false
        type: string
        description: RUC del contribuyente (alias de issuerId vía header).
      responses:
        200:
          description: Se descargo el archivo correctamente.
        400:
          description: Solicitud incorrecta.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: No encontrado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /sunat/download-pdf/{identifier}:
    get:
      summary: Descarga de archivo PDF.
      description: Descarga de archivo PDF de SUNAT.
      operationId: sunat_download_pdf
      tags:
      - Descarga de Comprobantes (Individual)
      produces:
      - application/pdf
      parameters:
      - name: identifier
        in: path
        description: 'ID de los registros obtenidos mediante la consulta. Se puede generar con el formato: {RUC}{Tipo Doc}{Serie}{Número}'
        required: true
        type: string
        default: 0000000000001F00100000001
      - name: issuerId
        in: query
        description: RUC del contribuyente.
        required: true
        type: string
        default: '20123456789'
      - name: elogia-supplier-ruc
        in: header
        required: false
        type: string
        description: RUC del contribuyente (alias de issuerId vía header).
      responses:
        200:
          description: Se descargo el archivo correctamente.
        400:
          description: Solicitud incorrecta.
          schema:
            $ref: '#/definitions/ErrorResponse'
        404:
          description: No encontrado.
          schema:
            $ref: '#/definitions/ErrorResponse'
        422:
          description: Se encontraron validaciones.
          schema:
            $ref: '#/definitions/ValidationResponse'
  /taxpayer/declaration/delete:
    post:
      tags:
      - Declaración
      summary: Delete preliminary (unblocks a failed declaration)
      description: 'Deletes the preliminary of a declaration with the same effect as the "Eliminar" button of the web platform, so the whole cycle delete → process → generate-file → sunat can be done through the API. Supported bookType: RVIE, RCE, RCE-ND (no domiciliados). `ticket` is the Declaracion id and must belong to `issuerId` (otherwise 403, nothing is deleted). It does NOT require SUNAT to have failed; it only rejects declarations that are in progress or already declared (409). ASYNCHRONOUS: the platform cleanup is done before answering, but the deletion of the preliminary IN SUNAT is queued and executed by an in-cluster worker, so the response is 202 with a requestId. You MUST poll /taxpayer/declaration/delete/status until COMPLETADO before generating the preliminary again: otherwise the regeneration fails with "el registro electronico ... ya ha sido generado".

        '
      operationId: deleteDeclaration
      security:
      - api_key: []
      x-google-quota:
        metricCosts:
          delete-declaration-request: 1
      x-google-backend:
        address: https://stax-delete-declaration-thwjy6dtda-uc.a.run.app
        path_translation: APPEND_PATH_TO_ADDRESS
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/DeleteDeclarationRequest'
      responses:
        '202':
          description: 'Deleted on the platform; the deletion in SUNAT was queued. Poll /taxpayer/declaration/delete/status with the returned requestId.

            '
          schema:
            $ref: '#/definitions/DeleteDeclarationResponse'
          examples:
            application/json:
              success: true
              status: 202
              message: Preliminar eliminado en la plataforma. La baja en SUNAT quedo encolada; consulte el estado antes de regenerar.
              data:
                requestId: 6f2f1a5c-2f2e-4b3a-9a0f-6a1f0f4b7c21
                ticket: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
                bookType: RCE
                period: 2026-01
                issuerId: '20123456789'
                sunat:
                  status: EN_COLA
        '400':
          description: Bad request (missing/invalid fields, or fields that do not match the declaration).
          schema:
            $ref: '#/definitions/ErrorResponse'
        '401':
          description: Unauthorized (token missing, inactive, expired or from another company).
          schema:
            $ref: '#/definitions/ErrorResponse'
        '403':
          description: Forbidden (quota exceeded, or the declaration belongs to another issuerId — nothing is deleted).
          schema:
            $ref: '#/definitions/ErrorResponse'
        '404':
          description: Declaracion not found for the given ticket.
          schema:
            $ref: '#/definitions/ErrorResponse'
        '409':
          description: Already deleted, in progress, or the period was already declared.
          schema:
            $ref: '#/definitions/ErrorResponse'
        '502':
          description: 'Deleted on the platform but the deletion in SUNAT could not be queued. The body carries the reason in data.sunatError. A rejection BY SUNAT is not reported here: it arrives as status ERROR in /delete/status.

            '
          schema:
            $ref: '#/definitions/DeleteDeclarationSunatErrorResponse'
        '500':
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
  /taxpayer/declaration/delete/status:
    post:
      tags:
      - Declaración
      summary: Delete preliminary status
      description: 'Returns the outcome of a deletion requested with /taxpayer/declaration/delete: EN_PROCESO (the deletion in SUNAT is still queued), COMPLETADO (done — the preliminary can be generated again) or ERROR (SUNAT rejected it; the reason comes in sunatError). The requestId must belong to the company of the token (otherwise 403). Poll this endpoint before regenerating the preliminary.

        '
      operationId: deleteDeclarationStatus
      security:
      - api_key: []
      x-google-quota:
        metricCosts:
          delete-declaration-status-request: 1
      x-google-backend:
        address: https://stax-delete-declaration-thwjy6dtda-uc.a.run.app
        path_translation: APPEND_PATH_TO_ADDRESS
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/DeleteDeclarationStatusRequest'
      responses:
        '200':
          description: Current state of the deletion request.
          schema:
            $ref: '#/definitions/DeleteDeclarationStatusResponse'
          examples:
            application/json:
              success: true
              status: 200
              message: El preliminar quedo eliminado. Ya puede regenerarlo.
              data:
                requestId: 6f2f1a5c-2f2e-4b3a-9a0f-6a1f0f4b7c21
                status: COMPLETADO
                requestedAt: '2026-08-27T15:04:05Z'
        '400':
          description: Bad request (requestId missing).
          schema:
            $ref: '#/definitions/ErrorResponse'
        '401':
          description: Unauthorized (token missing, inactive, expired or from another company).
          schema:
            $ref: '#/definitions/ErrorResponse'
        '403':
          description: Forbidden (quota exceeded, or the request belongs to another issuerId).
          schema:
            $ref: '#/definitions/ErrorResponse'
        '404':
          description: No deletion request for the given requestId.
          schema:
            $ref: '#/definitions/ErrorResponse'
        '500':
          description: Internal error.
          schema:
            $ref: '#/definitions/ErrorResponse'
definitions:
  UploadResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      message:
        type: string
        example: Se subio correctamente.
      data:
        type: object
        properties: {}
  GenerateUploadUrlRequest:
    type: object
    required:
    - user
    - email
    - action
    - issuerId
    - erpFormat
    - bookType
    - period
    - deleteExistingRecords
    - contentType
    - fileName
    - fileSizeBytes
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Acción permitida por el servicio.
        enum:
        - UPLOAD_FORMAT
        example: UPLOAD_FORMAT
      issuerId:
        type: string
        description: RUC o identificador del emisor.
        example: '20123456789'
      erpFormat:
        type: string
        description: Formato del archivo a importar.
        enum:
        - PLE
        - SIRE
        example: PLE
      bookType:
        type: string
        description: 'Tipo de libro / conjunto de registros. PLE admite: PURCHASES, SALES, RCE-ND. SIRE admite: RCE, RVIE.'
        enum:
        - PURCHASES
        - SALES
        - RCE
        - RVIE
        - RCE-ND
        example: PURCHASES
      period:
        type: string
        description: Periodo en formato YYYYMM.
        pattern: ^[0-9]{6}$
        example: '202512'
      deleteExistingRecords:
        type: boolean
        description: Si es true, elimina registros existentes antes de importar. Si es false, hace upsert (actualiza/agrega) sin borrar.
        example: false
      contentType:
        type: string
        description: Content-Type del archivo que se subirá.
        example: text/plain
      fileName:
        type: string
        description: Nombre del archivo (se normaliza con basename para evitar path traversal).
        example: PLE2012345678920251000140100001111_011220250906_API.txt
      fileSizeBytes:
        type: integer
        format: int64
        description: Tamaño del archivo en bytes.
        example: 5565
  GenerateUploadUrlResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        $ref: '#/definitions/GenerateUploadUrlResponseData'
  GenerateUploadUrlResponseData:
    type: object
    properties:
      fileName:
        type: string
        example: PLE2012345678920251000140100001111_011220250906_API.txt
      ticket:
        type: string
        description: ID del job creado para el proceso de importación.
        example: ef7741df-4beb-417e-835f-d41c37bc34d2
      erpFormat:
        type: string
        enum:
        - PLE
        - SIRE
        example: PLE
      book_type:
        type: string
        enum:
        - PURCHASES
        - SALES
        - RCE
        - RVIE
        - RCE-ND
        example: PURCHASES
      period:
        type: string
        example: '202512'
      uploadUrl:
        type: string
        description: URL para subir el archivo.
        example: https://storage.googleapis.com/...
      expiresAt:
        type: string
        format: date-time
        description: Fecha/hora de expiración mostrada al usuario.
        example: '2026-01-06T23:35:31.161Z'
      expected:
        type: object
        properties:
          method:
            type: string
            example: PUT
          headers:
            type: object
            properties:
              Content-Type:
                type: string
                example: text/plain
              Content-Length:
                type: integer
                format: int64
                example: 5565
  TaxpayerRecordsResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      message:
        type: string
        example: Registros obtenidos.
      data:
        type: array
        items:
          $ref: '#/definitions/TaxpayerRecord'
      meta:
        $ref: '#/definitions/Meta'
  TaxpayerRecord:
    type: object
    properties:
      id:
        type: string
        example: 0000000000001F00100000001
      idEmisor:
        type: string
        example: '00000000000'
      tipoDocEmisor:
        type: string
        example: '6'
      nroDocEmisor:
        type: string
        example: '00000000000'
      razonSocialEmisor:
        type: string
        example: EMPRESA DEMO S.A.C.
      idReceptor:
        type: string
        example: '20000000001'
      tipoDocReceptor:
        type: string
        example: '6'
      nroDocReceptor:
        type: string
        example: '20000000001'
      razonSocialReceptor:
        type: string
        example: DISTRIBUIDORA DEMO S.R.L.
      tipo:
        type: string
        example: '01'
      serie:
        type: string
        example: F001
      numero:
        type: string
        example: '1'
      fechaEmision:
        type: string
        format: date
        example: '2024-01-01'
      moneda:
        type: string
        example: PEN
      period:
        type: string
        example: 2024-01
      carSunat:
        type: string
        example: 0000000000001F0010000000001
      fechaVencimientoPago:
        type: string
        example: '2024-01-10'
      anio:
        type: string
        example: '2024'
      mes:
        type: string
        example: '01'
      dia:
        type: string
        example: '01'
      nroInicialRango:
        type: string
        example: null
      nroFinalRango:
        type: string
        example: ''
      importeGravadoDg:
        type: string
        example: '100.00'
      dsctoGravada:
        type: string
        example: null
      importeIgvipmDg:
        type: string
        example: '18.00'
      dsctoIgv:
        type: string
        example: null
      importeGravadoDgng:
        type: string
        example: '0.00'
      importeIgvipmDgng:
        type: string
        example: '0.00'
      importeGravadoDng:
        type: string
        example: '0.00'
      importeIgvipmDng:
        type: string
        example: '0.00'
      importeValoradqNg:
        type: string
        example: '0.00'
      importeIsc:
        type: string
        example: '0.00'
      importeGravadaIvap:
        type: string
        example: null
      importeIvap:
        type: string
        example: null
      importeIcbper:
        type: string
        example: '0.00'
      importeOtrosTribcar:
        type: string
        example: '0.00'
      importeExportacion:
        type: string
        example: null
      importeExonerado:
        type: string
        example: null
      importeInafecto:
        type: string
        example: null
      importeTotal:
        type: string
        example: '118.00'
      tipoCambio:
        type: string
        example: '1.000'
      tipoCpModificado:
        type: string
        example: ''
      serieCpModificado:
        type: string
        example: ''
      numeroCpModificado:
        type: string
        example: ''
      fechaEmisionModificado:
        type: string
        example: ''
      codDamDsi:
        type: string
        example: ''
      clasBssSss:
        type: string
        example: ''
      idProyOperador:
        type: string
        example: ''
      porcpart:
        type: string
        example: ''
      imb:
        type: string
        example: '0.00'
      carOrigEI:
        type: string
        example: ''
      importeDetraccion:
        type: string
        example: ''
      tipoNota:
        type: string
        example: ''
      estadoCp:
        type: string
        example: '1'
      incal:
        type: string
        example: '0'
      importeFobEmbarcado:
        type: string
        example: null
      importeOpGratuita:
        type: string
        example: null
      tipoOperacion:
        type: string
        example: null
      damCp:
        type: string
        example: null
      clu:
        type: string
        example: ''
      text:
        type: string
        example: "{\n  \"clu2\": \"string\",\n  \"clu3\": \"string\",\n  \"clu4\": \"string\",\n  ...\n  \"clu39\": \"string\"\n}"
      createdAt:
        type: string
        format: date-time
        example: '2024-05-20T19:03:32.818000000Z'
      updatedAt:
        type: string
        format: date-time
        example: '2024-05-20T19:03:32.818000000Z'
      estadoSunat:
        type: string
        example: '1'
      condicionPago:
        type: string
        example: '1'
  SunatRecordsResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      message:
        type: string
        example: Registros obtenidos.
      data:
        type: array
        items:
          $ref: '#/definitions/SunatRecord'
      meta:
        $ref: '#/definitions/Meta'
  SunatRecord:
    type: object
    properties:
      id:
        type: string
        example: 0000000000001F00100000001
      idEmisor:
        type: string
        example: '00000000000'
      tipoDocEmisor:
        type: string
        example: '6'
      nroDocEmisor:
        type: string
        example: '00000000000'
      razonSocialEmisor:
        type: string
        example: EMPRESA DEMO S.A.C.
      idReceptor:
        type: string
        example: '20000000001'
      tipoDocReceptor:
        type: string
        example: '6'
      nroDocReceptor:
        type: string
        example: '20000000001'
      razonSocialReceptor:
        type: string
        example: DISTRIBUIDORA DEMO S.R.L.
      tipo:
        type: string
        example: '01'
      serie:
        type: string
        example: F001
      numero:
        type: string
        example: '1'
      fechaEmision:
        type: string
        format: date
        example: '2024-01-01'
      moneda:
        type: string
        example: PEN
      period:
        type: string
        example: 2024-01
      carSunat:
        type: string
        example: 0000000000001F0010000000001
      fechaVencimientoPago:
        type: string
        example: '2024-01-10'
      anio:
        type: string
        example: '2024'
      mes:
        type: string
        example: '01'
      dia:
        type: string
        example: '01'
      nroInicialRango:
        type: string
        example: null
      nroFinalRango:
        type: string
        example: ''
      importeGravadoDg:
        type: string
        example: '100.00'
      dsctoGravada:
        type: string
        example: null
      importeIgvipmDg:
        type: string
        example: '18.00'
      dsctoIgv:
        type: string
        example: null
      importeGravadoDgng:
        type: string
        example: '0.00'
      importeIgvipmDgng:
        type: string
        example: '0.00'
      importeGravadoDng:
        type: string
        example: '0.00'
      importeIgvipmDng:
        type: string
        example: '0.00'
      importeValoradqNg:
        type: string
        example: '0.00'
      importeIsc:
        type: string
        example: '0.00'
      importeGravadaIvap:
        type: string
        example: null
      importeIvap:
        type: string
        example: null
      importeIcbper:
        type: string
        example: '0.00'
      importeOtrosTribcar:
        type: string
        example: '0.00'
      importeExportacion:
        type: string
        example: null
      importeExonerado:
        type: string
        example: null
      importeInafecto:
        type: string
        example: null
      importeTotal:
        type: string
        example: '118.00'
      tipoCambio:
        type: string
        example: '1.000'
      tipoCpModificado:
        type: string
        example: ''
      serieCpModificado:
        type: string
        example: ''
      numeroCpModificado:
        type: string
        example: ''
      fechaEmisionModificado:
        type: string
        example: ''
      codDamDsi:
        type: string
        example: ''
      clasBssSss:
        type: string
        example: ''
      idProyOperador:
        type: string
        example: ''
      porcpart:
        type: string
        example: ''
      imb:
        type: string
        example: '0.00'
      carOrigEI:
        type: string
        example: ''
      importeDetraccion:
        type: string
        example: ''
      tipoNota:
        type: string
        example: ''
      estadoCp:
        type: string
        example: '1'
      incal:
        type: string
        example: '0'
      importeFobEmbarcado:
        type: string
        example: null
      importeOpGratuita:
        type: string
        example: null
      tipoOperacion:
        type: string
        example: null
      damCp:
        type: string
        example: null
      clu:
        type: string
        example: ''
      text:
        type: string
        example: "{\n  \"clu2\": \"string\",\n  \"clu3\": \"string\",\n  \"clu4\": \"string\",\n  ...\n  \"clu39\": \"string\"\n}"
  Meta:
    type: object
    properties:
      size:
        type: integer
        example: 10
      currentPage:
        type: integer
        example: 1
      lastPage:
        type: integer
        example: 1
      perPage:
        type: integer
        example: 10
      total:
        type: integer
        example: 10
      ruc:
        type: string
        description: RUC del contribuyente consultado.
        example: '20123456789'
  ErrorResponse:
    type: object
    properties:
      success:
        type: boolean
        example: false
      message:
        type: string
        example: Solicitud incorrecta. El formato del periodo es incorrecto.
  ValidationResponse:
    type: object
    properties:
      success:
        type: boolean
        example: false
      message:
        type: string
        example: Se han presentado unas validaciones al procesar el request.
      data:
        type: array
        example: []
        items: {}
  ReceivedReceiptsResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      message:
        type: string
        example: Registros obtenidos correctamente.
      data:
        type: array
        items:
          $ref: '#/definitions/ReceivedReceipt'
      meta:
        $ref: '#/definitions/Meta'
  ReceivedReceipt:
    type: object
    properties:
      nroDocEmisor:
        type: string
        example: '20987654321'
      tipo:
        type: string
        example: '01'
      serie:
        type: string
        example: FA02
      numero:
        type: string
        example: '134796'
      fechaEmision:
        type: string
        format: date
        example: '2026-07-10'
      json:
        type: integer
        example: 1
      pdf:
        type: integer
        example: 1
      xml:
        type: integer
        example: 0
  ProcessFormatRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - fileName
    - erpFormat
    - bookType
    - issuerId
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Acción permitida por el servicio.
        enum:
        - CONFIRM_UPLOAD
        example: CONFIRM_UPLOAD
      ticket:
        type: string
        description: UUID del ImportJob (ticket) previamente creado.
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
      fileName:
        type: string
        description: Nombre del archivo subido (se normaliza con basename).
        example: PLE2012345678920251000140100001111_011220250906_API.txt
      erpFormat:
        type: string
        description: Formato del archivo importado.
        enum:
        - PLE
        - SIRE
        example: PLE
      bookType:
        type: string
        description: 'Tipo de libro / registros. PLE admite: PURCHASES, SALES, RCE-ND. SIRE admite: RCE, RVIE.'
        enum:
        - PURCHASES
        - SALES
        - RCE
        - RVIE
        - RCE-ND
        example: PURCHASES
      issuerId:
        type: string
        description: RUC o identificador del emisor.
        example: '20123456789'
  ProcessFormatResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        type: object
        properties:
          fileName:
            type: string
            example: PLE2012345678920251000140100001111_011220250906_API.txt
          erpFormat:
            type: string
            example: PLE
          book_type:
            type: string
            example: PURCHASES
  ConfirmProcessFormatRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - fileName
    - erpFormat
    - bookType
    - issuerId
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Acción permitida por el servicio.
        enum:
        - REQUEST_STATUS
        example: REQUEST_STATUS
      ticket:
        type: string
        description: UUID del ImportJob (ticket) a consultar.
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
      fileName:
        type: string
        description: Nombre del archivo asociado al ticket (se normaliza con basename).
        example: PLE2012345678920251000140100001111_011220250906_API.txt
      erpFormat:
        type: string
        description: Formato del archivo.
        enum:
        - PLE
        - SIRE
        example: PLE
      bookType:
        type: string
        description: 'Tipo de libro / registros. PLE admite: PURCHASES, SALES, RCE-ND. SIRE admite: RCE, RVIE.'
        enum:
        - PURCHASES
        - SALES
        - RCE
        - RVIE
        - RCE-ND
        example: PURCHASES
      issuerId:
        type: string
        description: RUC o identificador del emisor.
        example: '20123456789'
  ConfirmProcessFormatResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        description: Mensaje de estado según 'state'.
        example: Processing in progress.
      data:
        type: object
        properties:
          fileName:
            type: string
            example: PLE2012345678920251000140100001111_011220250906_API.txt
          erpFormat:
            type: string
            example: PLE
          book_type:
            type: string
            example: PURCHASES
          ticket:
            type: string
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          state:
            type: string
            description: Raw state code. -1=pending file, 1=in progress, 2=observations, 4=failed, 6=completed
            example: '-1'
          status:
            type: string
            description: Human-readable upload processing status.
            enum:
            - UPLOAD_PENDING_FILE
            - UPLOAD_IN_PROGRESS
            - UPLOAD_OBSERVATIONS
            - UPLOAD_FAILED
            - UPLOAD_COMPLETED
            example: UPLOAD_PENDING_FILE
  ExchangeRateRequest:
    type: object
    required:
    - issuerId
    - action
    - queryDate
    - currencyFrom
    - currencyTo
    properties:
      issuerId:
        type: string
        description: RUC o identificador del emisor.
        example: '20123456789'
      action:
        type: string
        description: Acción permitida por el servicio.
        enum:
        - EXCHANGE_RATE
        example: EXCHANGE_RATE
      queryDate:
        type: string
        format: date
        description: Fecha en formato YYYY-MM-DD.
        example: '2026-01-28'
      currencyFrom:
        type: string
        description: Moneda origen (ISO 4217). Debe ser siempre PEN.
        enum:
        - PEN
        example: PEN
      currencyTo:
        type: string
        description: Moneda destino (ISO 4217).
        pattern: ^[A-Z]{3}$
        example: USD
  ExchangeRateResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        $ref: '#/definitions/ExchangeRateResponseData'
  ExchangeRateResponseData:
    type: object
    properties:
      queryDate:
        type: string
        format: date
        example: '2026-01-28'
      currencyFrom:
        type: string
        example: PEN
      currencyTo:
        type: string
        example: USD
      isBusinessDay:
        type: boolean
        example: true
      rates:
        type: array
        items:
          type: object
          properties:
            currencySource:
              type: string
              example: SBS
            purchaseRate:
              type: number
              format: float
              example: 3.72
            saleRate:
              type: number
              format: float
              example: 3.75
            publicationDate:
              type: string
              format: date
              example: '2026-01-28'
  ReceiptDetailsRequest:
    type: object
    required:
    - user
    - email
    - action
    - issuerId
    - documentType
    - serie
    - number
    - issueDate
    properties:
      user:
        type: string
        example: ELOGIA TECH
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Debe ser RECEIPT_QUERY
        enum:
        - RECEIPT_QUERY
        example: RECEIPT_QUERY
      issuerId:
        type: string
        description: RUC del emisor
        example: '10456789012'
      documentType:
        type: string
        description: Tipo de comprobante (00,01,03,07,08)
        example: '01'
      serie:
        type: string
        description: Serie (ej. E001, F001, B001, etc.)
        example: E001
      number:
        type: string
        description: Correlativo (se normaliza y se prueba raw y padded a 8 dígitos)
        example: '1002'
      issueDate:
        type: string
        format: date
        description: Fecha de emisión (YYYY-MM-DD)
        example: '2026-01-26'
  ReceiptFileData:
    type: object
    properties:
      exists:
        type: boolean
        example: true
      filename:
        type: string
        example: 10456789012-01-E001-1002.xml
      contentBase64:
        type: string
        description: Base64 del archivo
        example: JVBERi0xLjQKJc...
      contentType:
        type: string
        example: application/pdf
      size:
        type: integer
        format: int64
        example: 123456
      tooLarge:
        type: boolean
        example: false
      maxAllowedBytes:
        type: integer
        format: int64
        example: 8388608
      source:
        type: string
        description: Origen del contenido
        example: gcs
  ReceiptDetailsFiles:
    type: object
    properties:
      xml:
        $ref: '#/definitions/ReceiptFileData'
      pdf:
        $ref: '#/definitions/ReceiptFileData'
      cdr:
        $ref: '#/definitions/ReceiptFileData'
  ReceiptDetailsResponseData:
    type: object
    properties:
      foundIn:
        type: string
        description: Tabla de origen del registro (RegistroPeriodo o RegistrosCliente).
        example: RegistroPeriodo
      documentType:
        type: string
        example: '01'
      series:
        type: string
        example: E001
      number:
        type: string
        example: '1002'
      issuerRuc:
        type: string
        example: '10456789012'
      issuerName:
        type: string
        example: EMPRESA DEMO S.A.C.
      customerRuc:
        type: string
        example: '20000000001'
      customerName:
        type: string
        example: DISTRIBUIDORA DEMO S.R.L.
      issueDate:
        type: string
        format: date
        example: '2026-01-26'
      period:
        type: string
        example: 2026-01
      currency:
        type: string
        example: PEN
      totalAmount:
        type: string
        example: '118.00'
      taxableAmount:
        type: string
        example: '100.00'
      igvAmount:
        type: string
        example: '18.00'
      sunatStatus:
        type: string
        example: '1'
      observation:
        type: string
        example: ''
      files:
        $ref: '#/definitions/ReceiptDetailsFiles'
  ReceiptDetailsResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        $ref: '#/definitions/ReceiptDetailsResponseData'
  ExecuteComparisonRequest:
    type: object
    required:
    - user
    - email
    - action
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be EXECUTE_COMPARISON
        example: EXECUTE_COMPARISON
      issuerId:
        type: string
        description: Taxpayer issuer RUC
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-01
      bookType:
        type: string
        description: Book type
        enum:
        - RCE
        - RVIE
        example: RCE
  ExecuteComparisonResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        format: int32
        example: 200
      message:
        type: string
        example: success
      data:
        $ref: '#/definitions/ExecuteComparisonResponseData'
  ExecuteComparisonResponseData:
    type: object
    properties:
      ticket:
        type: string
        example: eea3180d-87ca-4748-befd-ba378c750707
      bookType:
        type: string
        example: RCE
      period:
        type: string
        example: 2026-01
  ExecutionStatusRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be STATUS_COMPARISON
        example: STATUS_COMPARISON
      ticket:
        type: string
        example: eea3180d-87ca-4748-befd-ba378c750707
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        example: 2026-01
      bookType:
        type: string
        example: RCE
  ExecutionStatusResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        format: int32
        example: 200
      message:
        type: string
        example: Processed successfully.
      data:
        $ref: '#/definitions/ExecutionStatusResponseData'
  ExecutionStatusResponseData:
    type: object
    properties:
      ticket:
        type: string
        example: eea3180d-87ca-4748-befd-ba378c750707
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        example: 2026-01
      bookType:
        type: string
        example: RCE
      preliminary:
        type: string
        description: 0=registered, 1=in progress, 2=processed, 3=rejected
        example: '2'
      proposal:
        type: string
        description: 0=registered, 1=in progress, 2=processed, 3=rejected
        example: '2'
      declared:
        type: string
        description: 0=registered, 1=in progress, 2=processed, 3=rejected
        example: '0'
      active:
        type: string
        description: 0=inactive, 1=active
        example: '1'
      state:
        type: string
        description: Backend processing state. 1=in process, 4=failed, 6=completed
        example: '6'
      status:
        type: string
        description: Human-readable status code derived from preliminary and state fields.
        enum:
        - COMPARISON_PENDING
        - COMPARISON_IN_PROGRESS
        - COMPARISON_COMPLETED
        - COMPARISON_FAILED
        - COMPARISON_UNKNOWN
        example: COMPARISON_COMPLETED
  ExecutionQueryRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    - view
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be QUERY_COMPARISON
        example: QUERY_COMPARISON
      ticket:
        type: string
        example: eea3180d-87ca-4748-befd-ba378c750707
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        example: 2026-01
      bookType:
        type: string
        example: RCE
      view:
        type: string
        description: Filter type for the query results
        enum:
        - ALL
        - SUNAT
        - CLIENT
        - DIFF
        - MATCH
        example: ALL
      pageToken:
        type: string
        description: 'Pagination token. Do NOT send in the first request. For the next page, send meta.nextPageToken as pageToken.

          '
        example: eyJsYXN0RG9jSWQiOiIzNjViZjUwOC02OGFhLTQ3YWQtYjE4NC05NzllY2MxODE5OWMiLCJyb3dJbmRleCI6MH0=
  ExecutionQueryResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      message:
        type: string
        example: Rows fetched successfully
      data:
        type: array
        items:
          $ref: '#/definitions/ComparisonRow'
      meta:
        $ref: '#/definitions/PaginationMeta'
  PaginationMeta:
    type: object
    properties:
      pageSize:
        type: integer
        format: int32
        description: Page size controlled by backend
        example: 100
      nextPageToken:
        type: string
        description: Token for the next page (if any)
        example: eyJsYXN0RG9jSWQiOiIzNjViZjUwOC02OGFhLTQ3YWQtYjE4NC05NzllY2MxODE5OWMiLCJyb3dJbmRleCI6MH0=
      hasNext:
        type: boolean
        description: Indicates if more pages are available
        example: true
  ComparisonRow:
    type: object
    properties:
      partnerName:
        type: string
        description: Partner legal name
        example: RINTI S A
      documentNumber:
        type: string
        description: Document identifier
        example: 20456789123-01-F001-445143
      comparisonResult:
        type: string
        description: Result label (Match/Diff/Only in SUNAT/Only in Client)
        example: Registrado
      detail:
        type: string
        description: Additional details (if available)
        example: ''
      concept:
        type: string
        description: Concept/field that differs (if view=DIFF)
        example: Importe total
      erpValue:
        type: string
        description: ERP value for the compared concept (if view=DIFF)
        example: '976.85'
      sunatValue:
        type: string
        description: SUNAT value for the compared concept (if view=DIFF)
        example: '977.43'
      differenceAmount:
        type: number
        format: double
        description: Difference between ERP and SUNAT for the concept (if view=DIFF)
        example: -0.58
      issueDate:
        type: string
        description: Issue date (YYYY-MM-DD)
        example: '2026-01-15'
      currency:
        type: string
        description: Currency code (PEN, USD)
        example: PEN
      exchangeRate:
        type: number
        format: double
        description: Exchange rate used
        example: 1
      sunatStatus:
        type: string
        description: SUNAT status code
        example: '1'
      taxAmount:
        type: number
        format: double
        description: Tax amount
        example: 456.24
      totalAmount:
        type: number
        format: double
        description: Total amount
        example: 2990.89
  PrepareDeclarationRequest:
    type: object
    required:
    - user
    - email
    - action
    - issuerId
    - period
    - bookType
    - ticket
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be PREPARE_DECLARATION
        enum:
        - PREPARE_DECLARATION
        example: PREPARE_DECLARATION
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-01
      bookType:
        type: string
        description: Book type. RCE-ND not supported here; use /declaration/generate-file instead.
        enum:
        - RVIE
        - RCE
        example: RCE
      ticket:
        type: string
        description: 'Comparacion id (returned by Execute comparison). The API resolves or creates the Declaracion record automatically.

          '
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
  PrepareDeclarationResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: Procesamiento iniciado
      data:
        type: object
        properties:
          ticket:
            type: string
            description: Id de la Declaracion creada o existente para el periodo/tipo.
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          bookType:
            type: string
            example: RCE
  DeclarationStatusRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be STATUS_PREPARE_DECLARATION
        enum:
        - STATUS_PREPARE_DECLARATION
        example: STATUS_PREPARE_DECLARATION
      ticket:
        type: string
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        example: 2026-01
      bookType:
        type: string
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RCE
  DeclarationStatusResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        type: object
        properties:
          ticket:
            type: string
            example: 18b25a09-4739-45e2-963a-fc65822c9841
          issuerId:
            type: string
            example: '20123456789'
          period:
            type: string
            example: 2025-02
          bookType:
            type: string
            example: RCE
          preliminary:
            type: string
            description: 0=registered, 1=in progress, 2=prepared, 3=rejected
            example: '2'
          proposal:
            type: string
            description: 0=registered, 1=in progress, 2=prepared, 3=rejected
            example: '1'
          declared:
            type: string
            description: 0=registered, 1=in progress, 2=prepared, 3=rejected
            example: '0'
          active:
            type: string
            description: 0=inactive, 1=active
            example: '1'
          archivoPreliminar:
            type: string
            description: Estado del archivo plano preliminar. 0=registered, 1=in progress, 2=generated, 3=rejected. Empty string if not applicable.
            example: '2'
          status:
            type: string
            description: 'Human-readable status code. Reflects the most advanced active phase (priority: declared > archivoPreliminar > preliminary).

              '
            enum:
            - PENDING
            - PRELIMINARY_IN_PROGRESS
            - PRELIMINARY_COMPLETED
            - PRELIMINARY_FAILED
            - FILE_IN_PROGRESS
            - FILE_GENERATED
            - FILE_FAILED
            - DECLARATION_SENT
            - DECLARATION_ACCEPTED
            - DECLARATION_REJECTED
            example: FILE_GENERATED
  DeclarationQueryRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    - view
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be QUERY_DECLARATION
        enum:
        - QUERY_DECLARATION
        example: QUERY_DECLARATION
      ticket:
        type: string
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        example: 2026-01
      bookType:
        type: string
        description: For RCE-ND, the endpoint returns an empty data array (line-level records not supported for ND).
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RCE
      view:
        type: string
        enum:
        - ALL
        - MATCH
        - FIX
        example: ALL
      pageToken:
        type: string
        description: Do NOT send in the first request. Use meta.nextPageToken.
        example: eyJsYXN0RG9jSWQiOiIuLi4iLCJyb3dJbmRleCI6MH0=
      pageSize:
        type: integer
        format: int32
        description: Page size (backend clamps between 1..500, default 100)
        example: 100
  DeclarationQueryResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      message:
        type: string
        example: Rows fetched successfully
      data:
        type: array
        items:
          $ref: '#/definitions/DeclarationRow'
      meta:
        $ref: '#/definitions/PaginationMeta'
  DeclarationRow:
    type: object
    properties:
      partnerName:
        type: string
        example: PROVEEDOR DEMO E.I.R.L.
      documentNumber:
        type: string
        example: 20987654321-01-F016-0001218
      comparisonResult:
        type: string
        description: ALL/MATCH/FIX mapped label
        example: Corregido
      issueDate:
        type: string
        example: '2025-06-20'
      currency:
        type: string
        example: PEN
      exchangeRate:
        type: number
        format: double
        example: 3.582
      sunatStatus:
        type: string
        example: '1'
      taxAmount:
        type: number
        format: double
        example: 302.03
      totalAmount:
        type: number
        format: double
        example: 1980
      tags:
        type: string
        example: ''
      concept:
        type: string
        example: ''
      erpValue:
        type: string
        example: ''
      sunatValue:
        type: string
        example: ''
      differenceAmount:
        type: number
        format: double
        example: 0
  SunatDeclarationRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be SUNAT_DECLARATION
        enum:
        - SUNAT_DECLARATION
        example: SUNAT_DECLARATION
      ticket:
        type: string
        description: Declaracion ticket (id)
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
      issuerId:
        type: string
        description: RUC del emisor
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-01
      bookType:
        type: string
        description: Book type. For RCE-ND, requires archivoPreliminar='2' instead of preliminary='2'.
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RVIE
  SunatDeclarationResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        format: int32
        example: 200
      message:
        type: string
        example: success
      data:
        type: object
        properties:
          ticket:
            type: string
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          bookType:
            type: string
            example: RVIE
          period:
            type: string
            example: 2026-01
  DeclarationFileRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be FILE_DECLARATION
        enum:
        - FILE_DECLARATION
        example: FILE_DECLARATION
      ticket:
        type: string
        description: Declaraciones.id
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
      issuerId:
        type: string
        description: RUC del emisor
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-01
      bookType:
        type: string
        description: Book type
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RCE
  DeclarationFileResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        type: object
        properties:
          ticket:
            type: string
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          issuerId:
            type: string
            example: '20123456789'
          period:
            type: string
            example: 2026-01
          bookType:
            type: string
            example: RCE
          signedUrl:
            type: string
            description: Signed URL (valid for 24 hours)
            example: https://storage.googleapis.com/bucket-demo/....
          expiresAt:
            type: string
            format: date-time
            description: ISO timestamp when the signed URL expires
            example: '2026-02-12T19:06:40.000Z'
  GeneratePreliminaryFileRequest:
    type: object
    required:
    - user
    - email
    - action
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be GENERATE_PRELIMINARY
        enum:
        - GENERATE_PRELIMINARY
        example: GENERATE_PRELIMINARY
      issuerId:
        type: string
        description: RUC del emisor
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-01
      bookType:
        type: string
        description: 'Book type. RVIE = ventas, RCE = compras, RCE-ND = no domiciliados.

          '
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RCE-ND
      ticket:
        type: string
        description: 'Declaracion id (returned by /declaration/process). Required for RVIE and RCE. Optional for RCE-ND (a new Declaracion is created if not found).

          '
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
  GeneratePreliminaryFileResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: Generación de archivo iniciada
      data:
        type: object
        properties:
          ticket:
            type: string
            description: Declaraciones.id — use this to poll /declaration/status (archivoPreliminar field)
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          bookType:
            type: string
            example: RCE-ND
  SunatTicketStatusRequest:
    type: object
    required:
    - user
    - email
    - action
    - ticket
    - issuerId
    - period
    - bookType
    properties:
      user:
        type: string
        example: test-user
      email:
        type: string
        example: user@example.com
      action:
        type: string
        description: Must be SUNAT_TICKET_STATUS
        enum:
        - SUNAT_TICKET_STATUS
        example: SUNAT_TICKET_STATUS
      ticket:
        type: string
        description: Declaraciones.id
        example: bda8c472-d0da-4a46-abc9-60da4cccd848
      issuerId:
        type: string
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-04
      bookType:
        type: string
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RCE
  SunatTicketStatusResponse:
    type: object
    properties:
      ok:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: success
      data:
        type: object
        properties:
          ticket:
            type: string
            description: Declaraciones.id
            example: bda8c472-d0da-4a46-abc9-60da4cccd848
          issuerId:
            type: string
            example: '20123456789'
          period:
            type: string
            example: 2026-04
          bookType:
            type: string
            example: RCE
          preliminary:
            type: string
            description: 0=registered, 1=in progress, 2=processed, 3=rejected
            example: '2'
          proposal:
            type: string
            description: 0=registered, 1=in progress, 2=processed, 3=rejected
            example: '1'
          declared:
            type: string
            description: 0=registered, 1=in progress, 2=processed, 3=rejected
            example: '0'
          active:
            type: string
            example: '1'
          sunatTicketId:
            type: string
            description: SunatTickets.id
            example: 06105fed-b2a9-48a6-9602-c2f94a197a8e
          sunatTicket:
            type: string
            description: Ticket number returned by SUNAT (null if not yet received)
            example: null
          sunatState:
            type: string
            description: 0=loaded, 1=in progress, 2=success, 3=error
            example: '3'
          sunatServiceCode:
            type: string
            example: null
          sunatStatusCode:
            type: string
            description: SUNAT service status code (codEstadoProceso)
            example: '01'
          sunatStatusDescription:
            type: string
            description: Descripción legible del codEstadoProceso de SUNAT (null si no disponible)
            example: Cargado (solicitado)
          sunatProcessCode:
            type: string
            description: SUNAT process code
            example: '61'
          sunatDescription:
            type: string
            description: Error or success description from SUNAT
            example: 'connection timed out: /34.118.232.41:9091'
          sunatJsonResponse:
            type: string
            description: Full JSON response from SUNAT (if available)
            example: null
          sunatErrorResponse:
            type: string
            description: Error response from SUNAT (if available)
            example: null
          status:
            type: string
            description: Estado interno del ticket derivado de SunatTickets.state.
            enum:
            - TICKET_PENDING
            - TICKET_IN_PROGRESS
            - TICKET_ACCEPTED
            - TICKET_ERRORS
            - TICKET_UNKNOWN
            example: TICKET_PENDING
  DeleteDeclarationRequest:
    type: object
    required:
    - user
    - email
    - action
    - issuerId
    - period
    - bookType
    - ticket
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      action:
        type: string
        description: Must be DELETE_PRELIMINARY
        enum:
        - DELETE_PRELIMINARY
        example: DELETE_PRELIMINARY
      issuerId:
        type: string
        description: 'RUC del emisor. Debe coincidir con el emisor del token y con Declaraciones.id_emisor; si no, la respuesta es 403 y no se borra nada.

          '
        example: '20123456789'
      period:
        type: string
        description: Period in YYYY-MM format
        example: 2026-01
      bookType:
        type: string
        description: 'Book type. RVIE = ventas, RCE = compras, RCE-ND = no domiciliados. Debe coincidir con el tipo de la declaración.

          '
        enum:
        - RVIE
        - RCE
        - RCE-ND
        example: RCE
      ticket:
        type: string
        description: Declaracion id (el mismo que devuelven /declaration/process y /declaration/generate-file).
        example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
  DeleteDeclarationResponse:
    type: object
    description: 'Cuerpo del 202. La limpieza en la plataforma ya se aplico; la baja del preliminar en SUNAT queda encolada y su desenlace se consulta con requestId en /taxpayer/declaration/delete/status.

      '
    properties:
      success:
        type: boolean
        example: true
      status:
        type: integer
        example: 202
      message:
        type: string
        example: Preliminar eliminado en la plataforma. La baja en SUNAT quedo encolada; consulte el estado antes de regenerar.
      data:
        type: object
        properties:
          requestId:
            type: string
            description: 'Id de la solicitud. Es lo que se manda a /taxpayer/declaration/delete/status para saber si la baja en SUNAT ya termino.

              '
            example: 6f2f1a5c-2f2e-4b3a-9a0f-6a1f0f4b7c21
          ticket:
            type: string
            description: Declaraciones.id de la declaración eliminada
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          bookType:
            type: string
            example: RCE
          period:
            type: string
            example: 2026-01
          issuerId:
            type: string
            example: '20123456789'
          sunat:
            type: object
            description: 'Estado de la baja en SUNAT en el momento de responder. EN_COLA = encolada, se consulta en /delete/status. NO_APLICA = no habia preliminar registrado en SUNAT (no se genero el archivo ni la declaración fue rechazada), asi que la solicitud queda COMPLETADO de una.

              '
            properties:
              status:
                type: string
                enum:
                - EN_COLA
                - NO_APLICA
                example: EN_COLA
              topic:
                type: string
                description: Topic al que se publico la baja. Solo con status EN_COLA.
                example: stax-declare-delete-api-dev
              messageId:
                type: string
                description: Id del mensaje de Pub/Sub. Solo con status EN_COLA.
                example: '13058408291012345'
  DeleteDeclarationSunatErrorResponse:
    type: object
    description: 'Cuerpo del 502: la declaración sí quedó eliminada en la plataforma, pero la baja en SUNAT no se pudo encolar. Trae el motivo. Si es SUNAT quien la rechaza, eso NO sale por aquí: aparece como status ERROR en /taxpayer/declaration/delete/status.

      '
    properties:
      success:
        type: boolean
        example: false
      status:
        type: integer
        example: 502
      message:
        type: string
        example: La declaracion se elimino en la plataforma, pero SUNAT rechazo la eliminacion del preliminar.
      data:
        type: object
        properties:
          requestId:
            type: string
            example: 6f2f1a5c-2f2e-4b3a-9a0f-6a1f0f4b7c21
          ticket:
            type: string
            example: ea6abdbc-7da6-4b07-bb5f-d6352590cc34
          bookType:
            type: string
            example: RCE
          period:
            type: string
            example: 2026-01
          sunatError:
            type: object
            description: 'Motivo devuelto por SUNAT: el cuerpo de su respuesta de error. Si la llamada no llegó a obtener respuesta (timeout, red), aquí viaja el mensaje de la excepción como texto en lugar del objeto.

              '
  DeleteDeclarationStatusRequest:
    type: object
    required:
    - user
    - email
    - issuerId
    - requestId
    properties:
      user:
        type: string
        example: usuario.demo
      email:
        type: string
        example: usuario@empresa-demo.pe
      issuerId:
        type: string
        description: 'RUC del emisor. Debe coincidir con el emisor del token y con el de la solicitud consultada; si no, la respuesta es 403.

          '
        example: '20123456789'
      requestId:
        type: string
        description: El requestId que devolvio /taxpayer/declaration/delete.
        example: 6f2f1a5c-2f2e-4b3a-9a0f-6a1f0f4b7c21
  DeleteDeclarationStatusResponse:
    type: object
    properties:
      success:
        type: boolean
        example: true
      status:
        type: integer
        example: 200
      message:
        type: string
        example: El preliminar quedo eliminado. Ya puede regenerarlo.
      data:
        type: object
        properties:
          requestId:
            type: string
            example: 6f2f1a5c-2f2e-4b3a-9a0f-6a1f0f4b7c21
          status:
            type: string
            description: 'EN_PROCESO = la baja en SUNAT sigue en la cola. COMPLETADO = el preliminar quedo eliminado en SUNAT (o no hacia falta tocarlo): ya se puede regenerar. ERROR = SUNAT la rechazo; el motivo viene en sunatError.

              '
            enum:
            - EN_PROCESO
            - COMPLETADO
            - ERROR
            example: COMPLETADO
          requestedAt:
            type: string
            description: 'Cuando se pidio el borrado (created_at de la solicitud). No se expone updated_at: en ApiRequests esa columna la sella por lote el conteo de cuotas, asi que como marca de tiempo del borrado mentiria.

              '
            example: '2026-08-27T15:04:05Z'
          sunatError:
            type: string
            description: Motivo que devolvio SUNAT. Solo con status ERROR.
            example: 'SUNAT: no existe preliminar para el periodo'
