openapi: 3.1.0 info: title: PDF Count API description: Conteo de servicios facturados en facturas médicas PDF. version: 1.0.0 servers: - url: http://localhost:8080 paths: /health: get: summary: Liveness probe responses: "200": description: OK /ready: get: summary: Readiness probe responses: "200": description: Ready /v1/count: post: summary: Conteo síncrono (hasta 50 PDFs) parameters: - name: include_rejected in: query schema: type: boolean default: false requestBody: required: true content: multipart/form-data: schema: type: object properties: files: type: array items: type: string format: binary responses: "200": description: Resultados por PDF content: application/json: schema: $ref: "#/components/schemas/CountResponse" /v1/jobs: post: summary: Crear job asíncrono requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateJobRequest" responses: "202": description: Job aceptado content: application/json: schema: $ref: "#/components/schemas/JobStatus" /v1/jobs/{jobID}: get: summary: Estado del job parameters: - name: jobID in: path required: true schema: type: string - name: wait_ms in: query description: Long-polling; espera hasta wait_ms (máx. 30000) a que el job cambie de estado schema: type: integer minimum: 0 maximum: 30000 responses: "200": description: Progreso content: application/json: schema: $ref: "#/components/schemas/JobStatus" delete: summary: Cancelar job parameters: - name: jobID in: path required: true schema: type: string responses: "200": description: Cancelado /v1/jobs/{jobID}/upload: post: summary: Subir chunk de PDFs a un job parameters: - name: jobID in: path required: true schema: type: string - name: include_rejected in: query schema: type: boolean requestBody: content: multipart/form-data: schema: type: object properties: files: type: array items: type: string format: binary responses: "202": description: Chunk aceptado /v1/jobs/{jobID}/results: get: summary: Resultados paginados parameters: - name: jobID in: path required: true schema: type: string - name: cursor in: query schema: type: string - name: limit in: query schema: type: integer default: 500 responses: "200": description: Página de resultados content: application/json: schema: $ref: "#/components/schemas/JobResultsPage" components: schemas: ServiceRow: type: object properties: text: type: string probability: type: number format: float is_service: type: boolean PDFResult: type: object properties: filename: type: string service_count: type: integer status: type: string enum: [ok, error, pending] services: type: array items: $ref: "#/components/schemas/ServiceRow" error: type: string CountResponse: type: object properties: results: type: array items: $ref: "#/components/schemas/PDFResult" processed: type: integer failed: type: integer JobStatus: type: object properties: job_id: type: string status: type: string total: type: integer processed: type: integer failed: type: integer JobResultsPage: type: object properties: job_id: type: string results: type: array items: $ref: "#/components/schemas/PDFResult" next_cursor: type: string has_more: type: boolean CreateJobRequest: type: object properties: files: type: array items: type: string prefix: type: string description: Prefijo MinIO con PDFs ya subidos include_rejected: type: boolean default: false callback_url: type: string