{"openapi":"3.1.0","info":{"title":"Firma Electrónica","description":"Servicio de firma electrónica simple (SES) con sellado de tiempo RFC 3161 (eIDAS art. 25).","version":"1.1.0"},"paths":{"/firma/documentos":{"post":{"tags":["firma"],"summary":"Upload Document","description":"Upload a PDF document and register it in the database.","operationId":"upload_document_firma_documentos_post","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_document_firma_documentos_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/solicitudes":{"post":{"tags":["firma"],"summary":"Create Signing Request","description":"Create a signing request and dispatch the signing link by email.","operationId":"create_signing_request_firma_solicitudes_post","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SigningRequestCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Signing Request Firma Solicitudes Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/firmar/{token}":{"get":{"tags":["firma"],"summary":"Signing Page","description":"Render the accessible signing page for the given one-time token.","operationId":"signing_page_firma_firmar__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/firmar/{token}/otp":{"post":{"tags":["firma"],"summary":"Request Otp","description":"Generate and send a one-time password linked to the signing request.","operationId":"request_otp_firma_firmar__token__otp_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_request_otp_firma_firmar__token__otp_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Request Otp Firma Firmar  Token  Otp Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/firmar/{token}/confirmar":{"post":{"tags":["firma"],"summary":"Confirm Signature","description":"Verify OTP and finalise the electronic signature with RSA and optional TSA.","operationId":"confirm_signature_firma_firmar__token__confirmar_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_confirm_signature_firma_firmar__token__confirmar_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Confirm Signature Firma Firmar  Token  Confirmar Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/solicitudes/{request_id}/estado":{"get":{"tags":["firma"],"summary":"Get Signing Status","description":"Return the current status of a signing request.","operationId":"get_signing_status_firma_solicitudes__request_id__estado_get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SigningStatusOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/documentos/{document_id}/solicitudes":{"get":{"tags":["firma"],"summary":"List Document Requests","description":"Return all signing requests associated with a given document.","operationId":"list_document_requests_firma_documentos__document_id__solicitudes_get","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SigningRequestOut"},"title":"Response List Document Requests Firma Documentos  Document Id  Solicitudes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/contratos":{"get":{"tags":["firma","contratos"],"summary":"List Contracts","description":"Return metadata for all available contract templates.","operationId":"list_contracts_firma_contratos_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Contracts Firma Contratos Get"}}}}}}},"/firma/firmar/{token}/documento":{"get":{"tags":["firma","firma"],"summary":"View Signing Document","description":"Serve the PDF being signed and record a document_viewed audit event.\n\nWHY (A4 fix): recording this event allows the system to prove the signee\nopened the document before signing, strengthening the informed-consent\nargument under CC arts. 1254-1262.","operationId":"view_signing_document_firma_firmar__token__documento_get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/documentos/{document_id}":{"delete":{"tags":["firma","firma"],"summary":"Delete Document","description":"Delete a document and all associated signing data (RGPD art. 17).\n\nDeletes from disk: the original PDF, any signed PDFs, handwritten sig PNGs,\nand the combined final PDF. Signing request records and audit events are\nanonymised (email/IP replaced with [suprimido]) rather than hard-deleted to\npreserve the integrity audit trail while removing personal data.","operationId":"delete_document_firma_documentos__document_id__delete","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Document Firma Documentos  Document Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/contratos/{template_id}/pdf":{"post":{"tags":["firma","contratos"],"summary":"Generate Contract","description":"Render a contract template with the supplied data and return a PDF.\n\nThe response has Content-Type application/pdf. Template variables should\nbe passed as a JSON object in the request body.","operationId":"generate_contract_firma_contratos__template_id__pdf_post","parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"default":{},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/info":{"post":{"tags":["pdf-tools"],"summary":"PDF metadata and page count","description":"Return basic information about a PDF: page count, encryption, form fields, metadata.","operationId":"tool_info_firma_tools_info_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_info_firma_tools_info_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Tool Info Firma Tools Info Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/office-to-pdf":{"post":{"tags":["pdf-tools"],"summary":"Convert Word/Excel/PowerPoint to PDF","description":"Convert .docx / .xlsx / .pptx / .odt / .ods to PDF via LibreOffice.","operationId":"tool_office_to_pdf_firma_tools_office_to_pdf_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_office_to_pdf_firma_tools_office_to_pdf_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/compress":{"post":{"tags":["pdf-tools"],"summary":"Reduce PDF file size with Ghostscript","description":"Compress a PDF. Levels: screen (smallest) → ebook → printer → prepress (highest quality).","operationId":"tool_compress_firma_tools_compress_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_compress_firma_tools_compress_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/to-pdfa":{"post":{"tags":["pdf-tools"],"summary":"Convert PDF to PDF/A-2b for legal archiving","description":"Convert a PDF to PDF/A-2b format, required for long-term legal archiving.","operationId":"tool_to_pdfa_firma_tools_to_pdfa_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_to_pdfa_firma_tools_to_pdfa_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/ocr":{"post":{"tags":["pdf-tools"],"summary":"Add text layer to scanned PDF via Tesseract","description":"Run OCR on a scanned PDF to make it searchable. lang examples: spa, eng, spa+eng.","operationId":"tool_ocr_firma_tools_ocr_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_ocr_firma_tools_ocr_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/watermark":{"post":{"tags":["pdf-tools"],"summary":"Add diagonal text watermark to every page","description":"Overlay a diagonal text watermark on every page of the PDF.","operationId":"tool_watermark_firma_tools_watermark_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_watermark_firma_tools_watermark_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/page-numbers":{"post":{"tags":["pdf-tools"],"summary":"Add page numbers to every page","description":"Add page numbers. format_str accepts {page} and {total} placeholders.","operationId":"tool_page_numbers_firma_tools_page_numbers_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_page_numbers_firma_tools_page_numbers_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/flatten":{"post":{"tags":["pdf-tools"],"summary":"Flatten form fields and annotations","description":"Flatten all form fields so the PDF can no longer be edited.","operationId":"tool_flatten_firma_tools_flatten_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_flatten_firma_tools_flatten_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/split":{"post":{"tags":["pdf-tools"],"summary":"Split PDF into multiple files by page range","description":"Split a PDF by page ranges.\n\nranges: comma-separated pairs like '1-3,4-6,7-10'. Returns base64-encoded PDFs.","operationId":"tool_split_firma_tools_split_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_split_firma_tools_split_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Tool Split Firma Tools Split Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/extract-pages":{"post":{"tags":["pdf-tools"],"summary":"Extract specific pages into a new PDF","description":"Extract pages (1-indexed, comma-separated). Example: pages=1,3,5","operationId":"tool_extract_pages_firma_tools_extract_pages_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_extract_pages_firma_tools_extract_pages_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/rotate":{"post":{"tags":["pdf-tools"],"summary":"Rotate PDF pages","description":"Rotate pages by 90, 180 or 270 degrees. pages: comma-separated 1-indexed numbers, or empty for all.","operationId":"tool_rotate_firma_tools_rotate_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_rotate_firma_tools_rotate_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/redact":{"post":{"tags":["pdf-tools"],"summary":"Black-out text matching regex patterns","description":"Redact (permanently black-out) text matching the given regex patterns.\n\npatterns: newline- or comma-separated regex strings.\nExamples: NIF pattern '[0-9]{8}[A-Z]', IBAN 'ES[0-9]{22}'.","operationId":"tool_redact_firma_tools_redact_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_redact_firma_tools_redact_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/metadata":{"post":{"tags":["pdf-tools"],"summary":"Set PDF metadata fields","description":"Set PDF metadata (title, author, subject, keywords).","operationId":"tool_metadata_firma_tools_metadata_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_metadata_firma_tools_metadata_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/protect":{"post":{"tags":["pdf-tools"],"summary":"Password-protect a PDF (AES-256)","description":"Encrypt a PDF with AES-256. The password is required to open it.","operationId":"tool_protect_firma_tools_protect_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_protect_firma_tools_protect_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/unprotect":{"post":{"tags":["pdf-tools"],"summary":"Remove PDF password protection","description":"Remove password protection from a PDF.","operationId":"tool_unprotect_firma_tools_unprotect_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_unprotect_firma_tools_unprotect_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/images-to-pdf":{"post":{"tags":["pdf-tools"],"summary":"Convert images (PNG/JPEG) to PDF","description":"Combine one or more images into a single PDF document.","operationId":"tool_images_to_pdf_firma_tools_images_to_pdf_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_images_to_pdf_firma_tools_images_to_pdf_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/tools/pdf-to-images":{"post":{"tags":["pdf-tools"],"summary":"Render PDF pages as PNG images","description":"Render each PDF page as a PNG image. Returns base64-encoded images.","operationId":"tool_pdf_to_images_firma_tools_pdf_to_images_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_tool_pdf_to_images_firma_tools_pdf_to_images_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Tool Pdf To Images Firma Tools Pdf To Images Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/metering":{"get":{"tags":["admin-metering","admin-metering"],"summary":"Read All Tenants Stats","description":"Return usage statistics for all tenants.\n\nArgs:\n    from_date: Optional inclusive lower-bound ISO date (YYYY-MM-DD).\n    to_date: Optional inclusive upper-bound ISO date (YYYY-MM-DD).\n    ctx: Authenticated tenant context (must be superadmin).\n    db: Database session.\n\nReturns:\n    A list of per-tenant statistics dicts.","operationId":"read_all_tenants_stats_admin_metering_get","parameters":[{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Date"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Read All Tenants Stats Admin Metering Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/metering/{tenant}":{"get":{"tags":["admin-metering","admin-metering"],"summary":"Read Tenant Stats","description":"Return usage statistics for a single tenant.\n\nArgs:\n    tenant: Tenant identifier to aggregate.\n    from_date: Optional inclusive lower-bound ISO date (YYYY-MM-DD).\n    to_date: Optional inclusive upper-bound ISO date (YYYY-MM-DD).\n    ctx: Authenticated tenant context (must be superadmin).\n    db: Database session.\n\nReturns:\n    A statistics dict for the requested tenant.","operationId":"read_tenant_stats_admin_metering__tenant__get","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Date"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Read Tenant Stats Admin Metering  Tenant  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/metering/{tenant}/daily":{"get":{"tags":["admin-metering","admin-metering"],"summary":"Read Tenant Daily","description":"Return a per-day usage breakdown for a single tenant.\n\nArgs:\n    tenant: Tenant identifier to aggregate.\n    from_date: Required inclusive lower-bound ISO date (YYYY-MM-DD).\n    to_date: Required inclusive upper-bound ISO date (YYYY-MM-DD).\n    ctx: Authenticated tenant context (must be superadmin).\n    db: Database session.\n\nReturns:\n    A list of per-day breakdown dicts ordered chronologically.","operationId":"read_tenant_daily_admin_metering__tenant__daily_get","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}},{"name":"from_date","in":"query","required":true,"schema":{"type":"string","title":"From Date"}},{"name":"to_date","in":"query","required":true,"schema":{"type":"string","title":"To Date"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Read Tenant Daily Admin Metering  Tenant  Daily Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/webhooks":{"post":{"tags":["webhooks","webhooks"],"summary":"Create Webhook","description":"Create a webhook subscription for the authenticated tenant.\n\nThe tenant is taken from the API key context, never from the request body.","operationId":"create_webhook_firma_webhooks_post","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["webhooks","webhooks"],"summary":"List Webhooks","description":"List all webhook subscriptions owned by the authenticated tenant.","operationId":"list_webhooks_firma_webhooks_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookOut"},"title":"Response List Webhooks Firma Webhooks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/webhooks/{webhook_id}":{"delete":{"tags":["webhooks","webhooks"],"summary":"Delete Webhook","description":"Delete a webhook subscription.\n\nA tenant may delete only its own subscriptions; a superadmin may delete\nany subscription.","operationId":"delete_webhook_firma_webhooks__webhook_id__delete","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/webhooks/{webhook_id}/test":{"post":{"tags":["webhooks","webhooks"],"summary":"Test Webhook","description":"Send a mock payload to a subscription to verify connectivity.\n\nGenerates a synthetic `document_signed` payload and delivers it\nsynchronously, returning the resulting HTTP status and any error message.","operationId":"test_webhook_firma_webhooks__webhook_id__test_post","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Test Webhook Firma Webhooks  Webhook Id  Test Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tenants":{"get":{"tags":["admin","admin"],"summary":"List Tenants","description":"List every tenant owning at least one document, with aggregate stats.","operationId":"list_tenants_admin_tenants_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Tenants Admin Tenants Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/documents":{"get":{"tags":["admin","admin"],"summary":"List Documents","description":"List documents with optional tenant/status filters and pagination.\n\nThe total number of matching documents is returned in the\n``X-Total-Count`` response header.","operationId":"list_documents_admin_documents_get","parameters":[{"name":"tenant","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","pattern":"^(signed|pending|all)$","default":"all","title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/documents/{document_id}/audit":{"get":{"tags":["admin","admin"],"summary":"Document Audit","description":"Return the complete audit trail of a document.\n\nIncludes every SigningRequest and each of their AuditEvents.\n\nRaises:\n    HTTPException: 404 if the document does not exist.","operationId":"document_audit_admin_documents__document_id__audit_get","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Document Audit Admin Documents  Document Id  Audit Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/stats":{"get":{"tags":["admin","admin"],"summary":"Global Stats","description":"Return global service statistics across all tenants.","operationId":"global_stats_admin_stats_get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Global Stats Admin Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/tenants/{tenant}/data":{"delete":{"tags":["admin","admin"],"summary":"Delete Tenant Data","description":"Delete all data of a tenant (RGPD art. 17 right to erasure).\n\nRefuses to delete while any SigningRequest of the tenant is still pending.\n\nRaises:\n    HTTPException: 409 if pending signing requests exist for the tenant.\n\nReturns:\n    A dict with the number of deleted documents.","operationId":"delete_tenant_data_admin_tenants__tenant__data_delete","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Tenant Data Admin Tenants  Tenant  Data Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/":{"get":{"tags":["admin","admin"],"summary":"Admin Dashboard","description":"Render the HTML administration dashboard.","operationId":"admin_dashboard_admin__get","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/verificar":{"get":{"tags":["verificacion"],"summary":"Verificar Buscador","description":"Render the public document search form, or redirect to a verification.\n\nActs as a no-JS fallback: when the search form submits with a\n``document_id`` query parameter, redirect to the canonical path-based\nverification URL ``/verificar/{document_id}``.\n\nArgs:\n    document_id: Optional document id submitted by the search form.\n\nReturns:\n    A redirect to the verification page, or the HTML search form.","operationId":"verificar_buscador_verificar_get","parameters":[{"name":"document_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/verificar/{document_id}":{"get":{"tags":["verificacion"],"summary":"Verificar Documento","description":"Render the public verification page for a document.\n\nArgs:\n    document_id: Identifier of the document to verify.\n    db: Database session.\n\nReturns:\n    HTML response with verification results, or a not-found message.","operationId":"verificar_documento_verificar__document_id__get","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/mis-documentos":{"get":{"tags":["verificacion"],"summary":"Mis Documentos","description":"List the authenticated tenant's documents with pagination and filtering.\n\nArgs:\n    status: Filter by aggregate status (``all``/``signed``/``pending``).\n    page: 1-based page number.\n    ctx: Tenant context resolved from the API key.\n    db: Database session.\n\nReturns:\n    HTML response with the paginated document table.","operationId":"mis_documentos_firma_mis_documentos_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"all","title":"Status"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/firma/documentos/{document_id}/signed-pdf":{"get":{"tags":["verificacion"],"summary":"Signed Pdf","description":"Return the signed PDF for a document's first signed request.\n\nArgs:\n    document_id: Identifier of the document.\n    ctx: Tenant context resolved from the API key.\n    db: Database session.\n\nReturns:\n    A PDF attachment response.\n\nRaises:\n    HTTPException: 404 if the document or signed PDF is missing, 403 if the\n        tenant does not own the document and is not a superadmin.","operationId":"signed_pdf_firma_documentos__document_id__signed_pdf_get","parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}},{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["monitoring"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}}},"components":{"schemas":{"Body_confirm_signature_firma_firmar__token__confirmar_post":{"properties":{"otp_code":{"type":"string","title":"Otp Code"},"declaration_accepted":{"type":"boolean","title":"Declaration Accepted"},"firma_imagen_b64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Firma Imagen B64"}},"type":"object","required":["otp_code","declaration_accepted"],"title":"Body_confirm_signature_firma_firmar__token__confirmar_post"},"Body_request_otp_firma_firmar__token__otp_post":{"properties":{"declaration_accepted":{"type":"boolean","title":"Declaration Accepted"}},"type":"object","required":["declaration_accepted"],"title":"Body_request_otp_firma_firmar__token__otp_post"},"Body_tool_compress_firma_tools_compress_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"level":{"type":"string","enum":["screen","ebook","printer","prepress"],"title":"Level","default":"ebook"}},"type":"object","required":["file"],"title":"Body_tool_compress_firma_tools_compress_post"},"Body_tool_extract_pages_firma_tools_extract_pages_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"pages":{"type":"string","title":"Pages","default":"1"}},"type":"object","required":["file"],"title":"Body_tool_extract_pages_firma_tools_extract_pages_post"},"Body_tool_flatten_firma_tools_flatten_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_tool_flatten_firma_tools_flatten_post"},"Body_tool_images_to_pdf_firma_tools_images_to_pdf_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"},"page_size":{"type":"string","enum":["a4","letter","legal"],"title":"Page Size","default":"a4"}},"type":"object","required":["files"],"title":"Body_tool_images_to_pdf_firma_tools_images_to_pdf_post"},"Body_tool_info_firma_tools_info_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_tool_info_firma_tools_info_post"},"Body_tool_metadata_firma_tools_metadata_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"title":{"type":"string","title":"Title","default":""},"author":{"type":"string","title":"Author","default":""},"subject":{"type":"string","title":"Subject","default":""},"keywords":{"type":"string","title":"Keywords","default":""}},"type":"object","required":["file"],"title":"Body_tool_metadata_firma_tools_metadata_post"},"Body_tool_ocr_firma_tools_ocr_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"lang":{"type":"string","title":"Lang","default":"spa+eng"}},"type":"object","required":["file"],"title":"Body_tool_ocr_firma_tools_ocr_post"},"Body_tool_office_to_pdf_firma_tools_office_to_pdf_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_tool_office_to_pdf_firma_tools_office_to_pdf_post"},"Body_tool_page_numbers_firma_tools_page_numbers_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"position":{"type":"string","enum":["bottom-center","bottom-right","bottom-left"],"title":"Position","default":"bottom-center"},"start":{"type":"integer","minimum":1.0,"title":"Start","default":1},"format_str":{"type":"string","title":"Format Str","default":"{page} / {total}"}},"type":"object","required":["file"],"title":"Body_tool_page_numbers_firma_tools_page_numbers_post"},"Body_tool_pdf_to_images_firma_tools_pdf_to_images_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"dpi":{"type":"integer","maximum":600.0,"minimum":72.0,"title":"Dpi","default":150}},"type":"object","required":["file"],"title":"Body_tool_pdf_to_images_firma_tools_pdf_to_images_post"},"Body_tool_protect_firma_tools_protect_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"password":{"type":"string","minLength":4,"title":"Password"}},"type":"object","required":["file"],"title":"Body_tool_protect_firma_tools_protect_post"},"Body_tool_redact_firma_tools_redact_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"patterns":{"type":"string","title":"Patterns","default":""}},"type":"object","required":["file"],"title":"Body_tool_redact_firma_tools_redact_post"},"Body_tool_rotate_firma_tools_rotate_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"rotation":{"type":"integer","enum":[90,180,270],"title":"Rotation","default":90},"pages":{"type":"string","title":"Pages","default":""}},"type":"object","required":["file"],"title":"Body_tool_rotate_firma_tools_rotate_post"},"Body_tool_split_firma_tools_split_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"ranges":{"type":"string","title":"Ranges","default":"1-1"}},"type":"object","required":["file"],"title":"Body_tool_split_firma_tools_split_post"},"Body_tool_to_pdfa_firma_tools_to_pdfa_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_tool_to_pdfa_firma_tools_to_pdfa_post"},"Body_tool_unprotect_firma_tools_unprotect_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"password":{"type":"string","title":"Password"}},"type":"object","required":["file"],"title":"Body_tool_unprotect_firma_tools_unprotect_post"},"Body_tool_watermark_firma_tools_watermark_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"text":{"type":"string","title":"Text","default":"FIRMADO ELECTRÓNICAMENTE"},"opacity":{"type":"number","maximum":1.0,"minimum":0.01,"title":"Opacity","default":0.12},"angle":{"type":"number","maximum":360.0,"minimum":0.0,"title":"Angle","default":45.0}},"type":"object","required":["file"],"title":"Body_tool_watermark_firma_tools_watermark_post"},"Body_upload_document_firma_documentos_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"tenant":{"type":"string","title":"Tenant"},"uploaded_by":{"type":"string","title":"Uploaded By"},"lang":{"type":"string","title":"Lang","default":"es"}},"type":"object","required":["file","tenant","uploaded_by"],"title":"Body_upload_document_firma_documentos_post"},"DocumentOut":{"properties":{"id":{"type":"string","title":"Id"},"filename":{"type":"string","title":"Filename"},"original_sha256":{"type":"string","title":"Original Sha256"},"tenant":{"type":"string","title":"Tenant"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At"},"retention_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Retention Until"}},"type":"object","required":["id","filename","original_sha256","tenant","uploaded_at"],"title":"DocumentOut","description":"Public representation of a stored document."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"SigningRequestCreate":{"properties":{"document_id":{"type":"string","title":"Document Id"},"signee_email":{"type":"string","title":"Signee Email"},"signee_name":{"type":"string","title":"Signee Name"},"lang":{"type":"string","title":"Lang","default":"es"}},"type":"object","required":["document_id","signee_email","signee_name"],"title":"SigningRequestCreate","description":"Payload to create a new signing request for a document."},"SigningRequestOut":{"properties":{"id":{"type":"string","title":"Id"},"document_id":{"type":"string","title":"Document Id"},"signee_email":{"type":"string","title":"Signee Email"},"signee_name":{"type":"string","title":"Signee Name"},"status":{"type":"string","enum":["pending","email_sent","otp_sent","signed","cancelled"],"title":"Status"},"signed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Signed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"lang":{"type":"string","title":"Lang"}},"type":"object","required":["id","document_id","signee_email","signee_name","status","signed_at","created_at","lang"],"title":"SigningRequestOut","description":"Public representation of a signing request."},"SigningStatusOut":{"properties":{"status":{"type":"string","enum":["pending","email_sent","otp_sent","signed","cancelled"],"title":"Status"},"signed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Signed At"},"signee_email":{"type":"string","title":"Signee Email"},"document_title":{"type":"string","title":"Document Title"},"lang":{"type":"string","title":"Lang"}},"type":"object","required":["status","signed_at","signee_email","document_title","lang"],"title":"SigningStatusOut","description":"Status summary returned to a signee checking their signing link."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebhookCreate":{"properties":{"url":{"type":"string","title":"Url"},"secret":{"type":"string","title":"Secret"},"events":{"items":{"type":"string"},"type":"array","title":"Events"}},"type":"object","required":["url","secret","events"],"title":"WebhookCreate","description":"Schema for creating a webhook subscription.\n\nThe tenant is taken from the authenticated context, never from the body."},"WebhookOut":{"properties":{"id":{"type":"string","title":"Id"},"tenant":{"type":"string","title":"Tenant"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"},"active":{"type":"boolean","title":"Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_delivery_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Delivery At"},"last_delivery_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Delivery Status"}},"type":"object","required":["id","tenant","url","events","active","created_at"],"title":"WebhookOut","description":"Response schema. Excludes `secret` to avoid leaking the HMAC key."}}}}