{
  "openapi": "3.0.0",
  "info": {
    "title": "Taxo Extracción API",
    "description": "Extracción de documentos fiscales del SRI de Ecuador y del SAT de México: contribuyentes, tareas de descarga, documentos y webhooks. Autentica cada petición con tu API key en la cabecera `X-API-KEY`.",
    "version": "1.0",
    "contact": {}
  },
  "servers": [
    {
      "url": "https://api.taxo.ws",
      "description": "Production"
    },
    {
      "url": "https://staging-api.taxo.ws",
      "description": "Staging"
    }
  ],
  "security": [
    {
      "X-API-KEY": []
    }
  ],
  "tags": [
    {
      "name": "Tokens"
    },
    {
      "name": "Organizations"
    },
    {
      "name": "Taxpayers"
    },
    {
      "name": "Contribuyentes SRI"
    },
    {
      "name": "Tasks"
    },
    {
      "name": "Documents"
    },
    {
      "name": "Documents Void"
    },
    {
      "name": "Extractions"
    },
    {
      "name": "Extractions CFDI"
    },
    {
      "name": "Credentials"
    },
    {
      "name": "Webhooks"
    }
  ],
  "paths": {
    "/contributors/id/{id}": {
      "get": {
        "operationId": "SriContributorsController_getContributorById",
        "summary": "Obtener contribuyente por ID",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contribuyente encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseContributorDto"
                }
              }
            }
          },
          "404": {
            "description": "Contribuyente no encontrado"
          }
        },
        "tags": [
          "Contribuyentes SRI"
        ]
      }
    },
    "/contributors/search": {
      "get": {
        "operationId": "SriContributorsController_searchContributors",
        "summary": "Buscar contribuyentes",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Lista de contribuyentes encontrados",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchContributorsResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Contribuyentes SRI"
        ]
      }
    },
    "/contributors/{id}/taxpayers": {
      "delete": {
        "operationId": "SriContributorsController_removeTaxpayersFromContributor",
        "summary": "Remover taxpayers de un contribuyente",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveContributorsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contribuyente actualizado sin los taxpayers removidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseContributorDto"
                }
              }
            }
          },
          "400": {
            "description": "Error en la solicitud"
          },
          "404": {
            "description": "Contribuyente no encontrado"
          }
        },
        "tags": [
          "Contribuyentes SRI"
        ]
      },
      "get": {
        "operationId": "SriContributorsController_getContributorTaxpayers",
        "summary": "Obtener taxpayers asociados a un contribuyente",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de taxpayers asociados",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Taxpayer"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Contribuyente no encontrado"
          }
        },
        "tags": [
          "Contribuyentes SRI"
        ]
      },
      "post": {
        "operationId": "SriContributorsController_addTaxpayersToContributor",
        "summary": "Asociar taxpayers a un contribuyente",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssociateContributorsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contribuyente actualizado con los nuevos taxpayers",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseContributorDto"
                }
              }
            }
          },
          "400": {
            "description": "Error en la solicitud"
          },
          "404": {
            "description": "Contribuyente no encontrado"
          }
        },
        "tags": [
          "Contribuyentes SRI"
        ]
      }
    },
    "/contributors/{ruc}": {
      "get": {
        "operationId": "SriContributorsController_getContributorByRuc",
        "summary": "Obtener contribuyente por RUC",
        "parameters": [
          {
            "name": "ruc",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contribuyente encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseContributorDto"
                }
              }
            }
          },
          "404": {
            "description": "Contribuyente no encontrado"
          }
        },
        "tags": [
          "Contribuyentes SRI"
        ]
      }
    },
    "/documents": {
      "get": {
        "operationId": "DocumentsController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The documents have been successfully fetched."
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents-void": {
      "get": {
        "operationId": "DocumentsECVoidController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The documents void have been successfully fetched."
          }
        },
        "tags": [
          "Documents Void"
        ]
      }
    },
    "/documents-void/annul": {
      "post": {
        "operationId": "DocumentsECVoidController_annulDocument",
        "summary": "Annul a document",
        "description": "Queues a document for annulment in the SRI system",
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "Document annulment details",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VoidDocumentDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "La solicitud de anulación ha sido encolada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "La solicitud de anulación ha sido encolada"
                    },
                    "status": {
                      "type": "string",
                      "example": "encolado"
                    },
                    "taskId": {
                      "type": "string",
                      "example": "uuid-task-id"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request data"
          },
          "404": {
            "description": "Taxpayer not found"
          }
        },
        "tags": [
          "Documents Void"
        ]
      }
    },
    "/documents/convert": {
      "post": {
        "operationId": "DocumentsController_receiveXmlAndReturnJson",
        "parameters": [],
        "responses": {
          "201": {
            "description": ""
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/debug/by-access-key/{accessKey}": {
      "get": {
        "operationId": "DocumentsController_getDocumentByAccessKey",
        "parameters": [
          {
            "name": "accessKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/download/{bucket}/*": {
      "get": {
        "operationId": "DocumentsController_downloadPdfByDirectory",
        "parameters": [
          {
            "name": "bucket",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "0",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Content-Type",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/import/bulk": {
      "post": {
        "operationId": "DocumentsController_importDocumentsBulk",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "description": "Your API key like: staging_KGsVV2x4_XXXXXXXXXXXXX",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "ZIP contenedor: se extraen todos los XML de la raíz y dentro de ZIPs anidados, se agrupan por contribuyente de la organización (emisor/receptor) y se crea una importación por RUC. Puede mezclar XML sueltos y ZIPs internos; también un único ZIP interno con XMLs de varios contribuyentes.",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "ZIP con XML en la raíz, ZIPs internos o ambos. Cada XML se asigna al contribuyente según RUC emisor o receptor frente a la organización."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Importación masiva iniciada. El procesamiento se realiza en background.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkImportResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/import/{taxpayerIdentification}": {
      "post": {
        "operationId": "DocumentsController_importDocuments",
        "parameters": [
          {
            "name": "taxpayerIdentification",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "description": "Your API key like: staging_KGsVV2x4_XXXXXXXXXXXXX",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Subir archivo ZIP con XMLs mixtos",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Archivo ZIP conteniendo documentos XML (facturas, retenciones, notas de crédito, etc.)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Importación iniciada. El procesamiento se realiza en background.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportStartedResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/mx": {
      "get": {
        "operationId": "DocumentsController_findAllMx",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "AUTHORIZED",
                "VOID"
              ],
              "type": "string"
            }
          },
          {
            "name": "documentType",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "I",
                "E",
                "T",
                "N",
                "P"
              ],
              "type": "string"
            }
          },
          {
            "name": "dateType",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "emission",
                "extraction"
              ],
              "type": "string"
            }
          },
          {
            "name": "toDate",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fromDate",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "issued",
                "received"
              ],
              "type": "string"
            }
          },
          {
            "name": "taxpayerId",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "MX documents (CFDI) have been successfully fetched."
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/stats": {
      "get": {
        "operationId": "DocumentsController_getDocumentStats",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/documents/{accessKey}": {
      "get": {
        "operationId": "DocumentsController_getDocument",
        "parameters": [
          {
            "name": "accessKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Content-Type",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Documents"
        ]
      }
    },
    "/extractions": {
      "get": {
        "operationId": "ExtractionsController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The extraction have been successfully fetched."
          }
        },
        "tags": [
          "Extractions"
        ]
      }
    },
    "/extractions/{id}/listing-file": {
      "get": {
        "operationId": "ExtractionsController_getListingFile",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingFileResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "La extracción no existe o no tiene listado asociado."
          }
        },
        "tags": [
          "Extractions"
        ]
      }
    },
    "/extractions/{id}/retry": {
      "patch": {
        "operationId": "ExtractionsController_retryExtraction",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "batchSize",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "delay",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Extractions"
        ]
      },
      "put": {
        "operationId": "ExtractionsController_retryExtractionById",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Extractions"
        ]
      }
    },
    "/organizations": {
      "get": {
        "operationId": "OrganizationsController_findOne",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      },
      "patch": {
        "operationId": "OrganizationsController_rename",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/invitations": {
      "get": {
        "operationId": "InvitationsController_list",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      },
      "post": {
        "operationId": "InvitationsController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvitationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/invitations/{id}": {
      "delete": {
        "operationId": "InvitationsController_revoke",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/members": {
      "get": {
        "operationId": "OrganizationsController_listMembers",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/members/mcp-status": {
      "get": {
        "operationId": "OrganizationsController_getMembersMcpStatus",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/members/{userId}": {
      "delete": {
        "operationId": "OrganizationsController_removeMember",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/members/{userId}/role": {
      "patch": {
        "operationId": "OrganizationsController_updateMemberRole",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMemberRoleDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/members/{userId}/taxpayers": {
      "get": {
        "operationId": "OrganizationsController_listMemberTaxpayers",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      },
      "put": {
        "operationId": "OrganizationsController_setMemberTaxpayers",
        "parameters": [
          {
            "name": "userId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceMemberTaxpayersDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/taxpayers/{taxpayerId}/members": {
      "get": {
        "operationId": "OrganizationsController_listTaxpayerMembers",
        "parameters": [
          {
            "name": "taxpayerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      },
      "put": {
        "operationId": "OrganizationsController_setTaxpayerMembers",
        "parameters": [
          {
            "name": "taxpayerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceTaxpayerMembersDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/organizations/users": {
      "get": {
        "operationId": "OrganizationsController_findUsers",
        "parameters": [
          {
            "name": "page",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      },
      "post": {
        "operationId": "OrganizationsController_assignRoleToUser",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssignRoleUserOrganizationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": ""
          }
        },
        "tags": [
          "Organizations"
        ]
      }
    },
    "/tasks": {
      "get": {
        "operationId": "TasksController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          },
          {
            "name": "sortBy",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortOrder",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Filter tasks by taxpayer_identification or type ",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The tasks have been successfully fetched."
          }
        },
        "tags": [
          "Tasks"
        ]
      },
      "post": {
        "operationId": "TasksController_create",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "description": "Your API key like: staging_KGsVV2x4_XXXXXXXXXXXXX",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Create Task DTO",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTaskDto"
              },
              "examples": {
                "purchaseBill": {
                  "summary": "Purchase Bill Task",
                  "value": {
                    "type": "PURCHASE.BILL",
                    "taxpayerId": "1720120094001",
                    "startDownloadAt": "2024-07-01"
                  }
                },
                "purchaseRetention": {
                  "summary": "Purchase Retention Task",
                  "value": {
                    "type": "PURCHASE.RETENTION",
                    "taxpayerId": "1720120094001",
                    "startDownloadAt": "2024-07-07"
                  }
                },
                "getDocuments": {
                  "summary": "Get an individual document Task",
                  "value": {
                    "type": "RIDE",
                    "identifier": "2804202401050290441000120011000000003941942460118"
                  }
                },
                "categoryInvoice": {
                  "summary": "Category Invoice Task",
                  "value": {
                    "type": "CATEGORY.INVOICE",
                    "taxpayerId": "1707723134001",
                    "identifier": "2804202501099315216100123920010001849010018490117"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The Task has been successfully created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaskDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tasks"
        ]
      }
    },
    "/tasks/bulk": {
      "post": {
        "operationId": "TasksController_createBulk",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": ""
          }
        },
        "tags": [
          "Tasks"
        ]
      }
    },
    "/tasks/import-txt/recibidos": {
      "post": {
        "operationId": "TasksController_importTxtRecibidos",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "description": "Your API key like: staging_KGsVV2x4_XXXXXXXXXXXXX",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Archivo TXT descargado del SRI (compras / recibidos)",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Importacion de TXT SRI (recibidos / compras) iniciada. Resuelve el taxpayer por cedula en el TXT.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportTxtResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tasks"
        ]
      }
    },
    "/tasks/upload-zip": {
      "post": {
        "operationId": "TasksController_uploadZipAuto",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "description": "Your API key like: staging_KGsVV2x4_XXXXXXXXXXXXX",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "ZIP de XMLs SRI sin taxpayerId. Backend lee los XMLs, detecta el RUC del receptor y crea la Task.",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "ZIP de XMLs (todos del mismo taxpayer)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "ZIP procesado, taxpayer resuelto del contenido y Task creada con manualZipImport.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadZipAutoResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tasks"
        ]
      }
    },
    "/tasks/upload-zip/{taxpayerId}": {
      "post": {
        "operationId": "TasksController_uploadZip",
        "parameters": [
          {
            "name": "taxpayerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "description": "Your API key like: staging_KGsVV2x4_XXXXXXXXXXXXX",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Upload ZIP file",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "ZIP file containing XML documents"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "ZIP file uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadZipResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Tasks"
        ]
      }
    },
    "/tasks/{id}/detail": {
      "get": {
        "operationId": "TasksController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Tasks"
        ]
      }
    },
    "/taxpayer/{ruc}/activities": {
      "get": {
        "operationId": "TaxpayerController_getEconomicActivities",
        "summary": "Get the taxpayer establishments and their economic activities (CIIU)",
        "description": "Operacion sincrona y MUY lenta: el crawler navega el asistente de Actualizacion del SRI con un navegador headless, recorriendo un wizard por cada establecimiento. Con uno son decenas de segundos; con varios, minutos, y en ese caso devuelve 504. El crawler cachea por contribuyente, asi que un reintento posterior suele responder al instante (`fromCache: true`). Configurar el timeout del cliente en al menos 120s y no llamarlo dentro de un flujo donde el usuario espera en pantalla.",
        "parameters": [
          {
            "name": "ruc",
            "required": true,
            "in": "path",
            "description": "RUC del contribuyente. Se resuelve dentro de la organizacion del API key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Establecimientos con sus actividades. `establishments` puede venir vacio sin que sea un error (ver `message`), y `partial: true` indica que algun establecimiento fallo."
          },
          "400": {
            "description": "El contribuyente no tiene credenciales validas"
          },
          "401": {
            "description": "Credenciales del SRI invalidas"
          },
          "403": {
            "description": "Credenciales invalidas o clave vencida (`passwordExpired: true`)"
          },
          "404": {
            "description": "Taxpayer not found"
          },
          "502": {
            "description": "Fallo del SRI o del crawler"
          },
          "504": {
            "description": "El SRI no respondio a tiempo (reintentar mas tarde)"
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayer/{ruc}/registry": {
      "get": {
        "operationId": "TaxpayerController_getRegistry",
        "summary": "Get taxpayer registry by RUC",
        "parameters": [
          {
            "name": "ruc",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Registry data retrieved"
          },
          "404": {
            "description": "Taxpayer not found in SRI registry"
          },
          "500": {
            "description": "Server error"
          },
          "504": {
            "description": "SRI registry did not respond in time"
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayer/{ruc}/ruc-certificate": {
      "get": {
        "operationId": "TaxpayerController_getRucCertificate",
        "summary": "Download the taxpayer RUC certificate from SRI",
        "description": "Operacion sincrona y lenta (20-90s): el crawler abre un navegador contra el SRI. El SRI permite 3 solicitudes diarias por tipo de certificado y cada llamada consume al menos una, asi que no conviene reintentar automaticamente. Configurar el timeout del cliente en al menos 120s.",
        "parameters": [
          {
            "name": "ruc",
            "required": true,
            "in": "path",
            "description": "RUC del contribuyente. Se resuelve dentro de la organizacion del API key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Signed URL al PDF del certificado"
          },
          "400": {
            "description": "El contribuyente no tiene credenciales validas"
          },
          "401": {
            "description": "Credenciales del SRI invalidas"
          },
          "403": {
            "description": "Credenciales invalidas o clave vencida (`passwordExpired: true`)"
          },
          "404": {
            "description": "Taxpayer not found"
          },
          "429": {
            "description": "Cupo diario del SRI agotado (3/dia)"
          },
          "502": {
            "description": "Fallo del SRI o del crawler"
          },
          "504": {
            "description": "El SRI no respondio a tiempo"
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayer/{taxpayerId}/inbox": {
      "get": {
        "operationId": "TaxpayerController_getInbox",
        "summary": "Get taxpayer inbox notifications",
        "parameters": [
          {
            "name": "taxpayerId",
            "required": true,
            "in": "path",
            "description": "Taxpayer ID (UUID)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Inbox notifications retrieved successfully"
          },
          "404": {
            "description": "Taxpayer not found"
          },
          "500": {
            "description": "Server error"
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers": {
      "get": {
        "operationId": "TaxpayersController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          },
          {
            "name": "sortBy",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortOrder",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Filter taxpayers by Identification number or Full Name",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The taxpayers have been successfully fetched."
          }
        },
        "tags": [
          "Taxpayers"
        ]
      },
      "post": {
        "operationId": "TaxpayersController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTaxpayerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "create a new taxpayer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaxpayerDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/fiel": {
      "post": {
        "operationId": "TaxpayersController_createFiel",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFielTaxpayerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registra taxpayer por FIEL (JSON). Requiere subir certificados antes via POST /v1/credentials/upload-certificates/:rfc.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaxpayerDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/mark-bad-credentials": {
      "post": {
        "operationId": "TaxpayersController_markBadCredentials",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarkBadCredentialsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Marca el taxpayer con el RUC indicado como BAD_CREDENTIALS",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarkBadCredentialsResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Taxpayer no encontrado para el RUC en la organización"
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/overview": {
      "get": {
        "operationId": "TaxpayersController_getOverview",
        "parameters": [
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 10,
              "type": "number"
            }
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "description": "Filter taxpayers by Identification number or Full Name",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Taxpayers of the organization with document count and last sync date."
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/stats": {
      "get": {
        "operationId": "TaxpayersController_getTaxpayerDocumentStats",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/validate-credentials": {
      "get": {
        "operationId": "TaxpayersController_getValidationSummary",
        "parameters": [
          {
            "name": "jobId",
            "required": true,
            "in": "query",
            "description": "ID del job de validación masiva",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Obtiene el resumen de una validación masiva de credenciales por jobId"
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/validate-credentials-bulk": {
      "post": {
        "operationId": "TaxpayersController_validateCredentialsBulk",
        "parameters": [],
        "responses": {
          "202": {
            "description": "Inicia la validación masiva de credenciales para todos los taxpayers con BAD_CREDENTIALS",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateCredentialsBulkResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{identification}": {
      "patch": {
        "operationId": "TaxpayersController_update",
        "parameters": [
          {
            "name": "identification",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTaxpayerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "update partial taxpayer info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaxpayerDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{identification}/add-ciec": {
      "patch": {
        "operationId": "TaxpayersController_addCiec",
        "parameters": [
          {
            "name": "identification",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTaxpayerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agrega credenciales CIEC a un taxpayer registrado por FIEL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaxpayerDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{identification}/add-fiel": {
      "patch": {
        "operationId": "TaxpayersController_addFiel",
        "parameters": [
          {
            "name": "identification",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFielTaxpayerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agrega credenciales FIEL a un taxpayer existente con CIEC. Requiere haber subido certificados via POST /v1/credentials/upload-certificates/:rfc.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaxpayerDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{id}": {
      "delete": {
        "operationId": "TaxpayersController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "delete taxpayer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "boolean"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      },
      "get": {
        "operationId": "TaxpayersController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "return a taxpayer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTaxpayerDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{id}/contributors": {
      "get": {
        "operationId": "TaxpayersController_getContributorsByTaxpayer",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "schema": {
              "example": 1,
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "example": 20,
              "type": "number"
            }
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "CUSTOMER",
                "SUPPLIER"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{id}/credentials": {
      "get": {
        "operationId": "TaxpayersController_getCredentials",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "description": "API Key requerido. Las credenciales se encriptan con esta clave para que el cliente pueda desencriptarlas.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Credenciales del taxpayer encriptadas con el x-api-key. Desencriptar en el cliente usando AES-256-GCM.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptedCredentialsResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Este endpoint requiere autenticación por API Key (header x-api-key), para que el cliente pueda desencriptar las credenciales."
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{id}/remove-from-organization": {
      "post": {
        "operationId": "TaxpayersController_removeFromOrganization",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Mueve el contribuyente a la organización genérica",
            "content": {
              "application/json": {
                "schema": {
                  "type": "boolean"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/taxpayers/{id}/validate-credentials": {
      "post": {
        "operationId": "TaxpayersController_validateCredentials",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Validates the stored credentials of a taxpayer against SRI",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateCredentialsResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Taxpayers"
        ]
      }
    },
    "/tokens": {
      "get": {
        "operationId": "TokensController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Tokens"
        ]
      },
      "post": {
        "operationId": "TokensController_create",
        "parameters": [],
        "responses": {
          "201": {
            "description": ""
          }
        },
        "tags": [
          "Tokens"
        ]
      }
    },
    "/tokens/{id}": {
      "delete": {
        "operationId": "TokensController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Tokens"
        ]
      },
      "patch": {
        "operationId": "TokensController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTokenDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Tokens"
        ]
      }
    },
    "/v1/credentials/upload-certificates/{identifier}": {
      "post": {
        "operationId": "CredentialsController_uploadCertificates",
        "parameters": [
          {
            "name": "identifier",
            "required": true,
            "in": "path",
            "description": "RFC del contribuyente (ej. AASI760413RP8)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Subir archivos .cer y .key (cualquier nombre de archivo aceptado)",
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "cer": {
                    "type": "string",
                    "format": "binary",
                    "description": "Archivo .cer del certificado"
                  },
                  "key": {
                    "type": "string",
                    "format": "binary",
                    "description": "Archivo .key de la clave privada"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Certificados subidos correctamente. Usa cer_s3_key y key_s3_key en el request de extracciones.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadCertificatesResponseDto"
                }
              }
            }
          }
        },
        "tags": [
          "Credentials"
        ]
      }
    },
    "/v1/extractions": {
      "post": {
        "operationId": "ExtractionsController_createExtraction",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateExtractionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Extraction created successfully"
          },
          "400": {
            "description": "Bad request"
          }
        },
        "tags": [
          "Extractions"
        ]
      }
    },
    "/v1/extractions-cfdi": {
      "post": {
        "operationId": "ExtractionsCfdiController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSatbotDirectExtractionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "CFDI extraction created successfully"
          },
          "400": {
            "description": "Bad request"
          }
        },
        "tags": [
          "Extractions CFDI"
        ]
      }
    },
    "/v1/extractions-cfdi/fiel": {
      "post": {
        "operationId": "ExtractionsCfdiController_createFiel",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSatbotFielExtractionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "CFDI extraction with FIEL created successfully"
          },
          "400": {
            "description": "Bad request"
          }
        },
        "tags": [
          "Extractions CFDI"
        ]
      }
    },
    "/v1/extractions-cfdi/reprocess/{jobPublicId}": {
      "post": {
        "operationId": "ExtractionsCfdiController_reprocess",
        "parameters": [
          {
            "name": "jobPublicId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Extraction reprocessing initiated"
          },
          "404": {
            "description": "Job not found"
          }
        },
        "tags": [
          "Extractions CFDI"
        ]
      }
    },
    "/v1/extractions/{id}": {
      "get": {
        "operationId": "ExtractionsController_getExtraction",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The extraction ID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Extraction details"
          },
          "404": {
            "description": "Extraction not found"
          }
        },
        "tags": [
          "Extractions"
        ]
      }
    },
    "/v1/extractions/{id}/documents/{documentId}/download": {
      "get": {
        "operationId": "ExtractionsController_downloadDocument",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "The extraction ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "required": true,
            "in": "path",
            "description": "The document ID to download",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "description": "File type to download",
            "schema": {
              "enum": [
                "PDF",
                "JSON",
                "XML"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File content (binary or text)"
          },
          "404": {
            "description": "Document not found"
          }
        },
        "tags": [
          "Extractions"
        ]
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "WebhooksController_findAll",
        "parameters": [
          {
            "name": "page",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": true,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Webhooks"
        ]
      },
      "post": {
        "operationId": "WebhooksController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": ""
          }
        },
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "operationId": "WebhooksController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Webhooks"
        ]
      },
      "get": {
        "operationId": "WebhooksController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "update partial taxpayer info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseWebhookDto"
                }
              }
            }
          }
        },
        "tags": [
          "Webhooks"
        ]
      },
      "patch": {
        "operationId": "WebhooksController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "Webhooks"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "X-API-KEY": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY",
        "description": "API Key para autenticación"
      }
    },
    "schemas": {
      "AccessKeyItemDto": {
        "type": "object",
        "properties": {
          "accessKey": {
            "type": "string",
            "description": "Clave de acceso del documento (49 dígitos)",
            "example": "0101202601179129015100120011000006079937846333315"
          },
          "receiverIdentification": {
            "type": "string",
            "description": "Identificación del receptor del documento (IDENTIFICACION_RECEPTOR del TXT). Puede ser cédula (10 dígitos) o RUC (13 dígitos)",
            "example": "1719956854001"
          }
        },
        "required": [
          "accessKey",
          "receiverIdentification"
        ]
      },
      "ActiveSessionDto": {
        "type": "object",
        "properties": {
          "viewState": {
            "type": "string",
            "description": "ViewState de la sesión JSF del SRI",
            "example": "4836621168818476484:4051829485435980574"
          },
          "cookies": {
            "description": "Array de cookies de la sesión (opcional si se proporciona cookiesString)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cookiesString": {
            "type": "string",
            "description": "Cookies en formato string para enviar al crawler",
            "example": "JSESSIONID=xxx; KEYCLOAK_SESSION=yyy"
          },
          "totalDocumentos": {
            "type": "number",
            "description": "Total de documentos esperados en la sesión",
            "example": 14
          }
        },
        "required": [
          "viewState",
          "cookiesString"
        ]
      },
      "AssignRoleUserOrganizationDto": {
        "type": "object",
        "properties": {}
      },
      "AssociateContributorsDto": {
        "type": "object",
        "properties": {
          "contributorIds": {
            "description": "Lista de IDs de contribuyentes a asociar",
            "example": [
              1,
              2,
              3
            ],
            "type": "array",
            "items": {
              "type": "number"
            }
          },
          "taxpayerIds": {
            "description": "Lista de IDs de taxpayers a asociar",
            "example": [
              "1234567890",
              "0987654321"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "contributorIds",
          "taxpayerIds"
        ]
      },
      "BulkImportResponseDto": {
        "type": "object",
        "properties": {
          "totalZips": {
            "type": "number",
            "example": 5,
            "description": "Número de grupos de importación (uno por contribuyente con XMLs válidos)"
          },
          "successfulCount": {
            "type": "number",
            "example": 3,
            "description": "Número de ZIPs procesados exitosamente"
          },
          "rejectedCount": {
            "type": "number",
            "example": 2,
            "description": "Número de ZIPs rechazados"
          },
          "successful": {
            "description": "Lista de ZIPs procesados exitosamente",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SuccessfulZipImportDto"
            }
          },
          "rejected": {
            "description": "Lista de ZIPs rechazados con sus razones",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RejectedZipDto"
            }
          },
          "rejectedXmls": {
            "description": "XMLs rechazados (sin contribuyente en la organización o ilegibles)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RejectedXmlDto"
            }
          },
          "detectedMode": {
            "type": "string",
            "example": "mixed",
            "description": "Origen de los XML en el contenedor: flat-xmls (solo raíz), nested-zips (solo dentro de ZIPs internos) o mixed (ambos)",
            "enum": [
              "nested-zips",
              "flat-xmls",
              "mixed"
            ]
          }
        },
        "required": [
          "totalZips",
          "successfulCount",
          "rejectedCount",
          "successful",
          "rejected"
        ]
      },
      "CreateExtractionDto": {
        "type": "object",
        "properties": {}
      },
      "CreateFielTaxpayerDto": {
        "type": "object",
        "properties": {
          "rfc": {
            "type": "string",
            "example": "AOBE910907K45",
            "description": "RFC del contribuyente mexicano (12-13 caracteres). Obligatorio en POST /taxpayers/fiel; en PATCH .../add-fiel puede omitirse (se usa el RFC de la URL)."
          },
          "fullName": {
            "type": "string",
            "example": "SUAREZ CORO BRYAN BOLIVAR",
            "description": "Nombre del contribuyente. Opcional: si viene fullName en la respuesta del upload (paso 1), enviarlo aquí."
          },
          "cert_password": {
            "type": "string",
            "example": "23287c91",
            "description": "Contraseña del certificado FIEL en texto plano"
          },
          "cer_s3_key": {
            "type": "string",
            "example": "certificates/AOBE910907K45/AOBE910907K45.cer",
            "description": "S3 key del .cer devuelto por POST /v1/credentials/upload-certificates/:rfc"
          },
          "key_s3_key": {
            "type": "string",
            "example": "certificates/AOBE910907K45/AOBE910907K45.key",
            "description": "S3 key del .key devuelto por POST /v1/credentials/upload-certificates/:rfc"
          },
          "byPassCheckCredential": {
            "type": "boolean",
            "example": false,
            "description": "Flag para omitir validación. Por defecto false. FIEL no valida contra SAT en el registro."
          }
        },
        "required": [
          "cert_password",
          "cer_s3_key",
          "key_s3_key"
        ]
      },
      "CreateInvitationDto": {
        "type": "object",
        "properties": {}
      },
      "CreateSatbotDirectExtractionDto": {
        "type": "object",
        "properties": {
          "ciec_password": {
            "type": "string",
            "description": "Contraseña CIEC en texto plano. Opcional si el taxpayer ya está registrado."
          },
          "client_rfc": {
            "type": "string",
            "description": "RFC del contribuyente"
          },
          "from": {
            "type": "string",
            "description": "Fecha inicio (YYYY-MM-DD HH:mm:ss)"
          },
          "to": {
            "type": "string",
            "description": "Fecha fin (YYYY-MM-DD HH:mm:ss)"
          }
        },
        "required": [
          "client_rfc",
          "from",
          "to"
        ]
      },
      "CreateSatbotFielExtractionDto": {
        "type": "object",
        "properties": {
          "client_rfc": {
            "type": "string",
            "description": "RFC del contribuyente"
          },
          "cert_password": {
            "type": "string",
            "description": "Contraseña de la FIEL. Opcional si el taxpayer está registrado con FIEL (se resuelve desde DB)"
          },
          "cer_s3_key": {
            "type": "string",
            "description": "S3 key del .cer devuelto por POST /v1/credentials/upload-certificates/:rfc. Opcional si taxpayer registrado con FIEL.",
            "example": "certificates/AASI760413RP8/AASI760413RP8.cer"
          },
          "key_s3_key": {
            "type": "string",
            "description": "S3 key del .key devuelto por POST /v1/credentials/upload-certificates/:rfc. Opcional si taxpayer registrado con FIEL.",
            "example": "certificates/AASI760413RP8/AASI760413RP8.key"
          },
          "from": {
            "type": "string",
            "description": "Fecha inicio (YYYY-MM-DD HH:mm:ss)"
          },
          "to": {
            "type": "string",
            "description": "Fecha fin (YYYY-MM-DD HH:mm:ss)"
          }
        },
        "required": [
          "client_rfc",
          "from",
          "to"
        ]
      },
      "CreateTaskDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "PURCHASE.ALL",
              "PURCHASE.BILL",
              "PURCHASE.SETTLEMENT",
              "PURCHASE.CREDIT_NOTE",
              "PURCHASE.DEBIT_NOTE",
              "PURCHASE.REFERRAL_GUIDE",
              "PURCHASE.RETENTION",
              "TAXPAYER.REGIMEN",
              "TAXPAYER.OBLIGATIONS",
              "TAXPAYER.STATEMENTS.UPLOAD",
              "TAXPAYER.STATEMENTS.DOWNLOAD",
              "SALE.INVOICE",
              "SALE.CREDIT_NOTE",
              "SALE.SALE_RETENTION",
              "SALE.SETTLEMENT",
              "SALE.ALL",
              "VOIDS.ALL",
              "VOID.DOCUMENT",
              "RIDE",
              "TAXPAYER.OPINION",
              "TAXPAYER.SITUATION",
              "CFDI.INBOUND.ALL",
              "CFDI.OUTBOUND.ALL",
              "CATEGORY.INVOICE",
              "CATEGORY.CFDI"
            ],
            "example": "TAXPAYER.REGIMEN",
            "description": "the type of task"
          },
          "taxpayerId": {
            "type": "string",
            "example": "1206316641001",
            "description": "The identification of taxpayer"
          },
          "rfc": {
            "type": "string",
            "example": "AOEW950404-1G1",
            "description": "RFC del contribuyente (México)"
          },
          "voidDetails": {
            "type": "object",
            "description": "Void document details for annulment tasks (required only for VOID_DOCUMENT type)",
            "example": {
              "ruc": "1234567890001",
              "type": "01",
              "fechaAutorizacion": "13/11/2025",
              "accessKey": "010520180117600132100120010110063009043924631114",
              "numeroAutorizacion": "010520180117600132100120010110063009043924631114",
              "identificacionReceptor": "0999999999001",
              "correoElectronicoReceptor": "cliente@example.com"
            }
          },
          "manualDownload": {
            "type": "boolean",
            "description": "Flag to indicate if the download should be manual",
            "example": true
          },
          "accessKeys": {
            "description": "Array of access keys for manual download tasks",
            "example": [
              "010520180117600132100120010110063009043924631114",
              "010520180117600132100120010110063009043924631115"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "manualZipImport": {
            "type": "string",
            "description": "S3 URL for manual ZIP import (alternative to manualDownload with accessKeys)",
            "example": "s3://bucket-name/1707723134001_1234567890.zip"
          },
          "accessKeyItems": {
            "description": "Array de items con clave de acceso y su IDENTIFICACION_RECEPTOR del TXT. Permite validar que los documentos pertenezcan al taxpayer antes de procesarlos. Si se proporciona, se extraerán los accessKeys de aquí y se validará que todos los receiverIdentification coincidan con el taxpayerId (soporta cédula 10 dígitos o RUC 13 dígitos).",
            "example": [
              {
                "accessKey": "0101202601179129015100120011000006079937846333315",
                "receiverIdentification": "1719956854"
              },
              {
                "accessKey": "0201202601179129015100120011000007108407846333313",
                "receiverIdentification": "1719956854001"
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccessKeyItemDto"
            }
          },
          "activeSession": {
            "description": "Sesión activa del SRI para reutilizar autenticación en el crawler. Aplica solo a tareas de compra (PURCHASE.*). Requiere viewState y cookiesString.",
            "example": {
              "viewState": "4836621168818476484:4051829485435980574",
              "cookiesString": "JSESSIONID=xxx; KEYCLOAK_SESSION=yyy",
              "totalDocumentos": 14
            },
            "allOf": [
              {
                "$ref": "#/components/schemas/ActiveSessionDto"
              }
            ]
          }
        },
        "required": [
          "type",
          "taxpayerId"
        ]
      },
      "CreateTaxpayerDto": {
        "type": "object",
        "properties": {
          "credential": {
            "type": "string",
            "example": "f7eec5865add4fb39173273c68022243",
            "description": "the identification of taxpayer, should be base64 encoded and separated by a colon character, for example: 12063423410001:MySuperSecretPassword"
          },
          "byPassCheckCredential": {
            "type": "boolean",
            "example": false,
            "description": "Flag to bypass credential check. If true, skips credential validation and creates taxpayer with provided data. Default: false",
            "default": false
          }
        },
        "required": [
          "credential"
        ]
      },
      "CreateWebhookDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "example": "https://example.com/webhook",
            "description": "The URL to which the webhook will send the notification."
          },
          "headers": {
            "example": [
              {
                "key": "Authorization",
                "value": "Bearer token"
              }
            ],
            "description": "The headers to include in the webhook request.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Header"
            }
          }
        },
        "required": [
          "url",
          "headers"
        ]
      },
      "EncryptedCredentialsResponseDto": {
        "type": "object",
        "properties": {
          "encryptedCredential": {
            "type": "string",
            "example": "aGVsbG8gd29ybGQ=",
            "description": "Credencial encriptada en base64. Desencriptar usando x-api-key como clave."
          },
          "iv": {
            "type": "string",
            "example": "a1b2c3d4e5f6a7b8c9d0e1f2",
            "description": "Vector de inicialización (IV) en hexadecimal para AES-256-GCM"
          },
          "salt": {
            "type": "string",
            "example": "f1e2d3c4b5a69788990a1b2c3d4e5f6",
            "description": "Salt en hexadecimal para derivación de clave con scrypt"
          },
          "authTag": {
            "type": "string",
            "example": "0123456789abcdef0123456789abcdef",
            "description": "Auth tag de GCM en hexadecimal para verificación de integridad"
          }
        },
        "required": [
          "encryptedCredential",
          "iv",
          "salt",
          "authTag"
        ]
      },
      "Header": {
        "type": "object",
        "properties": {}
      },
      "ImportStartedResponseDto": {
        "type": "object",
        "properties": {
          "extractionId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "description": "ID de la extracción para tracking"
          },
          "status": {
            "type": "string",
            "example": "INITIALIZED",
            "description": "Estado actual de la importación"
          },
          "message": {
            "type": "string",
            "example": "Importación iniciada. Recibirás notificación por webhook al completar.",
            "description": "Mensaje informativo"
          },
          "taxpayerIdentification": {
            "type": "string",
            "example": "1719956854001",
            "description": "RUC del contribuyente"
          },
          "organizationId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "description": "ID de la organización"
          }
        },
        "required": [
          "extractionId",
          "status",
          "message",
          "taxpayerIdentification",
          "organizationId"
        ]
      },
      "ImportTxtResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "5f7eec5865add4fb39173273c68022243",
            "description": "the identification of the task"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "example": "2023-12-14T20:39:01.000Z",
            "description": "the date when the task was created"
          },
          "status": {
            "type": "string",
            "enum": [
              "INITIALIZED",
              "IN_PROGRESS",
              "COMPLETED",
              "FAILED"
            ],
            "example": "INITIALIZED",
            "description": "the status of task"
          },
          "type": {
            "type": "string",
            "enum": [
              "PURCHASE.ALL",
              "PURCHASE.BILL",
              "PURCHASE.SETTLEMENT",
              "PURCHASE.CREDIT_NOTE",
              "PURCHASE.DEBIT_NOTE",
              "PURCHASE.REFERRAL_GUIDE",
              "PURCHASE.RETENTION",
              "TAXPAYER.REGIMEN",
              "TAXPAYER.OBLIGATIONS",
              "TAXPAYER.STATEMENTS.UPLOAD",
              "TAXPAYER.STATEMENTS.DOWNLOAD",
              "SALE.INVOICE",
              "SALE.CREDIT_NOTE",
              "SALE.SALE_RETENTION",
              "SALE.SETTLEMENT",
              "SALE.ALL",
              "VOIDS.ALL",
              "VOID.DOCUMENT",
              "RIDE",
              "TAXPAYER.OPINION",
              "TAXPAYER.SITUATION",
              "CFDI.INBOUND.ALL",
              "CFDI.OUTBOUND.ALL",
              "CATEGORY.INVOICE",
              "CATEGORY.CFDI"
            ],
            "example": "SALE.ALL",
            "description": "the type of task"
          },
          "starDownloadAt": {
            "type": "string",
            "example": "2023-12-14",
            "description": "the date when the task was started in format YYYY-MM-DD"
          },
          "documentsCount": {
            "type": "number",
            "example": 9,
            "description": "Numero de documentos validos en el TXT"
          },
          "taxpayerIdentification": {
            "type": "string",
            "example": "1726051285001",
            "description": "Identificacion del taxpayer (RUC/cedula) resuelta en base de datos"
          },
          "organizationId": {
            "type": "string",
            "example": "uuid-org",
            "description": "ID de la organizacion de la primera tarea creada (compatibilidad hacia atras)"
          },
          "organizationsCount": {
            "type": "number",
            "example": 2,
            "description": "Cantidad de organizaciones en las que se creo tarea (fan-out)"
          },
          "tasks": {
            "description": "Tareas creadas (una por organizacion con ese contribuyente)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportTxtTaskItemDto"
            }
          },
          "failedOrganizationIds": {
            "description": "Ids de organizaciones en las que fallo la creacion (el resto tuvo exito)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skippedTaxpayers": {
            "description": "Taxpayers omitidos (BAD_CREDENTIALS, DELETED o INACTIVE). No se creo tarea para esas organizaciones.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportTxtSkippedTaxpayerDto"
            }
          },
          "skippedOrganizations": {
            "description": "Organizaciones omitidas por no estar ACTIVE (contribuyente procesable pero organizacion inactiva o eliminada).",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportTxtSkippedOrganizationDto"
            }
          }
        },
        "required": [
          "id",
          "createdAt",
          "status",
          "type",
          "starDownloadAt",
          "documentsCount",
          "taxpayerIdentification",
          "organizationId",
          "organizationsCount",
          "tasks"
        ]
      },
      "ImportTxtSkippedOrganizationDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "INACTIVE",
              "DELETED"
            ]
          }
        },
        "required": [
          "organizationId",
          "status"
        ]
      },
      "ImportTxtSkippedTaxpayerDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "INACTIVE",
              "BAD_CREDENTIALS",
              "DELETED"
            ]
          }
        },
        "required": [
          "organizationId",
          "status"
        ]
      },
      "ImportTxtTaskItemDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "organizationId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "INITIALIZED",
              "IN_PROGRESS",
              "COMPLETED",
              "FAILED"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "PURCHASE.ALL",
              "PURCHASE.BILL",
              "PURCHASE.SETTLEMENT",
              "PURCHASE.CREDIT_NOTE",
              "PURCHASE.DEBIT_NOTE",
              "PURCHASE.REFERRAL_GUIDE",
              "PURCHASE.RETENTION",
              "TAXPAYER.REGIMEN",
              "TAXPAYER.OBLIGATIONS",
              "TAXPAYER.STATEMENTS.UPLOAD",
              "TAXPAYER.STATEMENTS.DOWNLOAD",
              "SALE.INVOICE",
              "SALE.CREDIT_NOTE",
              "SALE.SALE_RETENTION",
              "SALE.SETTLEMENT",
              "SALE.ALL",
              "VOIDS.ALL",
              "VOID.DOCUMENT",
              "RIDE",
              "TAXPAYER.OPINION",
              "TAXPAYER.SITUATION",
              "CFDI.INBOUND.ALL",
              "CFDI.OUTBOUND.ALL",
              "CATEGORY.INVOICE",
              "CATEGORY.CFDI"
            ]
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "organizationId",
          "status",
          "type",
          "createdAt"
        ]
      },
      "ListingFileResponseDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Signed URL de descarga del listado"
          },
          "fileName": {
            "type": "string",
            "description": "Nombre del archivo, tomado del final de la key en S3"
          },
          "expiresIn": {
            "type": "number",
            "description": "Vigencia del signed URL, en segundos"
          }
        },
        "required": [
          "url",
          "fileName",
          "expiresIn"
        ]
      },
      "MarkBadCredentialsDto": {
        "type": "object",
        "properties": {
          "ruc": {
            "type": "string",
            "example": "12063423410001",
            "description": "RUC (identification) of the taxpayer to mark as BAD_CREDENTIALS"
          }
        },
        "required": [
          "ruc"
        ]
      },
      "MarkBadCredentialsResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "identification": {
            "type": "string",
            "example": "12063423410001"
          },
          "status": {
            "type": "string",
            "enum": [
              "BAD_CREDENTIALS"
            ]
          },
          "badCredentialsAt": {
            "format": "date-time",
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "identification",
          "status",
          "badCredentialsAt"
        ]
      },
      "RejectedXmlDto": {
        "type": "object",
        "properties": {
          "fileName": {
            "type": "string",
            "example": "factura_001.xml",
            "description": "Nombre del archivo XML rechazado"
          },
          "reason": {
            "type": "string",
            "example": "No se pudo asignar a un contribuyente de la organización",
            "description": "Razón del rechazo"
          },
          "emitterRuc": {
            "type": "string",
            "example": "0912345678001",
            "description": "RUC del emisor extraído del XML (si se pudo determinar)"
          },
          "receiverRuc": {
            "type": "string",
            "example": "1234567890001",
            "description": "RUC del receptor extraído del XML (si se pudo determinar)"
          }
        },
        "required": [
          "fileName",
          "reason"
        ]
      },
      "RejectedZipDto": {
        "type": "object",
        "properties": {
          "fileName": {
            "type": "string",
            "example": "archivo2.zip",
            "description": "Nombre del archivo ZIP rechazado"
          },
          "reason": {
            "type": "string",
            "example": "Taxpayer no encontrado en la organización",
            "description": "Razón del rechazo"
          },
          "extractedRuc": {
            "type": "string",
            "example": "1234567890001",
            "description": "RUC extraído del ZIP (si se pudo determinar)"
          }
        },
        "required": [
          "fileName",
          "reason"
        ]
      },
      "RemoveContributorsDto": {
        "type": "object",
        "properties": {
          "contributorIds": {
            "description": "Lista de IDs de contribuyentes a asociar",
            "example": [
              1,
              2,
              3
            ],
            "type": "array",
            "items": {
              "type": "number"
            }
          },
          "taxpayerIds": {
            "description": "Lista de IDs de taxpayers a asociar",
            "example": [
              "1234567890",
              "0987654321"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "contributorIds",
          "taxpayerIds"
        ]
      },
      "RenameOrganizationDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Equipo Christian",
            "description": "The new display name of the organization"
          }
        },
        "required": [
          "name"
        ]
      },
      "ReplaceMemberTaxpayersDto": {
        "type": "object",
        "properties": {}
      },
      "ReplaceTaxpayerMembersDto": {
        "type": "object",
        "properties": {}
      },
      "ResponseContributorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number"
          },
          "ruc": {
            "type": "string"
          },
          "businessName": {
            "type": "string"
          },
          "tradeName": {
            "type": "string"
          },
          "contributorType": {
            "type": "string",
            "enum": [
              "CUSTOMER",
              "SUPPLIER"
            ],
            "description": "Tipo de contribuyente: CUSTOMER (Cliente) o SUPPLIER (Proveedor)",
            "example": "CUSTOMER"
          },
          "status": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "taxpayers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Taxpayer"
            }
          }
        },
        "required": [
          "id",
          "ruc",
          "businessName",
          "tradeName",
          "contributorType",
          "status",
          "type",
          "address",
          "phone",
          "email",
          "taxpayers"
        ]
      },
      "ResponseTaskDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "5f7eec5865add4fb39173273c68022243",
            "description": "the identification of the task"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "example": "2023-12-14T20:39:01.000Z",
            "description": "the date when the task was created"
          },
          "status": {
            "type": "string",
            "enum": [
              "INITIALIZED",
              "IN_PROGRESS",
              "COMPLETED",
              "FAILED"
            ],
            "example": "INITIALIZED",
            "description": "the status of task"
          },
          "type": {
            "type": "string",
            "enum": [
              "PURCHASE.ALL",
              "PURCHASE.BILL",
              "PURCHASE.SETTLEMENT",
              "PURCHASE.CREDIT_NOTE",
              "PURCHASE.DEBIT_NOTE",
              "PURCHASE.REFERRAL_GUIDE",
              "PURCHASE.RETENTION",
              "TAXPAYER.REGIMEN",
              "TAXPAYER.OBLIGATIONS",
              "TAXPAYER.STATEMENTS.UPLOAD",
              "TAXPAYER.STATEMENTS.DOWNLOAD",
              "SALE.INVOICE",
              "SALE.CREDIT_NOTE",
              "SALE.SALE_RETENTION",
              "SALE.SETTLEMENT",
              "SALE.ALL",
              "VOIDS.ALL",
              "VOID.DOCUMENT",
              "RIDE",
              "TAXPAYER.OPINION",
              "TAXPAYER.SITUATION",
              "CFDI.INBOUND.ALL",
              "CFDI.OUTBOUND.ALL",
              "CATEGORY.INVOICE",
              "CATEGORY.CFDI"
            ],
            "example": "SALE.ALL",
            "description": "the type of task"
          },
          "starDownloadAt": {
            "type": "string",
            "example": "2023-12-14",
            "description": "the date when the task was started in format YYYY-MM-DD"
          }
        },
        "required": [
          "id",
          "createdAt",
          "status",
          "type",
          "starDownloadAt"
        ]
      },
      "ResponseTaxpayerDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "12063423410001",
            "description": "the id of taxpayer"
          },
          "fullName": {
            "type": "string",
            "example": "John Doe",
            "description": "the name of taxpayer"
          },
          "identification": {
            "type": "string",
            "example": "12063423410001",
            "description": "the identification of taxpayer"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string",
            "example": "2023-12-06T08:23:19.000Z",
            "description": "the created date of a taxpayer"
          },
          "status": {
            "type": "string",
            "example": "ACTIVE | INACTIVE",
            "description": "the status of a taxpayer"
          },
          "priority": {
            "type": "number",
            "example": 1,
            "description": "the priority of a taxpayer"
          },
          "contacts": {
            "type": "string",
            "example": [
              {
                "kind": "EMAIL",
                "value": "foo@bar.com"
              },
              {
                "kind": "PHONE",
                "value": "3000000000"
              }
            ],
            "description": "the contacts of a taxpayer"
          },
          "legalRepresentative": {
            "type": "string",
            "example": {
              "identification": "12063423410001",
              "fullName": "John Doe"
            },
            "description": "the legal representative of a taxpayer"
          },
          "registrationType": {
            "type": "string",
            "example": "CIEC",
            "description": "Tipo de registro: CIEC, FIEL, o BOTH",
            "nullable": true
          }
        },
        "required": [
          "id",
          "fullName",
          "identification",
          "createdAt",
          "status",
          "priority",
          "contacts",
          "legalRepresentative",
          "registrationType"
        ]
      },
      "ResponseWebhookDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "12063423410001",
            "description": "the id of taxpayer"
          },
          "url": {
            "type": "string",
            "example": "https://webhook.site/",
            "description": "the webhook url"
          },
          "status": {
            "type": "string",
            "example": "ACTIVE | INACTIVE",
            "description": "the status of a webhook"
          },
          "headers": {
            "type": "string",
            "example": [
              {
                "key": "foo",
                "value": "bar"
              }
            ],
            "description": "the headers of a webhok"
          }
        },
        "required": [
          "id",
          "url",
          "status",
          "headers"
        ]
      },
      "SearchContributorsResponseDto": {
        "type": "object",
        "properties": {
          "contributors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResponseContributorDto"
            }
          },
          "total": {
            "type": "number"
          }
        },
        "required": [
          "contributors",
          "total"
        ]
      },
      "SuccessfulZipImportDto": {
        "type": "object",
        "properties": {
          "extractionId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "description": "ID de la extracción para tracking"
          },
          "status": {
            "type": "string",
            "example": "INITIALIZED",
            "description": "Estado actual de la importación"
          },
          "message": {
            "type": "string",
            "example": "Importación iniciada. Recibirás notificación por webhook al completar.",
            "description": "Mensaje informativo"
          },
          "taxpayerIdentification": {
            "type": "string",
            "example": "1719956854001",
            "description": "RUC del contribuyente"
          },
          "organizationId": {
            "type": "string",
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "description": "ID de la organización"
          },
          "fileName": {
            "type": "string",
            "example": "archivo1.zip",
            "description": "Nombre del archivo ZIP procesado"
          }
        },
        "required": [
          "extractionId",
          "status",
          "message",
          "taxpayerIdentification",
          "organizationId",
          "fileName"
        ]
      },
      "Taxpayer": {
        "type": "object",
        "properties": {}
      },
      "UpdateMemberRoleDto": {
        "type": "object",
        "properties": {}
      },
      "UpdateTaxpayerDto": {
        "type": "object",
        "properties": {
          "byPassCheckCredential": {
            "type": "boolean",
            "example": false,
            "description": "Flag to bypass credential check. If true, skips credential validation and updates taxpayer with provided data. Default: false",
            "default": false
          }
        }
      },
      "UpdateTokenDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID del token a actualizar"
          },
          "status": {
            "type": "string",
            "description": "Estado del token",
            "enum": [
              "ACTIVE",
              "INACTIVE"
            ],
            "example": "ACTIVE"
          }
        },
        "required": [
          "id",
          "status"
        ]
      },
      "UpdateWebhookDto": {
        "type": "object",
        "properties": {
          "headers": {
            "example": [
              {
                "key": "Authorization",
                "value": "Bearer token"
              }
            ],
            "description": "The headers to include in the webhook request.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Header"
            }
          }
        },
        "required": [
          "headers"
        ]
      },
      "UploadCertificatesResponseDto": {
        "type": "object",
        "properties": {
          "cer_s3_key": {
            "type": "string",
            "description": "S3 key (relative path) of the uploaded .cer file - use for cer_s3_key in extractions",
            "example": "certificates/AASI760413RP8/AASI760413RP8.cer"
          },
          "key_s3_key": {
            "type": "string",
            "description": "S3 key (relative path) of the uploaded .key file - use for key_s3_key in extractions",
            "example": "certificates/AASI760413RP8/AASI760413RP8.key"
          },
          "fullName": {
            "type": "string",
            "description": "Nombre del contribuyente extraído del certificado .cer (CN). Enviar en fullName al registrar con POST /taxpayers/fiel",
            "example": "SUAREZ CORO BRYAN BOLIVAR"
          }
        },
        "required": [
          "cer_s3_key",
          "key_s3_key"
        ]
      },
      "UploadZipAutoCreatedTaskDto": {
        "type": "object",
        "properties": {
          "taskId": {
            "type": "string",
            "description": "ID de la Task creada"
          },
          "organizationId": {
            "type": "string",
            "description": "ID de la organización donde se creó la Task"
          },
          "type": {
            "type": "string",
            "description": "TaskType detectado del primer XML",
            "example": "PURCHASE.BILL"
          }
        },
        "required": [
          "taskId",
          "organizationId",
          "type"
        ]
      },
      "UploadZipAutoResponseDto": {
        "type": "object",
        "properties": {
          "createdTasks": {
            "description": "Tasks creadas (una por cada combinación taxpayer + organización elegible).",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UploadZipAutoCreatedTaskDto"
            }
          },
          "taxpayerId": {
            "type": "string",
            "description": "RUC del taxpayer resuelto a partir del contenido del ZIP",
            "example": "1707723134001"
          },
          "s3Key": {
            "type": "string",
            "description": "S3 key del ZIP guardado (compartido entre todas las Tasks creadas)",
            "example": "zips/1707723134001/1707723134001_20260604_120000.zip"
          },
          "documentsCount": {
            "type": "number",
            "description": "Cantidad de XMLs detectados en el ZIP",
            "example": 5
          },
          "skippedTaxpayers": {
            "description": "Taxpayers omitidos por status no-ACTIVE (BAD_CREDENTIALS / DELETED / INACTIVE).",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UploadZipAutoSkippedItemDto"
            }
          },
          "skippedOrganizations": {
            "description": "Organizaciones omitidas por status no-ACTIVE.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UploadZipAutoSkippedItemDto"
            }
          },
          "failedOrganizationIds": {
            "description": "IDs de las organizaciones donde la creación de la Task falló (parcial).",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "createdTasks",
          "taxpayerId",
          "s3Key",
          "documentsCount"
        ]
      },
      "UploadZipAutoSkippedItemDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string",
            "description": "ID de la organización omitida"
          },
          "status": {
            "type": "string",
            "description": "Razón / estado de omisión"
          }
        },
        "required": [
          "organizationId",
          "status"
        ]
      },
      "UploadZipResponseDto": {
        "type": "object",
        "properties": {
          "s3Key": {
            "type": "string",
            "description": "S3 key (relative path) of the uploaded ZIP file - use this value for manualZipImport",
            "example": "zips/1707723134001/1707723134001_20260109_235454.zip"
          },
          "taxpayerId": {
            "type": "string",
            "description": "Taxpayer ID (RUC)",
            "example": "1707723134001"
          },
          "fileName": {
            "type": "string",
            "description": "File name generated with readable timestamp (YYYYMMDD_HHMMSS)",
            "example": "1707723134001_20260109_235454.zip"
          },
          "uploadedAt": {
            "format": "date-time",
            "type": "string",
            "description": "Upload timestamp",
            "example": "2025-01-09T12:00:00.000Z"
          }
        },
        "required": [
          "s3Key",
          "taxpayerId",
          "fileName",
          "uploadedAt"
        ]
      },
      "ValidateCredentialsBulkResponseDto": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string",
            "example": "validate_credentials_bulk_abc123",
            "description": "ID del job de validación masiva"
          },
          "totalTaxpayers": {
            "type": "number",
            "example": 15,
            "description": "Total de taxpayers a validar"
          },
          "message": {
            "type": "string",
            "example": "Validación masiva de credenciales iniciada. Se procesarán 15 taxpayers.",
            "description": "Mensaje descriptivo"
          }
        },
        "required": [
          "jobId",
          "totalTaxpayers",
          "message"
        ]
      },
      "ValidateCredentialsResponseDto": {
        "type": "object",
        "properties": {
          "isValid": {
            "type": "boolean",
            "example": true,
            "description": "Indica si las credenciales son válidas"
          },
          "status": {
            "type": "string",
            "example": "ACTIVE",
            "description": "El estado actual del taxpayer después de la validación"
          },
          "message": {
            "type": "string",
            "example": "Credenciales válidas. Taxpayer reactivado.",
            "description": "Mensaje descriptivo del resultado de la validación"
          }
        },
        "required": [
          "isValid",
          "status",
          "message"
        ]
      },
      "VoidDocumentDto": {
        "type": "object",
        "properties": {
          "ruc": {
            "type": "string",
            "example": "0123456789001",
            "description": "Taxpayer RUC"
          },
          "type": {
            "type": "string",
            "example": "01",
            "description": "Código del tipo de comprobante (01-07)"
          },
          "fechaAutorizacion": {
            "type": "string",
            "example": "13/11/2025",
            "description": "Fecha de autorización en formato dd/mm/yyyy"
          },
          "accessKey": {
            "type": "string",
            "example": "010520180117600132100120010110063009043924631114",
            "description": "Clave de acceso del documento (49 caracteres)"
          },
          "numeroAutorizacion": {
            "type": "string",
            "example": "010520180117600132100120010110063009043924631114",
            "description": "Número de autorización del documento (37-49 caracteres)"
          },
          "identificacionReceptor": {
            "type": "string",
            "example": "0999999999001",
            "description": "Identificación del receptor (RUC/Cédula)"
          },
          "correoElectronicoReceptor": {
            "type": "string",
            "example": "cliente@example.com",
            "description": "Correo electrónico del receptor"
          }
        },
        "required": [
          "ruc",
          "type",
          "fechaAutorizacion",
          "accessKey",
          "numeroAutorizacion",
          "identificacionReceptor",
          "correoElectronicoReceptor"
        ]
      }
    }
  }
}
