{"openapi":"3.1.0","info":{"title":"DocGen API","description":"Document Generator — HTML to PDF/DOCX/ODT via LibreOffice. Supports templates, images, QR codes, tables, watermarks, page settings, multi-document composition, ZUGFeRD/XRechnung e-invoices, and asynchronous generation.","contact":{"name":"Dokmatiq","url":"https://dokmatiq.com","email":"support@dokmatiq.com"},"version":"0.1.0"},"servers":[{"url":"https://api.dokmatiq.com","description":"Generated server url"}],"tags":[{"name":"Auth","description":"Authentication and API key validation endpoints"},{"name":"PDF Tools","description":"Merge, split, extract pages, set metadata, and rotate PDFs"},{"name":"ZUGFeRD / Factur-X","description":"Embed, extract, and validate ZUGFeRD/Factur-X e-invoices in PDFs"},{"name":"Excel","description":"Generate, convert, and fill Excel workbooks (XLSX)"},{"name":"PDF Forms","description":"Inspect and fill PDF form fields (AcroForms)"},{"name":"Receipts","description":"AI-powered receipt and ticket data extraction, batch processing, and export"},{"name":"Admin","description":"Administration and usage tracking endpoints"},{"name":"Digital Signatures","description":"Sign PDFs with certificates, verify signatures, manage certificates"},{"name":"Preview","description":"Generate PDF page previews as PNG/JPEG images"},{"name":"Fonts","description":"Custom font management for PDF content areas and headers/footers"},{"name":"Documents","description":"Document generation, composition, and e-invoice operations"},{"name":"XRechnung","description":"XRechnung e-invoice generation, parsing, validation, and transformation (CII & UBL)"}],"paths":{"/api/zugferd/validate":{"post":{"tags":["ZUGFeRD / Factur-X"],"summary":"Validate a ZUGFeRD/Factur-X PDF","description":"Validates a PDF against ZUGFeRD/Factur-X/XRechnung standards. Returns whether the document is valid and a detailed validation report.","operationId":"validate","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PDF file to validate"}},"required":["file"]}}}},"responses":{"200":{"description":"Validation result","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}},"500":{"description":"Validation failed","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/zugferd/validate/base64":{"post":{"tags":["ZUGFeRD / Factur-X"],"summary":"Validate a ZUGFeRD/Factur-X PDF (Base64)","description":"Validates a Base64-encoded PDF against ZUGFeRD/Factur-X standards.","operationId":"validateBase64","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Validation result","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}},"500":{"description":"Validation failed","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/zugferd/extract":{"post":{"tags":["ZUGFeRD / Factur-X"],"summary":"Extract invoice from ZUGFeRD PDF","description":"Extracts structured invoice data (seller, buyer, items, totals, bank details) from a ZUGFeRD/Factur-X PDF. Also returns the raw embedded XML.","operationId":"extract","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"ZUGFeRD/Factur-X PDF file"}},"required":["file"]}}}},"responses":{"200":{"description":"Extracted invoice data","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}},"500":{"description":"Extraction failed","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/zugferd/extract/base64":{"post":{"tags":["ZUGFeRD / Factur-X"],"summary":"Extract invoice from ZUGFeRD PDF (Base64)","description":"Extracts invoice data from a Base64-encoded ZUGFeRD/Factur-X PDF.","operationId":"extractBase64","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Extracted invoice data","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}},"500":{"description":"Extraction failed","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/zugferd/embed":{"post":{"tags":["ZUGFeRD / Factur-X"],"summary":"Embed ZUGFeRD invoice into an existing PDF","description":"Takes an existing PDF and invoice data, converts the PDF to PDF/A-3 and embeds a ZUGFeRD/Factur-X XML invoice. The invoice data is passed as a JSON part. Supported profiles: MINIMUM, BASICWL, BASIC, EN16931 (default), EXTENDED, XRECHNUNG.","operationId":"embed","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PDF file to embed the invoice into"},"invoice":{"$ref":"#/components/schemas/InvoiceData"}},"required":["file","invoice"]}}}},"responses":{"200":{"description":"ZUGFeRD PDF","content":{"application/pdf":{}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}},"500":{"description":"Embedding failed","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/zugferd/embed/base64":{"post":{"tags":["ZUGFeRD / Factur-X"],"summary":"Embed ZUGFeRD invoice into an existing PDF (Base64)","description":"Takes a Base64-encoded PDF and invoice data, converts to PDF/A-3 and embeds a ZUGFeRD/Factur-X XML invoice. Returns the ZUGFeRD PDF as binary.","operationId":"embedBase64","requestBody":{"description":"Request with Base64-encoded PDF and invoice data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZugferdEmbedRequest"}}},"required":true},"responses":{"200":{"description":"ZUGFeRD PDF","content":{"application/pdf":{}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}},"500":{"description":"Embedding failed","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/xrechnung/validate":{"post":{"tags":["XRechnung"],"summary":"Validate XRechnung XML","description":"Validates an XRechnung XML file against EN 16931 schema and business rules. Returns a detailed validation report.","operationId":"validate_1","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"XRechnung XML file"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/xrechnung/transform":{"post":{"tags":["XRechnung"],"summary":"Transform XRechnung between CII and UBL","description":"Transforms an XRechnung XML file from CII to UBL format. The source format is auto-detected. Currently supports CII → UBL transformation.","operationId":"transform","parameters":[{"name":"targetFormat","in":"query","description":"Target format","required":false,"schema":{"type":"string","default":"UBL","description":"XRechnung XML syntax format","enum":["CII","UBL"]}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"XRechnung XML file"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/xrechnung/parse":{"post":{"tags":["XRechnung"],"summary":"Parse XRechnung XML","description":"Parses an XRechnung XML file (CII or UBL) and returns structured invoice data as JSON. The format is auto-detected from the XML content.","operationId":"parse","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"XRechnung XML file"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/xrechnung/generate":{"post":{"tags":["XRechnung"],"summary":"Generate XRechnung XML","description":"Generates a standalone XRechnung XML invoice from structured invoice data. Supports CII (Cross Industry Invoice) and UBL (Universal Business Language) formats. Set 'xrechnungFormat' in the request to choose the output format (default: CII).","operationId":"generate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceData"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/xrechnung/extract":{"post":{"tags":["XRechnung"],"summary":"Extract invoice data from PDF or image using AI","description":"Extracts structured invoice data from a PDF invoice or photo (JPG, PNG) using Claude AI (claude-haiku).\n\nThe endpoint handles two input types:\n- **Text-based PDF**: Extracts text with PDFBox, sends to Claude for structured extraction\n- **Scanned PDF / Photo**: Sends directly to Claude Vision for OCR + extraction\n\nReturns structured InvoiceData as JSON, ready to pass to /generate or /zugferd/embed.\nMissing fields (e.g. Leitweg-ID) are listed in `missingFields` — these should be\nfilled from user profile data in the portal before generating the e-invoice.\n\nRequires `ANTHROPIC_API_KEY` environment variable. Without it, only PDF text extraction\nis performed and `aiExtractionUsed` will be false.\n","operationId":"extract_1","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PDF invoice or invoice photo (JPG, PNG, WEBP)"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ExtractionResult"}}}}}}},"/api/xrechnung/detect":{"post":{"tags":["XRechnung"],"summary":"Detect XRechnung format","description":"Detects whether an XML file is in CII or UBL format.","operationId":"detect","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"XRechnung XML file"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/templates":{"get":{"tags":["template-controller"],"operationId":"listTemplates","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"type":"string"}}}}}}},"post":{"tags":["template-controller"],"operationId":"uploadTemplate","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}}}}},"/api/signatures/verify":{"post":{"tags":["Digital Signatures"],"summary":"Verify PDF signatures (file upload)","description":"Upload a signed PDF to verify all embedded digital signatures. Returns signer details, certificate info, integrity status, and timestamp info.","operationId":"verifySignatures","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Verification result","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SignatureVerifyResult"}}}},"400":{"description":"Invalid PDF","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/signatures/verify/base64":{"post":{"tags":["Digital Signatures"],"summary":"Verify PDF signatures (Base64)","description":"Submit a Base64-encoded signed PDF to verify all embedded digital signatures.","operationId":"verifySignaturesBase64","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Verification result","content":{"*/*":{"schema":{"$ref":"#/components/schemas/SignatureVerifyResult"}}}},"400":{"description":"Invalid PDF","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/signatures/sign":{"post":{"tags":["Digital Signatures"],"summary":"Sign a PDF (Base64)","description":"Digitally sign a PDF using a PKCS#12 certificate. The certificate can be referenced by name (pre-uploaded) or provided inline as Base64. Optionally includes a visible signature and/or a trusted timestamp.","operationId":"signPdf","parameters":[{"name":"X-DocGen-Validate","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignatureRequest"}}},"required":true},"responses":{"200":{"description":"Signed PDF","content":{"application/pdf":{}}},"400":{"description":"Invalid request or certificate","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/signatures/sign/upload":{"post":{"tags":["Digital Signatures"],"summary":"Sign a PDF (file upload)","description":"Upload a PDF and a PKCS#12 certificate to sign the document. Alternative to the Base64-based endpoint.","operationId":"signPdfUpload","parameters":[{"name":"password","in":"query","required":true,"schema":{"type":"string"}},{"name":"reason","in":"query","required":false,"schema":{"type":"string"}},{"name":"location","in":"query","required":false,"schema":{"type":"string"}},{"name":"contactInfo","in":"query","required":false,"schema":{"type":"string"}},{"name":"signerName","in":"query","required":false,"schema":{"type":"string"}},{"name":"timestampUrl","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"pdf":{"type":"string","format":"binary"},"certificate":{"type":"string","format":"binary"}},"required":["certificate","pdf"]}}}},"responses":{"200":{"description":"Signed PDF","content":{"application/pdf":{}}},"400":{"description":"Invalid request or certificate","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/signatures/certificates":{"get":{"tags":["Digital Signatures"],"summary":"List stored certificates","description":"Returns all stored certificate files.","operationId":"listCertificates","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"post":{"tags":["Digital Signatures"],"summary":"Upload a PKCS#12 certificate","description":"Upload a .p12 or .pfx certificate file for PDF signing. The certificate is stored on the server and can be referenced by name in sign requests.","operationId":"uploadCertificate","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PKCS#12 certificate file (.p12 or .pfx)"}},"required":["file"]}}}},"responses":{"200":{"description":"Certificate stored","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}},"400":{"description":"Invalid certificate format","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}}}}},"/api/signatures/certificates/info":{"post":{"tags":["Digital Signatures"],"summary":"Inspect certificate details","description":"Upload a PKCS#12 certificate and retrieve its details (subject, issuer, validity) without storing it on the server.","operationId":"inspectCertificate","parameters":[{"name":"password","in":"query","description":"Certificate password","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PKCS#12 certificate file"}},"required":["file"]}}}},"responses":{"200":{"description":"Certificate details","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid certificate or wrong password","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/receipts/to-document":{"post":{"tags":["Receipts"],"summary":"Extract receipt and generate expense report document","description":"Combines receipt extraction and document generation in a single call.\n\n1. Extracts data from the uploaded receipt image using AI\n2. Generates a formatted expense report PDF or DOCX using the extracted data\n\nOptionally provide a template name to use a custom expense report template. Without a template, a clean default HTML-based expense report is generated.\n\nThis endpoint consumes AI credits for the extraction step plus standard credits for the document generation.\n","operationId":"receiptToDocument","parameters":[{"name":"format","in":"query","description":"Output format (PDF or DOCX)","required":false,"schema":{"type":"string","default":"PDF"}},{"name":"templateName","in":"query","description":"Optional template name for expense report layout","required":false,"schema":{"type":"string"}},{"name":"title","in":"query","description":"Document title / heading","required":false,"schema":{"type":"string","default":"Spesenbeleg"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Receipt image or PDF"}},"required":["file"]}}}},"responses":{"200":{"description":"Generated expense report document","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptToDocumentResult"}}}},"400":{"description":"No file uploaded or unsupported file type","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptToDocumentResult"}}}},"500":{"description":"Processing failed","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptToDocumentResult"}}}}}}},"/api/receipts/extract":{"post":{"tags":["Receipts"],"summary":"Extract data from a receipt or ticket image","description":"Extracts structured data from receipt photos, tickets, and invoice images using Claude AI Vision.\n\n**Supported document types:** Cash receipts, restaurant bills, parking tickets, train/flight/bus tickets, taxi receipts, hotel invoices, fuel receipts, general invoices.\n\n**Supported file formats:** JPEG, PNG, WebP, GIF, TIFF, PDF\n\nReturns structured JSON with receipt type, amounts, VAT breakdown, line items, type-specific metadata, SKR03/SKR04 account suggestions, language/country detection, plausibility checks, and image quality hints.\n\nRequires `ANTHROPIC_API_KEY` environment variable. This endpoint uses AI processing and consumes additional API credits.\n","operationId":"extractReceipt","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Receipt image or PDF (JPEG, PNG, WebP, GIF, TIFF, PDF)"}},"required":["file"]}}}},"responses":{"200":{"description":"Extracted receipt data","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}}},"400":{"description":"No file uploaded or unsupported file type","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}}},"500":{"description":"Extraction failed","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}}}}}},"/api/receipts/extract-batch":{"post":{"tags":["Receipts"],"summary":"Extract data from multiple receipts (batch)","description":"Processes multiple receipt images in parallel and returns all extraction results.\nIdeal for expense reports where multiple receipts need to be processed at once.\n\nMaximum 20 files per batch. Each file is processed independently — a failure in one file does not affect others.\n\nEach file in the batch consumes AI credits independently.\n","operationId":"extractBatch","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"files":{"type":"array","description":"Receipt images or PDFs (max 20 files)","items":{"type":"string","format":"binary"}}},"required":["files"]}}}},"responses":{"200":{"description":"Batch extraction results","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BatchExtractionResult"}}}},"400":{"description":"No files uploaded or too many files","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BatchExtractionResult"}}}},"500":{"description":"Batch processing failed","content":{"*/*":{"schema":{"$ref":"#/components/schemas/BatchExtractionResult"}}}}}}},"/api/receipts/extract-async":{"post":{"tags":["Receipts"],"summary":"Extract receipt data asynchronously with webhook notification","description":"Submits a receipt for asynchronous AI extraction. Returns a job ID immediately.\n\nWhen extraction completes (or fails), a webhook POST is sent to the `callbackUrl` with the full extraction result as JSON payload.\n\n**Webhook payload includes:**\n- `event`: \"receipt.extraction.completed\" or \"receipt.extraction.failed\"\n- `jobId`, `status`, `filename`, `durationMs`\n- `result`: full ReceiptExtractionResult (on success)\n- `error`: error message (on failure)\n\n**Security:** If `callbackSecret` is provided, the webhook includes an `X-DocGen-Signature` header with HMAC-SHA256 of the payload for verification.\n\nJobs are kept in memory for 30 minutes and then auto-cleaned.\n","operationId":"extractAsync","parameters":[{"name":"callbackUrl","in":"query","description":"Webhook URL to notify on completion","required":false,"schema":{"type":"string"}},{"name":"callbackSecret","in":"query","description":"Shared secret for HMAC-SHA256 webhook signature","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Receipt image or PDF"}},"required":["file"]}}}},"responses":{"202":{"description":"Job accepted","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptJob"}}}},"400":{"description":"No file uploaded or unsupported type","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptJob"}}}},"500":{"description":"Submission failed","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptJob"}}}}}}},"/api/receipts/export/xlsx":{"post":{"tags":["Receipts"],"summary":"Export receipt data as Excel (XLSX)","description":"Accepts a list of extracted ReceiptData objects and returns an XLSX file with formatted columns, auto-filter, and summary row.\n\nSuitable for import into DATEV, Lexware, or other bookkeeping software.\n","operationId":"exportXlsx","requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptData"}}}},"required":true},"responses":{"200":{"description":"XLSX file","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"No data provided","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/receipts/export/csv":{"post":{"tags":["Receipts"],"summary":"Export receipt data as CSV","description":"Accepts a list of extracted ReceiptData objects and returns a CSV file suitable for import into DATEV, Lexware, or other bookkeeping software.\n\nColumns: Date, Time, Type, Issuer, Reference, Currency, Net, VAT, Gross, Payment Method, SKR03 Account, SKR04 Account, Expense Category.\n","operationId":"exportCsv","requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptData"}}}},"required":true},"responses":{"200":{"description":"CSV file","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"400":{"description":"No data provided","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/preview":{"post":{"tags":["Preview"],"summary":"Preview a single PDF page (file upload)","description":"Upload a PDF and get a single page rendered as PNG or JPEG image. Returns the image directly as binary (not JSON). For multi-page previews, use the /api/preview/pages endpoint.","operationId":"previewUpload","parameters":[{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"format","in":"query","description":"Image format: PNG or JPEG","required":false,"schema":{"type":"string","default":"PNG"},"example":"PNG"},{"name":"dpi","in":"query","description":"Rendering DPI (default: 96, max: 300)","required":false,"schema":{"type":"integer","format":"int32","default":96},"example":96},{"name":"maxWidth","in":"query","description":"Max width in pixels (0 = no scaling)","required":false,"schema":{"type":"integer","format":"int32","default":0},"example":800}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Page preview image","content":{"image/png":{}}},"400":{"description":"Invalid PDF or page number","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/preview/pages":{"post":{"tags":["Preview"],"summary":"Preview multiple PDF pages (file upload)","description":"Upload a PDF and get multiple pages as Base64-encoded images in a JSON response. Specify pages as: 'all', '1', '1-3', '1,3,5', or '1-3,7'. Maximum 50 pages per request.","operationId":"previewPagesUpload","parameters":[{"name":"pages","in":"query","description":"Page specification: 'all', '1', '1-3', '1,3,5'","required":false,"schema":{"type":"string","default":"all"},"example":"all"},{"name":"format","in":"query","description":"Image format: PNG or JPEG","required":false,"schema":{"type":"string","default":"PNG"}},{"name":"dpi","in":"query","description":"Rendering DPI (default: 72, max: 300)","required":false,"schema":{"type":"integer","format":"int32","default":72}},{"name":"maxWidth","in":"query","description":"Max width in pixels (0 = no scaling)","required":false,"schema":{"type":"integer","format":"int32","default":0}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Multi-page preview","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"400":{"description":"Invalid PDF or page specification","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/preview/pages/base64":{"post":{"tags":["Preview"],"summary":"Preview multiple PDF pages (Base64)","description":"Submit a Base64-encoded PDF and get multiple pages as JSON with Base64 images.","operationId":"previewPagesBase64","parameters":[{"name":"pages","in":"query","required":false,"schema":{"type":"string","default":"all"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"PNG"}},{"name":"dpi","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":72}},{"name":"maxWidth","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Multi-page preview","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"400":{"description":"Invalid PDF or page specification","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/preview/page-count":{"post":{"tags":["Preview"],"summary":"Get PDF page count","description":"Upload a PDF and get the total number of pages (without rendering).","operationId":"pageCount","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Page count","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/preview/base64":{"post":{"tags":["Preview"],"summary":"Preview a single PDF page (Base64)","description":"Submit a Base64-encoded PDF and get a single page rendered as binary image.","operationId":"previewBase64","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"PNG"}},{"name":"dpi","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":96}},{"name":"maxWidth","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Page preview image","content":{"image/png":{}}},"400":{"description":"Invalid PDF or page number","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/pdf-tools/split":{"post":{"tags":["PDF Tools"],"summary":"Split a PDF into parts","description":"Split a PDF into multiple PDFs by page ranges. Returns a JSON object with Base64-encoded PDFs for each part. Pages spec: 'all' (each page separate), '1-3,4-6' (ranges), '1,3,5' (individual).","operationId":"split","parameters":[{"name":"pages","in":"query","description":"Page ranges: 'all', '1-3', '1-3,4-6', '1,3,5'","required":false,"schema":{"type":"string","default":"all"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Split result with Base64 PDFs","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/pdf-tools/rotate":{"post":{"tags":["PDF Tools"],"summary":"Rotate PDF pages","description":"Rotate pages in a PDF by 90, 180, or 270 degrees. Specify pages or rotate all.","operationId":"rotatePages","parameters":[{"name":"degrees","in":"query","description":"Rotation in degrees: 90, 180, 270","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"pages","in":"query","description":"Pages to rotate: 'all', '1', '1-3', '1,3,5'","required":false,"schema":{"type":"string","default":"all"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Rotated PDF","content":{"application/pdf":{}}}}}},"/api/pdf-tools/pdfa":{"post":{"tags":["PDF Tools"],"summary":"Convert PDF to PDF/A-3b","description":"Convert a PDF to PDF/A-3b format for long-term archiving. Uses embedded sRGB ICC color profile and XMP metadata. Optionally set title and author metadata.","operationId":"convertToPdfA","parameters":[{"name":"title","in":"query","description":"Document title for XMP metadata","required":false,"schema":{"type":"string"}},{"name":"author","in":"query","description":"Author for XMP metadata","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"PDF/A-3b compliant PDF","content":{"application/pdf":{}}},"400":{"description":"Invalid PDF","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/pdf-tools/pdfa/base64":{"post":{"tags":["PDF Tools"],"summary":"Convert PDF to PDF/A-3b (Base64)","description":"Convert a Base64-encoded PDF to PDF/A-3b format.","operationId":"convertToPdfABase64","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"PDF/A-3b compliant PDF","content":{"application/pdf":{}}}}}},"/api/pdf-tools/metadata":{"post":{"tags":["PDF Tools"],"summary":"Read PDF metadata","description":"Upload a PDF and retrieve its metadata (title, author, subject, keywords, creation date, page count, PDF version, encryption status).","operationId":"getMetadata","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"PDF metadata","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/pdf-tools/metadata/set":{"post":{"tags":["PDF Tools"],"summary":"Set PDF metadata","description":"Upload a PDF and set metadata fields. Returns the updated PDF. Supported fields: title, author, subject, keywords, creator, producer.","operationId":"setMetadata","parameters":[{"name":"title","in":"query","description":"Document title","required":false,"schema":{"type":"string"}},{"name":"author","in":"query","description":"Document author","required":false,"schema":{"type":"string"}},{"name":"subject","in":"query","description":"Document subject","required":false,"schema":{"type":"string"}},{"name":"keywords","in":"query","description":"Document keywords (comma-separated)","required":false,"schema":{"type":"string"}},{"name":"creator","in":"query","description":"Creator application","required":false,"schema":{"type":"string"}},{"name":"producer","in":"query","description":"PDF producer","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Updated PDF","content":{"application/pdf":{}}}}}},"/api/pdf-tools/metadata/set/base64":{"post":{"tags":["PDF Tools"],"summary":"Set PDF metadata (Base64)","description":"Set metadata on a Base64-encoded PDF. Returns the updated PDF.","operationId":"setMetadataBase64","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Updated PDF","content":{"application/pdf":{}}}}}},"/api/pdf-tools/merge":{"post":{"tags":["PDF Tools"],"summary":"Merge multiple PDFs into one","description":"Upload multiple PDF files and merge them into a single PDF. Files are merged in the order they are provided.","operationId":"merge","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"files":{"type":"array","description":"PDF files to merge (in order)","items":{"type":"string","format":"binary"}}},"required":["files"]}}}},"responses":{"200":{"description":"Merged PDF","content":{"application/pdf":{}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/pdf-tools/merge/base64":{"post":{"tags":["PDF Tools"],"summary":"Merge multiple PDFs (Base64)","description":"Merge multiple Base64-encoded PDFs into one.","operationId":"mergeBase64","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"required":true},"responses":{"200":{"description":"Merged PDF","content":{"application/pdf":{}}}}}},"/api/pdf-tools/extract":{"post":{"tags":["PDF Tools"],"summary":"Extract pages from a PDF","description":"Extract specific pages from a PDF into a new PDF. Unlike split, this always returns a single PDF with the selected pages.","operationId":"extractPages","parameters":[{"name":"pages","in":"query","description":"Pages to extract: '1', '1-3', '1,3,5', '2-4,8'","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Extracted PDF","content":{"application/pdf":{}}}}}},"/api/pdf-forms/fill":{"post":{"tags":["PDF Forms"],"summary":"Fill PDF form fields","description":"Fill form fields in a PDF with the provided values. Optionally flatten the form (convert to static content) and/or protect with a password. Use the inspect endpoint first to discover available field names.","operationId":"fillForm","parameters":[{"name":"X-DocGen-Validate","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdfFormFillRequest"}}},"required":true},"responses":{"200":{"description":"Filled PDF document","content":{"application/pdf":{}}},"400":{"description":"Invalid request or PDF has no form fields"}}}},"/api/pdf-forms/fill/upload":{"post":{"tags":["PDF Forms"],"summary":"Fill PDF form (file upload)","description":"Upload a PDF form file and fill it with the provided field values. Alternative to the Base64-based endpoint for direct file upload.","operationId":"fillFormUpload","parameters":[{"name":"flatten","in":"query","required":false,"schema":{"type":"boolean","default":false}},{"name":"password","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"fields":{"type":"string"}},"required":["fields","file"]}}}},"responses":{"200":{"description":"Filled PDF document","content":{"application/pdf":{}}},"400":{"description":"Invalid request or PDF has no form fields"}}}},"/api/pdf-forms/fields":{"post":{"tags":["PDF Forms"],"summary":"Inspect PDF form fields","description":"Upload a PDF form to retrieve all form fields with their names, types, current values, and available options. Use this to discover field names before filling.","operationId":"inspectFields","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"List of form fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdfFormField"}}}},"400":{"description":"Invalid PDF or processing error"}}}},"/api/pdf-forms/fields/base64":{"post":{"tags":["PDF Forms"],"summary":"Inspect PDF form fields (Base64)","description":"Submit a Base64-encoded PDF to retrieve all form fields.","operationId":"inspectFieldsBase64","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdfFormFillRequest"}}},"required":true},"responses":{"200":{"description":"List of form fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdfFormField"}}}},"400":{"description":"Invalid PDF or processing error"}}}},"/api/fonts":{"get":{"tags":["Fonts"],"summary":"List available font families","description":"Returns all available font families with their variants (regular, bold, italic, bolditalic).","operationId":"listFonts","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"post":{"tags":["Fonts"],"summary":"Upload a font file","description":"Uploads a TrueType (.ttf) or OpenType (.otf) font. Font family and variant are derived from the filename convention: FamilyName-Variant.ttf (e.g. OpenSans-Bold.ttf). If no variant suffix, it's treated as 'regular'. Uploaded fonts become available for content areas and are installed for LibreOffice headers/footers.","operationId":"uploadFont","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Font file (.ttf or .otf)"}},"required":["file"]}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}}}}}},"/api/excel/upload/to-json":{"post":{"tags":["Excel"],"summary":"Upload Excel and extract as JSON","description":"Upload an Excel file and extract its content as structured JSON.","operationId":"uploadToJson","parameters":[{"name":"sheetIndex","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"hasHeader","in":"query","required":false,"schema":{"type":"boolean","default":true}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"JSON data","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid file","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/upload/to-csv":{"post":{"tags":["Excel"],"summary":"Upload Excel and extract as CSV","description":"Upload an Excel file and extract its content as CSV text.","operationId":"uploadToCsv","parameters":[{"name":"sheetIndex","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"delimiter","in":"query","required":false,"schema":{"type":"string","default":","}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"CSV content","content":{"text/csv":{}}},"400":{"description":"Invalid file","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/upload/inspect":{"post":{"tags":["Excel"],"summary":"Upload and inspect an Excel workbook","description":"Upload an Excel file and return metadata: sheet names, row/column counts, named ranges.","operationId":"uploadInspect","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Workbook metadata","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid file","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/to-json":{"post":{"tags":["Excel"],"summary":"Convert Excel to JSON","description":"Extract data from an Excel sheet and return structured JSON with headers and typed values.","operationId":"toJson","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExcelConvertRequest"}}},"required":true},"responses":{"200":{"description":"JSON data","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/to-csv":{"post":{"tags":["Excel"],"summary":"Convert Excel to CSV","description":"Extract data from an Excel sheet and return it as CSV text.","operationId":"toCsv","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExcelConvertRequest"}}},"required":true},"responses":{"200":{"description":"CSV content","content":{"text/csv":{}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/inspect":{"post":{"tags":["Excel"],"summary":"Inspect an Excel workbook","description":"Analyze an Excel file and return metadata: sheet names, row/column counts, named ranges.","operationId":"inspect","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"Workbook metadata","content":{"*/*":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/generate":{"post":{"tags":["Excel"],"summary":"Generate Excel workbook from JSON","description":"Create a fully styled Excel workbook (.xlsx) from a structured JSON definition. Supports multiple sheets, column definitions, formulas, styling, headers/footers, freeze panes, print areas, merged cells, and more.","operationId":"generate_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExcelRequest"}}},"required":true},"responses":{"200":{"description":"Generated XLSX file","content":{"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/from-csv":{"post":{"tags":["Excel"],"summary":"Convert CSV to Excel","description":"Convert CSV content into a styled Excel workbook with auto-sized columns, header formatting, auto-filter, and frozen header row.","operationId":"fromCsv","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExcelConvertRequest"}}},"required":true},"responses":{"200":{"description":"Generated XLSX file","content":{"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/excel/fill-template":{"post":{"tags":["Excel"],"summary":"Fill an Excel template with data","description":"Upload a Base64-encoded Excel template and fill named cells, ranges, and tables with provided values. Formulas are recalculated automatically.","operationId":"fillTemplate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExcelTemplateRequest"}}},"required":true},"responses":{"200":{"description":"Filled XLSX file","content":{"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/api/documents/invoice/validate":{"post":{"tags":["Documents"],"summary":"Validate a ZUGFeRD/XRechnung PDF","description":"Validates a PDF against ZUGFeRD/Factur-X/XRechnung standards. Returns whether the document is valid and a detailed validation report.","operationId":"validateInvoice","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PDF file to validate"}},"required":["file"]}}}},"responses":{"200":{"description":"Validation result","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"400":{"description":"No file uploaded","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"500":{"description":"Validation failed","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/documents/invoice/extract":{"post":{"tags":["Documents"],"summary":"Extract invoice from ZUGFeRD PDF","description":"Extracts structured invoice data (seller, buyer, items, totals, bank details) from a ZUGFeRD/Factur-X PDF and returns it as JSON. Also includes the raw embedded XML.","operationId":"extractInvoice","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"ZUGFeRD/Factur-X PDF file"}},"required":["file"]}}}},"responses":{"200":{"description":"Extracted invoice data","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"400":{"description":"No file uploaded","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}},"500":{"description":"Extraction failed","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/documents/generate":{"post":{"tags":["Documents"],"summary":"Generate a document","description":"Generates a document from HTML or Markdown content, optionally using a LibreOffice template. Supports field/bookmark replacement, images, QR codes, tables, Markdown with native styles, watermarks, page settings, password protection, and ZUGFeRD invoice embedding.","operationId":"generateDocument","parameters":[{"name":"X-DocGen-Validate","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentRequest"}}},"required":true},"responses":{"200":{"description":"Generated document","content":{"application/octet-stream":{}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"500":{"description":"Generation failed","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"503":{"description":"Service unavailable (interrupted)","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/documents/generate-async":{"post":{"tags":["Documents"],"summary":"Generate a document asynchronously","description":"Submits a document generation request for asynchronous processing. Returns a job ID that can be used to poll status and download the result.","operationId":"generateDocumentAsync","parameters":[{"name":"X-DocGen-Validate","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentRequest"}}},"required":true},"responses":{"202":{"description":"Job accepted","content":{"*/*":{"schema":{"$ref":"#/components/schemas/JobInfo"}}}},"500":{"description":"Failed to submit job","content":{"*/*":{"schema":{"$ref":"#/components/schemas/JobInfo"}}}}}}},"/api/documents/compose":{"post":{"tags":["Documents"],"summary":"Compose a multi-part document","description":"Combines multiple document parts (each with its own template, HTML, fields, images, etc.) into a single output document. Supports page breaks between parts, global page settings, watermarks, password protection, and ZUGFeRD invoice embedding.","operationId":"composeDocument","parameters":[{"name":"X-DocGen-Validate","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComposeRequest"}}},"required":true},"responses":{"200":{"description":"Composed document","content":{"application/octet-stream":{}}},"400":{"description":"Invalid request","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"500":{"description":"Composition failed","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"503":{"description":"Service unavailable (interrupted)","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/auth/validate":{"post":{"tags":["Auth"],"summary":"Validate an API key","description":"Validates an API key and returns the associated tenant details for portal integration.","operationId":"validate_2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateApiKeyRequest"}}}},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ValidateApiKeyResponse"}}}}}}},"/api/receipts/jobs":{"get":{"tags":["Receipts"],"summary":"List all async receipt jobs","operationId":"listJobs","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReceiptJob"}}}}}}}},"/api/receipts/jobs/{jobId}":{"get":{"tags":["Receipts"],"summary":"Get async receipt job status","operationId":"getJobStatus","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptJob"}}}},"404":{"description":"Job not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptJob"}}}}}}},"/api/receipts/jobs/{jobId}/result":{"get":{"tags":["Receipts"],"summary":"Get async receipt extraction result","operationId":"getJobResult","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Extraction result","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}}},"404":{"description":"Job not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}}},"409":{"description":"Job not yet completed","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}}}}}},"/api/documents/jobs":{"get":{"tags":["Documents"],"summary":"List all async jobs","description":"Returns a list of all async document generation jobs (active and recently completed).","operationId":"listJobs_1","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/JobInfo"}}}}}}}},"/api/documents/jobs/{jobId}":{"get":{"tags":["Documents"],"summary":"Get async job status","description":"Returns the current status of an asynchronous document generation job.","operationId":"getJobStatus_1","parameters":[{"name":"jobId","in":"path","description":"The job ID returned by generate-async","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status","content":{"*/*":{"schema":{"$ref":"#/components/schemas/JobInfo"}}}},"404":{"description":"Job not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/JobInfo"}}}}}}},"/api/documents/jobs/{jobId}/download":{"get":{"tags":["Documents"],"summary":"Download async job result","description":"Downloads the generated document for a completed async job.","operationId":"downloadJobResult","parameters":[{"name":"jobId","in":"path","description":"The job ID returned by generate-async","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Generated document","content":{"application/octet-stream":{}}},"404":{"description":"Job not found","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}},"409":{"description":"Job not yet completed","content":{"*/*":{"schema":{"type":"string","format":"byte"}}}}}}},"/api/documents/health":{"get":{"tags":["Documents"],"summary":"Health check","description":"Returns the service health status.","operationId":"health","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/api/admin/usage":{"get":{"tags":["Admin"],"summary":"Get usage summary for all tenants","description":"Returns aggregated usage statistics for all tenants.","operationId":"getAllUsage","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/admin/usage/{tenantId}":{"get":{"tags":["Admin"],"summary":"Get usage summary for a specific tenant","description":"Returns aggregated usage statistics for a specific tenant.","operationId":"getTenantUsage","parameters":[{"name":"tenantId","in":"path","description":"Tenant ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}}}}}},"/api/admin/usage/{tenantId}/records":{"get":{"tags":["Admin"],"summary":"Get recent usage records for a tenant","description":"Returns the most recent usage records for a tenant (default: last 100).","operationId":"getTenantRecords","parameters":[{"name":"tenantId","in":"path","description":"Tenant ID","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max records to return","required":false,"schema":{"type":"integer","format":"int32","default":100}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsageRecord"}}}}}}}},"/api/templates/{templateName}":{"delete":{"tags":["template-controller"],"operationId":"deleteTemplate","parameters":[{"name":"templateName","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/signatures/certificates/{filename}":{"delete":{"tags":["Digital Signatures"],"summary":"Delete a certificate","description":"Deletes a stored certificate by filename.","operationId":"deleteCertificate","parameters":[{"name":"filename","in":"path","description":"Certificate filename","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/fonts/{filename}":{"delete":{"tags":["Fonts"],"summary":"Delete a font file","description":"Deletes a font file by filename. The font will no longer be available for document generation.","operationId":"deleteFont","parameters":[{"name":"filename","in":"path","description":"Font filename (e.g. OpenSans-Bold.ttf)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}}},"components":{"schemas":{"BankAccount":{"type":"object","description":"Bank account details for payment","properties":{"iban":{"type":"string","description":"IBAN","example":"DE89370400440532013000"},"bic":{"type":"string","description":"BIC/SWIFT code","example":"COBADEFFXXX"},"accountHolder":{"type":"string","description":"Account holder name","example":"Muster GmbH"}},"required":["iban"]},"InvoiceData":{"type":"object","description":"ZUGFeRD/Factur-X invoice data to embed in a PDF","properties":{"profile":{"type":"string","default":"EN16931","description":"ZUGFeRD profile","enum":["MINIMUM","BASICWL","BASIC","EN16931","EXTENDED","XRECHNUNG"]},"number":{"type":"string","description":"Invoice number","example":"RE-2026-001"},"date":{"type":"string","description":"Invoice date (ISO format)","example":"2026-03-25"},"dueDate":{"type":"string","description":"Due date (ISO format)","example":"2026-04-25"},"currency":{"type":"string","default":"EUR","description":"Currency code (ISO 4217)","example":"EUR"},"seller":{"$ref":"#/components/schemas/Party","description":"Seller / supplier party"},"buyer":{"$ref":"#/components/schemas/Party","description":"Buyer / customer party"},"items":{"type":"array","description":"Invoice line items","items":{"$ref":"#/components/schemas/InvoiceItem"}},"paymentTerms":{"type":"string","description":"Payment terms description","example":"Net 30 days"},"bankAccount":{"$ref":"#/components/schemas/BankAccount","description":"Bank account for payment"},"referenceNumber":{"type":"string","description":"Reference number (e.g. Leitweg-ID for XRechnung)","example":"04011000-12345-67"},"buyerReference":{"type":"string","description":"Buyer reference (Leitweg-ID), required for XRechnung","example":"04011000-12345-67"},"invoiceTypeCode":{"type":"string","default":"380","description":"Invoice type code (UN/CEFACT 1001)","enum":["380","381","384","389"],"example":380},"sellerTaxNumber":{"type":"string","description":"Seller tax number (Steuernummer, alternative to VAT ID)","example":"27/123/12345"},"paymentMeansCode":{"type":"string","default":"58","description":"Payment means code (UN/CEFACT 4461)","example":58},"xrechnungFormat":{"type":"string","default":"CII","description":"XRechnung output format (CII or UBL)","enum":["CII","UBL"]}},"required":["buyer","date","items","number","seller"]},"InvoiceItem":{"type":"object","description":"Invoice line item","properties":{"description":{"type":"string","description":"Item description","example":"Software Development"},"quantity":{"type":"number","description":"Quantity","example":10},"unit":{"type":"string","default":"HUR","description":"Unit code (UN/ECE Rec 20)","enum":["HUR","C62","KGM","MTR","LTR","DAY"],"example":"HUR"},"unitPrice":{"type":"number","description":"Unit price (net)","example":150.0},"vatRate":{"type":"number","description":"VAT rate in percent","example":19.0}},"required":["description","quantity","unitPrice","vatRate"]},"Party":{"type":"object","description":"Trade party (seller or buyer)","properties":{"name":{"type":"string","description":"Company or person name","example":"Muster GmbH"},"street":{"type":"string","description":"Street address","example":"Musterstraße 1"},"zip":{"type":"string","description":"ZIP / postal code","example":12345},"city":{"type":"string","description":"City","example":"Berlin"},"country":{"type":"string","default":"DE","description":"Country code (ISO 3166-1 alpha-2)","example":"DE"},"vatId":{"type":"string","description":"VAT identification number","example":"DE123456789"},"email":{"type":"string","description":"Email address","example":"info@muster.de"},"phone":{"type":"string","description":"Phone number","example":"+49 30 1234567"}},"required":["city","name","street","zip"]},"ZugferdEmbedRequest":{"type":"object","description":"Request to embed a ZUGFeRD invoice into a Base64-encoded PDF","properties":{"pdfBase64":{"type":"string","description":"Base64-encoded PDF"},"invoice":{"$ref":"#/components/schemas/InvoiceData","description":"Invoice data to embed"}},"required":["invoice","pdfBase64"]},"ExtractionResult":{"type":"object","description":"Result of AI-based invoice data extraction from PDF or image","properties":{"invoiceData":{"$ref":"#/components/schemas/InvoiceData","description":"Extracted invoice data (null fields = not found in document)"},"missingFields":{"type":"array","description":"Fields that could not be extracted and need manual input","example":["buyerReference","seller.vatId"],"items":{"type":"string"}},"uncertainFields":{"type":"array","description":"Fields where the AI was unsure — should be verified","example":["items[0].vatRate"],"items":{"type":"string"}},"extractedText":{"type":"string","description":"Raw text extracted from the PDF (null for images)"},"inputType":{"type":"string","description":"Content type of the input file","example":"application/pdf"},"aiExtractionUsed":{"type":"boolean","description":"Whether AI extraction was used (false if API key not configured)"},"message":{"type":"string","description":"Informational message about the extraction process"}}},"SignatureDetail":{"type":"object","description":"Details of a single signature","properties":{"fieldName":{"type":"string","description":"Name of the signature field in the PDF","example":"Signature1"},"coversWholeDocument":{"type":"boolean","description":"Whether the signature covers the entire document (no unsigned changes)"},"signerName":{"type":"string","description":"Subject (CN) of the signing certificate","example":"Max Mustermann"},"issuer":{"type":"string","description":"Issuer of the signing certificate","example":"D-TRUST GmbH"},"serialNumber":{"type":"string","description":"Serial number of the certificate","example":1234567890},"signDate":{"type":"string","description":"Signing date as ISO string","example":"2026-03-28T10:30:00Z"},"validFrom":{"type":"string","description":"Certificate validity start","example":"2025-01-01T00:00:00Z"},"validTo":{"type":"string","description":"Certificate validity end","example":"2027-12-31T23:59:59Z"},"certificateValid":{"type":"boolean","description":"Whether the certificate is currently within its validity period"},"integrityValid":{"type":"boolean","description":"Whether the document integrity check passed (document not modified after signing)"},"reason":{"type":"string","description":"Reason for signing","example":"Rechnungsfreigabe"},"location":{"type":"string","description":"Location of signing","example":"Berlin"},"hasTimestamp":{"type":"boolean","description":"Whether a timestamp is embedded"},"error":{"type":"string","description":"Error message if verification failed"}}},"SignatureVerifyResult":{"type":"object","description":"Result of PDF signature verification","properties":{"signed":{"type":"boolean","description":"Whether the PDF contains any signatures"},"signatureCount":{"type":"integer","format":"int32","description":"Number of signatures found"},"allValid":{"type":"boolean","description":"Whether all signatures are valid (integrity check passed)"},"signatures":{"type":"array","description":"Details of each signature","items":{"$ref":"#/components/schemas/SignatureDetail"}}}},"SignatureRequest":{"type":"object","description":"Request to digitally sign a PDF with a PKCS#12 certificate","properties":{"pdfBase64":{"type":"string","description":"Base64-encoded PDF to sign","example":"JVBERi0xLjcK...","minLength":1},"certificateName":{"type":"string","description":"Name of a pre-uploaded certificate (stored on server)","example":"firma-zertifikat"},"certificateBase64":{"type":"string","description":"Base64-encoded PKCS#12 (.p12/.pfx) certificate (inline, alternative to certificateName)","example":"MIIKcQIBAzCC..."},"certificatePassword":{"type":"string","description":"Password for the PKCS#12 certificate","example":"geheim","minLength":1},"reason":{"type":"string","description":"Reason for signing","example":"Rechnungsfreigabe"},"location":{"type":"string","description":"Location of signing","example":"Berlin"},"contactInfo":{"type":"string","description":"Contact information of the signer","example":"buchhaltung@firma.de"},"signerName":{"type":"string","description":"Name of the signer (if not extracted from certificate)","example":"Max Mustermann"},"timestampUrl":{"type":"string","description":"URL of a Timestamp Authority (TSA) server for trusted timestamps. Examples: http://timestamp.digicert.com, http://tsa.swisssign.net","example":"http://timestamp.digicert.com"},"visibleSignature":{"$ref":"#/components/schemas/VisibleSignatureConfig","description":"Configuration for a visible signature on the PDF page (optional)"}},"required":["certificatePassword","pdfBase64"]},"VisibleSignatureConfig":{"type":"object","description":"Visible signature appearance on the PDF","properties":{"page":{"type":"integer","format":"int32","default":"1","description":"Page number (1-based) where the signature should appear","example":1},"x":{"type":"number","format":"float","description":"X position in mm from the left edge","example":20},"y":{"type":"number","format":"float","description":"Y position in mm from the bottom edge","example":20},"width":{"type":"number","format":"float","description":"Width of the signature rectangle in mm","example":60},"height":{"type":"number","format":"float","description":"Height of the signature rectangle in mm","example":20},"text":{"type":"string","description":"Text to display in the signature field. Supports placeholders: ${signer}, ${date}, ${reason}, ${location}","example":"Digital signiert von\\n${signer}\\n${date}"},"fontSize":{"type":"number","format":"float","default":"8","description":"Font size for the signature text in points","example":8},"imageBase64":{"type":"string","description":"Base64-encoded image (PNG/JPEG) to display in the signature field (e.g. a handwritten signature)"}}},"LineItem":{"type":"object","description":"Individual line item on a receipt","properties":{"description":{"type":"string","description":"Item description","example":"Cappuccino"},"quantity":{"type":"number","description":"Quantity","example":2},"unitPrice":{"type":"number","description":"Unit price","example":3.5},"totalPrice":{"type":"number","description":"Total price for this item","example":7.0},"vatRate":{"type":"number","description":"VAT rate in percent (if stated per item)","example":19}}},"ReceiptData":{"type":"object","description":"Structured data extracted from a receipt, ticket, or invoice image","properties":{"receiptType":{"type":"string","description":"Type of receipt/document","enum":["cash_receipt","restaurant_bill","parking_ticket","train_ticket","flight_ticket","bus_ticket","taxi_receipt","hotel_invoice","fuel_receipt","invoice","other"],"example":"restaurant_bill"},"issuer":{"type":"string","description":"Issuer / merchant name","example":"Deutsche Bahn AG"},"recipient":{"type":"string","description":"Recipient name (if present on the document)","example":"Max Mustermann"},"date":{"type":"string","description":"Document date (ISO format)","example":"2026-04-12"},"time":{"type":"string","description":"Document time (HH:mm or HH:mm:ss)","example":"14:35"},"totalAmount":{"type":"number","description":"Total amount (gross)","example":50.58},"netAmount":{"type":"number","description":"Net amount (before VAT, if stated)","example":42.5},"currency":{"type":"string","default":"EUR","description":"Currency code (ISO 4217)","example":"EUR"},"vat":{"type":"array","description":"VAT breakdown by rate","items":{"$ref":"#/components/schemas/VatBreakdown"}},"items":{"type":"array","description":"Individual line items (if present)","items":{"$ref":"#/components/schemas/LineItem"}},"paymentMethod":{"type":"string","description":"Payment method","enum":["cash","card","debit_card","credit_card","contactless","online","invoice","other"],"example":"card"},"referenceNumber":{"type":"string","description":"Reference number (receipt number, ticket number, booking reference, etc.)","example":"BNR-2026-04-12-001"},"tipAmount":{"type":"number","description":"Tip amount (e.g. restaurant)","example":5.0},"taxNumber":{"type":"string","description":"Tax number of the issuer (Steuernummer)","example":"27/123/12345"},"vatId":{"type":"string","description":"VAT ID of the issuer (USt-IdNr.)","example":"DE123456789"},"issuerAddress":{"type":"string","description":"Issuer address (if present)","example":"Musterstraße 1, 12345 Berlin"},"metadata":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional type-specific metadata (e.g. departure, arrival, seat, parking duration)","example":{"departure":"Berlin Hbf","arrival":"München Hbf","class":"2"}},"language":{"type":"string","description":"Detected document language (ISO 639-1)","example":"de"},"country":{"type":"string","description":"Detected country of origin (ISO 3166-1 alpha-2)","example":"DE"},"skr03Account":{"type":"string","description":"Suggested SKR03 account number for bookkeeping","example":4530},"skr03Description":{"type":"string","description":"SKR03 account description","example":"Laufende Kfz-Betriebskosten"},"skr04Account":{"type":"string","description":"Suggested SKR04 account number for bookkeeping","example":6530},"skr04Description":{"type":"string","description":"SKR04 account description","example":"Laufende Kfz-Betriebskosten"},"expenseCategory":{"type":"string","description":"General expense category","enum":["travel","transportation","meals_entertainment","office_supplies","fuel","accommodation","parking","communication","other"],"example":"travel"}}},"ReceiptExtractionResult":{"type":"object","description":"Result of AI-based receipt/document data extraction from an image or PDF","properties":{"receiptData":{"$ref":"#/components/schemas/ReceiptData","description":"Extracted receipt data (null fields = not found in document)"},"missingFields":{"type":"array","description":"Fields that could not be extracted and need manual input","example":["vatId","recipient"],"items":{"type":"string"}},"uncertainFields":{"type":"array","description":"Fields where the AI was unsure — should be verified","example":["vat[0].netAmount","totalAmount"],"items":{"type":"string"}},"warnings":{"type":"array","description":"Plausibility warnings (e.g. net + VAT does not match gross)","example":["VAT check: net 42.50 + VAT 8.08 = 50.58, but total is 50.60"],"items":{"type":"string"}},"inputType":{"type":"string","description":"Content type of the input file","example":"image/jpeg"},"aiExtractionUsed":{"type":"boolean","description":"Whether AI extraction was used (false if API key not configured)"},"confidence":{"type":"number","format":"double","description":"Confidence score (0.0–1.0) indicating overall extraction quality","example":0.92},"message":{"type":"string","description":"Informational message about the extraction process"},"qualityHints":{"type":"array","description":"Quality hints for the input image (e.g. 'Image too dark', 'Receipt partially cut off')","example":["Image slightly blurry — consider re-photographing for better accuracy"],"items":{"type":"string"}}}},"ReceiptToDocumentResult":{"type":"object","properties":{"extraction":{"$ref":"#/components/schemas/ReceiptExtractionResult"},"generatedHtml":{"type":"string"},"suggestedFilename":{"type":"string"}}},"VatBreakdown":{"type":"object","description":"VAT breakdown for a specific rate","properties":{"rate":{"type":"number","description":"VAT rate in percent","example":19},"netAmount":{"type":"number","description":"Net amount at this rate","example":42.5},"vatAmount":{"type":"number","description":"VAT amount at this rate","example":8.08},"grossAmount":{"type":"number","description":"Gross amount at this rate","example":50.58}}},"BatchExtractionResult":{"type":"object","properties":{"totalFiles":{"type":"integer","format":"int32"},"successCount":{"type":"integer","format":"int32"},"failureCount":{"type":"integer","format":"int32"},"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchItemResult"}}}},"BatchItemResult":{"type":"object","properties":{"index":{"type":"integer","format":"int32"},"filename":{"type":"string"},"success":{"type":"boolean"},"error":{"type":"string"},"result":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}},"ReceiptJob":{"type":"object","properties":{"jobId":{"type":"string"},"status":{"type":"string"},"filename":{"type":"string"},"contentType":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"error":{"type":"string"},"result":{"$ref":"#/components/schemas/ReceiptExtractionResult"}}},"PreviewPage":{"type":"object","description":"Preview image of a single PDF page","properties":{"page":{"type":"integer","format":"int32","description":"Page number (1-based)","example":1},"imageBase64":{"type":"string","description":"Base64-encoded image data"},"width":{"type":"integer","format":"int32","description":"Image width in pixels","example":794},"height":{"type":"integer","format":"int32","description":"Image height in pixels","example":1123}}},"PreviewResponse":{"type":"object","description":"Multi-page PDF preview result","properties":{"pageCount":{"type":"integer","format":"int32","description":"Total number of pages in the PDF","example":3},"format":{"type":"string","description":"Image format used","example":"PNG"},"dpi":{"type":"integer","format":"int32","description":"DPI used for rendering","example":96},"pages":{"type":"array","description":"Preview images for each requested page","items":{"$ref":"#/components/schemas/PreviewPage"}}}},"PdfFormFillRequest":{"type":"object","description":"Base64-encoded PDF","properties":{"pdfBase64":{"type":"string","description":"Base64-encoded PDF form file","example":"JVBERi0xLjcK...","minLength":1},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Field values to fill (key = field name, value = field value). For text fields: the text string. For checkboxes: 'Yes'/'On'/'true' to check, 'Off'/'false' to uncheck. For radio buttons: the value of the option to select. For dropdowns/listboxes: the value to select.","example":{"vorname":"Max","nachname":"Mustermann","agb_akzeptiert":"Yes"}},"flatten":{"type":"boolean","default":"false","description":"Flatten the form after filling. When true, form fields are converted to static text and the PDF is no longer editable. Recommended for final documents."},"password":{"type":"string","description":"Password to protect the filled PDF (optional)","example":"geheim123"}},"required":["fields","pdfBase64"]},"PdfFormField":{"type":"object","description":"Description of a single PDF form field","properties":{"name":{"type":"string","description":"Fully qualified field name","example":"vorname"},"type":{"type":"string","description":"Field type: TEXT, CHECKBOX, RADIO, DROPDOWN, LISTBOX, SIGNATURE, BUTTON, UNKNOWN","example":"TEXT"},"value":{"type":"string","description":"Current field value (empty if not filled)"},"required":{"type":"boolean","description":"Whether the field is required","example":true},"readOnly":{"type":"boolean","description":"Whether the field is read-only","example":false},"maxLength":{"type":"integer","format":"int32","description":"Maximum length for text fields (0 = unlimited)","example":50},"options":{"type":"array","description":"Available options for DROPDOWN, LISTBOX, RADIO, CHECKBOX fields","example":["Yes","Off"],"items":{"type":"string"}},"alternativeName":{"type":"string","description":"Alternative field name (tooltip/display name)","example":"Vorname des Antragstellers"}}},"ExcelConvertRequest":{"type":"object","description":"Request to convert data between Excel and other formats (CSV, JSON)","properties":{"excelBase64":{"type":"string","description":"Base64-encoded Excel file (for XLSX → CSV/JSON conversion)"},"csvContent":{"type":"string","description":"CSV content (for CSV → XLSX conversion)"},"delimiter":{"type":"string","default":",","description":"CSV delimiter character","example":","},"quoteChar":{"type":"string","default":"\"","description":"CSV text qualifier / quote character","example":"\""},"hasHeader":{"type":"boolean","default":"true","description":"Whether the CSV has a header row"},"sheetName":{"type":"string","description":"Sheet name for CSV → XLSX conversion","example":"Data"},"sheetIndex":{"type":"integer","format":"int32","default":"0","description":"Sheet index to read (0-based, for multi-sheet XLSX)","example":0}}},"ExcelCell":{"type":"object","description":"An individual cell in an Excel sheet with explicit positioning and optional styling","properties":{"ref":{"type":"string","description":"Cell reference in A1 notation (e.g. 'B3'). Required when used in sheet-level 'cells' array, optional inside a row.","example":"B3"},"column":{"type":"integer","format":"int32","description":"Column index (0-based, alternative to ref — used inside rows)","example":1},"value":{"type":"object","description":"Cell value. Auto-detected type: number, boolean, date (yyyy-MM-dd), or string.","example":12500.5},"type":{"type":"string","description":"Explicit cell type override","enum":["STRING","NUMERIC","BOOLEAN","DATE","FORMULA","BLANK"]},"formula":{"type":"string","description":"Excel formula (without leading '=')","example":"SUM(B2:B10)"},"format":{"type":"string","description":"Number/date format for this cell","example":"#,##0.00"},"style":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Cell style override"},"comment":{"type":"string","description":"Comment/note to attach to this cell","example":"Includes tax"},"hyperlink":{"type":"string","description":"Hyperlink URL","example":"https://dokmatiq.com"}}},"ExcelCellStyle":{"type":"object","description":"Cell styling definition for Excel cells","properties":{"fontName":{"type":"string","description":"Font name","example":"Arial"},"fontSize":{"type":"integer","format":"int32","description":"Font size in points","example":11},"bold":{"type":"boolean","default":"false","description":"Bold text"},"italic":{"type":"boolean","default":"false","description":"Italic text"},"underline":{"type":"boolean","default":"false","description":"Underline text"},"strikethrough":{"type":"boolean","default":"false","description":"Strikethrough text"},"fontColor":{"type":"string","description":"Font color (hex)","example":"#000000"},"backgroundColor":{"type":"string","description":"Background fill color (hex)","example":"#4472C4"},"fillPattern":{"type":"string","description":"Fill pattern","enum":["SOLID_FOREGROUND","FINE_DOTS","ALT_BARS","SPARSE_DOTS","THICK_HORZ_BANDS","THICK_VERT_BANDS","THICK_BACKWARD_DIAG","THICK_FORWARD_DIAG","BIG_SPOTS","BRICKS","THIN_HORZ_BANDS","THIN_VERT_BANDS","THIN_BACKWARD_DIAG","THIN_FORWARD_DIAG","SQUARES","DIAMONDS"],"example":"SOLID_FOREGROUND"},"horizontalAlignment":{"type":"string","description":"Horizontal alignment","enum":["LEFT","CENTER","RIGHT","JUSTIFY","FILL"]},"verticalAlignment":{"type":"string","description":"Vertical alignment","enum":["TOP","CENTER","BOTTOM","JUSTIFY"]},"wrapText":{"type":"boolean","default":"false","description":"Enable text wrapping"},"rotation":{"type":"integer","format":"int32","description":"Text rotation in degrees (0-180)","example":0},"indent":{"type":"integer","format":"int32","description":"Indent level (number of spaces)","example":0},"borderStyle":{"type":"string","description":"Border style for all four sides","enum":["NONE","THIN","MEDIUM","THICK","DOUBLE","DOTTED","DASHED"]},"borderColor":{"type":"string","description":"Border color (hex, applied to all sides)","example":"#000000"},"numberFormat":{"type":"string","description":"Number format string","example":"#,##0.00"}}},"ExcelColumnDef":{"type":"object","description":"Column definition for an Excel sheet","properties":{"index":{"type":"integer","format":"int32","description":"Column index (0-based). If omitted, columns are created in list order.","example":0},"header":{"type":"string","description":"Column header text","example":"Produkt"},"width":{"type":"integer","format":"int32","description":"Column width in characters","example":25},"format":{"type":"string","description":"Excel number format for data cells in this column","example":"#,##0.00 €"},"align":{"type":"string","description":"Horizontal alignment for data cells","enum":["LEFT","CENTER","RIGHT"],"example":"LEFT"},"headerStyle":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Custom style override for this column's header cell"},"dataStyle":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Custom style override for this column's data cells"}}},"ExcelFormula":{"type":"object","description":"A formula to place at a specific cell position","properties":{"cell":{"type":"string","description":"Cell reference in A1 notation","example":"B11"},"formula":{"type":"string","description":"Excel formula (without leading '=')","example":"SUM(B2:B10)"},"label":{"type":"string","description":"Optional label to place in the cell to the left","example":"Total"},"format":{"type":"string","description":"Number format for the formula result","example":"#,##0.00 €"},"style":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Style for the formula cell"}},"required":["cell","formula"]},"ExcelFreezePane":{"type":"object","description":"Freeze pane configuration — rows and columns that remain visible while scrolling","properties":{"row":{"type":"integer","format":"int32","description":"Number of rows to freeze (from top). 1 = freeze header row.","example":1},"col":{"type":"integer","format":"int32","description":"Number of columns to freeze (from left). 0 = no column freeze.","example":0}},"required":["row"]},"ExcelHeaderFooter":{"type":"object","description":"Print header and footer for an Excel sheet. Supports Apache POI format codes: &L=left, &C=center, &R=right, &P=page number, &N=total pages, &D=date, &T=time, &F=filename","properties":{"header":{"type":"string","description":"Header text with formatting codes","example":"&LACME GmbH&RPage &P of &N"},"footer":{"type":"string","description":"Footer text with formatting codes","example":"&LConfidential&R&D"},"headerLeft":{"type":"string","description":"Left section of the header"},"headerCenter":{"type":"string","description":"Center section of the header"},"headerRight":{"type":"string","description":"Right section of the header"},"footerLeft":{"type":"string","description":"Left section of the footer"},"footerCenter":{"type":"string","description":"Center section of the footer"},"footerRight":{"type":"string","description":"Right section of the footer"}}},"ExcelNamedRange":{"type":"object","description":"Named range definition for structured references in formulas","properties":{"name":{"type":"string","description":"Name of the range","example":"SalesData"},"range":{"type":"string","description":"Range reference in A1 notation","example":"A1:D20"}},"required":["name","range"]},"ExcelRequest":{"type":"object","description":"Request to generate an Excel workbook from structured JSON data","properties":{"sheets":{"type":"array","description":"List of sheets to create in the workbook","items":{"$ref":"#/components/schemas/SheetDefinition"},"minItems":1},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Document properties (author, title, subject, etc.)"},"password":{"type":"string","description":"Password to protect the workbook","example":"secret123"}}},"ExcelRow":{"type":"object","description":"A data row in an Excel sheet","properties":{"index":{"type":"integer","format":"int32","description":"Row index (0-based, excluding header). If omitted, rows are appended in list order."},"values":{"type":"array","description":"Cell values in column order. Strings are auto-detected: numbers become numeric cells, dates (yyyy-MM-dd) become date cells, booleans become boolean cells, everything else is text.","example":["Widget","12500.50","2026-04-12"],"items":{"type":"object"}},"cells":{"type":"array","description":"Explicit cell definitions (alternative to 'values' for full control)","items":{"$ref":"#/components/schemas/ExcelCell"}},"height":{"type":"number","format":"float","description":"Row height in points","example":20},"style":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Style override for all cells in this row"}}},"SheetDefinition":{"type":"object","description":"Definition of a single sheet within an Excel workbook","properties":{"name":{"type":"string","description":"Sheet tab name","example":"Umsatz Q1"},"columns":{"type":"array","description":"Column definitions with headers, widths, formats, and alignment","items":{"$ref":"#/components/schemas/ExcelColumnDef"}},"rows":{"type":"array","description":"Data rows — each row contains a list of cells","items":{"$ref":"#/components/schemas/ExcelRow"}},"cells":{"type":"array","description":"Named cells with explicit positioning (e.g. for formulas, labels, or sparse data)","items":{"$ref":"#/components/schemas/ExcelCell"}},"namedRanges":{"type":"array","description":"Named ranges for structured references","items":{"$ref":"#/components/schemas/ExcelNamedRange"}},"formulas":{"type":"array","description":"Formulas to place at specific cell positions","items":{"$ref":"#/components/schemas/ExcelFormula"}},"mergedRegions":{"type":"array","description":"Merge cell ranges","items":{"type":"string"}},"headerFooter":{"$ref":"#/components/schemas/ExcelHeaderFooter","description":"Sheet-level header and footer configuration (for print)"},"printArea":{"type":"string","description":"Print area in A1 notation","example":"A1:F20"},"freezePane":{"$ref":"#/components/schemas/ExcelFreezePane","description":"Freeze pane configuration (fixed header row/column)"},"headerStyle":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Default style for the header row"},"dataStyle":{"$ref":"#/components/schemas/ExcelCellStyle","description":"Default style for data cells"},"defaultColumnWidth":{"type":"integer","format":"int32","description":"Default column width in characters","example":12},"defaultRowHeight":{"type":"number","format":"float","description":"Default row height in points","example":15},"autoSizeColumns":{"type":"boolean","default":"false","description":"Auto-size columns to fit content"},"autoFilter":{"type":"boolean","default":"false","description":"Enable auto-filter on the header row"},"pageOrientation":{"type":"string","description":"Page orientation for printing","enum":["PORTRAIT","LANDSCAPE"],"example":"LANDSCAPE"},"fitToPage":{"type":"boolean","default":"false","description":"Fit sheet to one page width when printing"},"protectionPassword":{"type":"string","description":"Protection password for this sheet (prevents editing)","example":"readonly"}}},"ExcelTemplateRequest":{"type":"object","description":"Request to fill an Excel template with data. Named cells and ranges in the template are populated with provided values.","properties":{"templateBase64":{"type":"string","description":"Base64-encoded Excel template file"},"values":{"type":"object","additionalProperties":{"type":"object"},"description":"Cell values to set (key = cell reference like 'Sheet1!A1' or named range, value = content)"},"tables":{"type":"object","additionalProperties":{"type":"array","items":{"type":"array","items":{"type":"object"}}},"description":"Table data to insert at named ranges (key = range name, value = row data)"},"recalculate":{"type":"boolean","default":"true","description":"Recalculate all formulas after filling"},"password":{"type":"string","description":"Password to protect the filled workbook"}},"required":["templateBase64"]},"BarcodeData":{"type":"object","description":"Barcode to generate at a bookmark position","properties":{"content":{"type":"string","description":"Content to encode in the barcode","example":4006381333931},"format":{"type":"string","default":"CODE128","description":"Barcode format: CODE128, CODE39, EAN13, EAN8, UPC_A, ITF, CODABAR","example":"EAN13"},"width":{"type":"integer","format":"int32","default":"50","description":"Barcode width in mm","example":60},"height":{"type":"integer","format":"int32","default":"20","description":"Barcode height in mm","example":25},"showText":{"type":"boolean","default":"true","description":"Show human-readable text below the barcode"}},"required":["content"]},"ColumnDef":{"type":"object","description":"Column definition for a table","properties":{"header":{"type":"string","description":"Column header text","example":"Description"},"width":{"type":"integer","format":"int32","description":"Column width in mm","example":60},"align":{"type":"string","description":"Text alignment","enum":["left","center","right"],"example":"left"},"format":{"type":"string","description":"Cell format","enum":["text","number","currency"],"example":"text"},"headerStyle":{"type":"string","description":"Paragraph style name for header cells (from template)"},"cellStyle":{"type":"string","description":"Paragraph style name for data cells (from template)"}}},"ContentArea":{"type":"object","description":"A positioned content area on the page, placed at absolute coordinates from the page edge. Like a text stamp at exact positions — ideal for address fields, date lines, reference numbers, etc. Coordinates are in millimeters from the top-left corner of the page.","properties":{"content":{"type":"string","description":"Text content with optional inline markup. Supports line breaks via \\n, **bold**, *italic*, and ***bold+italic***.","example":"**Firma Beispiel GmbH**\nFrau Anna Müller\nMusterstraße 42\n*12345 Berlin*"},"x":{"type":"number","format":"float","description":"Horizontal position in mm from the left page edge","example":25},"y":{"type":"number","format":"float","description":"Vertical position in mm from the top page edge","example":50},"width":{"type":"number","format":"float","description":"Maximum width in mm. Text wraps at this boundary.","example":80},"height":{"type":"number","format":"float","description":"Maximum height in mm. Content exceeding this is clipped. If omitted, no vertical clipping is applied.","example":35},"fontName":{"type":"string","default":"Helvetica","description":"Font name. Built-in: Helvetica, Times-Roman, Courier. Custom fonts can be referenced by family name (uploaded via /api/fonts) or provided inline via the customFonts field.","example":"OpenSans"},"customFonts":{"type":"object","additionalProperties":{"type":"string"},"description":"Inline custom fonts as Base64-encoded TTF/OTF data. Keys: 'regular', 'bold', 'italic', 'boldItalic'. At minimum 'regular' should be provided; missing variants fall back to regular. If omitted, the fontName is looked up from uploaded fonts or built-in fonts.","example":{"regular":"AAEAAAARAQ...","bold":"AAEAAAARAQ..."}},"fontSize":{"type":"number","format":"float","default":"11","description":"Font size in points","example":10},"lineHeight":{"type":"number","format":"float","default":"1.35","description":"Line height as multiplier of font size","example":1.4},"color":{"type":"string","default":"#000000","description":"Text color as hex (RGB)","example":"#333333"},"bold":{"type":"boolean","default":"false","description":"Bold text"},"alignment":{"type":"string","default":"LEFT","description":"Text alignment within the content area","enum":["LEFT","CENTER","RIGHT"],"example":"LEFT"},"pages":{"type":"string","default":"1","description":"Which pages this content area appears on. Single number = that page only (e.g. '1', '3'). Number with '+' = from that page onwards (e.g. '2+'). Range = specific range (e.g. '2-4'). 'all' = every page. Default: first page only.","example":2},"barcode":{"$ref":"#/components/schemas/BarcodeData","description":"Barcode to render in this content area (instead of text). When set, the content field is ignored and a barcode image is rendered at the given coordinates."},"imageBase64":{"type":"string","description":"Base64-encoded image (PNG, JPG, etc.) to render at the given coordinates. When set, the content field is ignored and the image is placed at x/y with the given width/height.","example":"iVBORw0KGgoAAAANS..."}},"required":["width","x","y"]},"DocumentRequest":{"type":"object","description":"Request to generate a single document","properties":{"htmlContent":{"type":"string","description":"HTML content to render","example":"<h1>Hello</h1><p>World</p>"},"outputFormat":{"type":"string","default":"PDF","description":"Output format","enum":["PDF","DOCX","ODT"]},"templateName":{"type":"string","description":"Name of a LibreOffice template file (without path, pre-uploaded)","example":"invoice-template.odt"},"templateBase64":{"type":"string","description":"Base64-encoded template file (alternative to templateName). Allows fully stateless operation without pre-uploading templates.","example":"UEsDBBQAAAAIAA..."},"templateFilename":{"type":"string","description":"Original filename of the inline template (used to detect format: .odt, .ott, .docx)","example":"rechnung.odt"},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Field placeholders to replace in the template (key = placeholder name, value = replacement text)"},"bookmarks":{"type":"object","additionalProperties":{"type":"string"},"description":"Bookmark positions for HTML content injection (key = bookmark name, value = HTML)"},"pageSettings":{"$ref":"#/components/schemas/PageSettings","description":"Page layout settings (orientation, paper size, margins, headers/footers)"},"watermark":{"$ref":"#/components/schemas/WatermarkConfig","description":"Watermark to overlay on all pages. Can be a simple string or an object with text, fontSize, opacity, color.","example":"DRAFT"},"password":{"type":"string","description":"Password to protect the output document","example":"secret123"},"images":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ImageData"},"description":"Images to embed at bookmark positions (key = bookmark name)"},"qrCodes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/QrCodeData"},"description":"QR codes to generate at bookmark positions (key = bookmark name)"},"barcodes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/BarcodeData"},"description":"Barcodes to generate at bookmark positions (key = bookmark name). Supports CODE128, CODE39, EAN13, EAN8, UPC_A, ITF, CODABAR formats."},"tables":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/TableData"},"description":"Tables to generate at bookmark positions (key = bookmark name)"},"markdownContent":{"type":"string","description":"Markdown content to render (alternative to htmlContent). Converted to native LibreOffice elements with proper styles.","example":"# Invoice\n\nDear **Mr. Smith**,\n\n- Item 1\n- Item 2\n\n| Product | Price |\n|---------|-------|\n| Widget  | 9.99  |"},"markdownBookmarks":{"type":"object","additionalProperties":{"type":"string"},"description":"Markdown content at bookmark positions (key = bookmark name, value = Markdown text)"},"markdownStyles":{"$ref":"#/components/schemas/MarkdownStyles","description":"Custom style mapping for Markdown elements. Maps Markdown elements (heading1, paragraph, listBullet, etc.) to LibreOffice style names from the template."},"contentAreas":{"type":"array","description":"Positioned content areas placed at absolute coordinates from the page edge. Ideal for address fields, date lines, reference numbers on letterheads. Only for PDF output.","items":{"$ref":"#/components/schemas/ContentArea"}},"stationery":{"$ref":"#/components/schemas/StationeryConfig","description":"Stationery (letterhead) PDF overlay. The provided PDF is placed as a background layer under the generated content, like printing on pre-printed company paper. Only for PDF output."},"invoice":{"$ref":"#/components/schemas/InvoiceData","description":"ZUGFeRD/Factur-X invoice data to embed in the PDF (only for PDF output)"},"callbackUrl":{"type":"string","description":"Webhook callback URL for async jobs. When set, DocGen sends a POST request to this URL when the job completes or fails. The payload contains jobId, status, downloadUrl, file size, duration, and error details.","example":"https://example.com/api/webhook/docgen"},"callbackSecret":{"type":"string","description":"Optional secret for HMAC-SHA256 webhook signature. When set, each webhook request includes an X-DocGen-Signature header for payload verification.","example":"my-webhook-secret-123"}},"required":["outputFormat"]},"HeaderFooterConfig":{"type":"object","description":"Header or footer configuration for a page style. Supports placeholders: {{PAGE}} (current page), {{PAGES}} (total pages), {{DATE}} (current date), {{TIME}} (current time), {{DATETIME}} (date and time), {{FILENAME}} (document filename).","properties":{"left":{"type":"string","description":"Left-aligned text","example":"Company Name"},"center":{"type":"string","description":"Center-aligned text","example":"Document Title"},"right":{"type":"string","description":"Right-aligned text","example":"{{PAGE}} / {{PAGES}}"},"height":{"type":"integer","format":"int32","description":"Height of the header/footer area in mm. If omitted, LibreOffice uses its default auto-height.","example":15},"spacing":{"type":"integer","format":"int32","default":"3","description":"Spacing between the header/footer and the body text in mm","example":5},"fontName":{"type":"string","default":"Helvetica","description":"Font name","example":"Helvetica"},"fontSize":{"type":"number","format":"float","default":"10","description":"Font size in points","example":9},"color":{"type":"string","default":"#000000","description":"Text color as hex (RGB)","example":"#666666"}}},"ImageData":{"type":"object","description":"Image to embed at a bookmark position","properties":{"base64":{"type":"string","description":"Base64-encoded image data (PNG, JPG, etc.)"},"width":{"type":"integer","format":"int32","description":"Image width in mm","example":50},"height":{"type":"integer","format":"int32","description":"Image height in mm","example":30}},"required":["base64"]},"MarkdownStyles":{"type":"object","description":"Custom style mapping for Markdown elements. Each field maps a Markdown element to a LibreOffice paragraph or character style name defined in the template. If omitted, sensible defaults are used (e.g. 'Heading 1' for h1).","properties":{"heading1":{"type":"string","description":"Paragraph style for # headings","example":"Heading 1"},"heading2":{"type":"string","description":"Paragraph style for ## headings","example":"Heading 2"},"heading3":{"type":"string","description":"Paragraph style for ### headings","example":"Heading 3"},"heading4":{"type":"string","description":"Paragraph style for #### headings","example":"Heading 4"},"heading5":{"type":"string","description":"Paragraph style for ##### headings","example":"Heading 5"},"heading6":{"type":"string","description":"Paragraph style for ###### headings","example":"Heading 6"},"paragraph":{"type":"string","description":"Paragraph style for normal text paragraphs","example":"Text Body"},"listBullet":{"type":"string","description":"Paragraph style for unordered list items","example":"List Bullet"},"listNumber":{"type":"string","description":"Paragraph style for ordered list items","example":"List Number"},"listBullet2":{"type":"string","description":"Paragraph style for nested unordered list items","example":"List Bullet 2"},"listNumber2":{"type":"string","description":"Paragraph style for nested ordered list items","example":"List Number 2"},"codeBlock":{"type":"string","description":"Paragraph style for code blocks","example":"Preformatted Text"},"blockQuote":{"type":"string","description":"Paragraph style for block quotes","example":"Quotations"},"codeSpan":{"type":"string","description":"Character style for inline code spans","example":"Source Text"},"codeFontName":{"type":"string","description":"Font name for inline code (used if no codeSpan style)","example":"Liberation Mono"}}},"PageSettings":{"type":"object","description":"Page layout settings for the generated document","properties":{"headerLeft":{"type":"string","description":"Left-aligned header text (supports {{PAGE}} and {{PAGES}} placeholders)","example":"Company Name"},"headerCenter":{"type":"string","description":"Center-aligned header text","example":"Document Title"},"headerRight":{"type":"string","description":"Right-aligned header text","example":"{{PAGE}}/{{PAGES}}"},"footerLeft":{"type":"string","description":"Left-aligned footer text"},"footerCenter":{"type":"string","description":"Center-aligned footer text","example":"Page {{PAGE}} of {{PAGES}}"},"footerRight":{"type":"string","description":"Right-aligned footer text"},"header":{"$ref":"#/components/schemas/HeaderFooterConfig","description":"Advanced header configuration with height, font, and page-specific control. Overrides headerLeft/headerCenter/headerRight when set."},"footer":{"$ref":"#/components/schemas/HeaderFooterConfig","description":"Advanced footer configuration with height, font, and page-specific control. Overrides footerLeft/footerCenter/footerRight when set."},"headerFirstPage":{"$ref":"#/components/schemas/HeaderFooterConfig","description":"Header for the first page only. When set, 'header' applies to pages 2+. Set to an empty object {} to suppress the header on the first page."},"footerFirstPage":{"$ref":"#/components/schemas/HeaderFooterConfig","description":"Footer for the first page only. When set, 'footer' applies to pages 2+. Set to an empty object {} to suppress the footer on the first page."},"headerEvenPages":{"$ref":"#/components/schemas/HeaderFooterConfig","description":"Header for even pages (left-hand pages). When set, 'header' applies to odd pages only."},"footerEvenPages":{"$ref":"#/components/schemas/HeaderFooterConfig","description":"Footer for even pages (left-hand pages). When set, 'footer' applies to odd pages only."},"headerFooterFontName":{"type":"string","description":"Default font name for all headers and footers. Individual header/footer configs can override this.","example":"Helvetica"},"headerFooterFontSize":{"type":"number","format":"float","description":"Default font size (pt) for all headers and footers. Individual header/footer configs can override this.","example":9},"headerFooterColor":{"type":"string","description":"Default text color for all headers and footers (hex RGB). Individual header/footer configs can override this.","example":"#666666"},"orientation":{"type":"string","description":"Page orientation","enum":["PORTRAIT","LANDSCAPE"]},"paperSize":{"type":"string","description":"Paper size","enum":["A4","A3","A5","LETTER","LEGAL"]},"marginTop":{"type":"integer","format":"int32","description":"Top margin in mm","example":20},"marginBottom":{"type":"integer","format":"int32","description":"Bottom margin in mm","example":20},"marginLeft":{"type":"integer","format":"int32","description":"Left margin in mm","example":25},"marginRight":{"type":"integer","format":"int32","description":"Right margin in mm","example":25},"pageNumberOffset":{"type":"integer","format":"int32","description":"Page number offset. The first page will be numbered as this value. For example, set to 3 to start counting at page 3 (useful for documents that are part of a larger document set).","example":1}}},"QrCodeData":{"type":"object","description":"QR code to generate at a bookmark position","properties":{"content":{"type":"string","description":"Content to encode in the QR code (text, URL, or EPC/GiroCode string)","example":"BCD\\n002\\n1\\nSCT\\nBFSWDE33BER\\nMax Mustermann\\nDE89370400440532013000\\nEUR123.45\\n\\n\\nRechnung 2024-001"},"size":{"type":"integer","format":"int32","default":"40","description":"QR code size in mm","example":40}},"required":["content"]},"StationeryConfig":{"type":"object","description":"Stationery (letterhead) PDF overlay configuration. The provided PDF is placed as a background layer under the generated content, like printing on pre-printed company stationery. Only applies to PDF output.","properties":{"pdf":{"type":"string","description":"Base64-encoded stationery PDF used for all pages. If firstPagePdf is also provided, this is used for pages 2+.","example":"JVBERi0xLjQK...","minLength":1},"firstPagePdf":{"type":"string","description":"Base64-encoded stationery PDF used only for the first page. When set, the main 'pdf' field is used for all following pages. Useful when the first page has a full letterhead and following pages have a simpler header.","example":"JVBERi0xLjQK..."}},"required":["pdf"]},"TableData":{"type":"object","description":"Table to generate at a bookmark position","properties":{"columns":{"type":"array","description":"Column definitions (headers, widths, alignment)","items":{"$ref":"#/components/schemas/ColumnDef"}},"rows":{"type":"array","description":"Table rows — each row is a list of cell values matching column order","items":{"type":"array","items":{"type":"string"}}},"style":{"$ref":"#/components/schemas/TableStyle","description":"Inline table styling (colors, fonts, borders)"},"templateStyle":{"type":"string","description":"LibreOffice table auto-format style name from the template","example":"Box List Blue"}},"required":["columns","rows"]},"TableStyle":{"type":"object","description":"Inline styling for tables (used when no template style is specified)","properties":{"headerBackground":{"type":"string","description":"Header row background color (hex)","example":"#003366"},"headerColor":{"type":"string","description":"Header row font color (hex)","example":"#FFFFFF"},"borderColor":{"type":"string","description":"Border color (hex)","example":"#CCCCCC"},"alternateRowColor":{"type":"string","description":"Alternate row background color (hex)","example":"#F5F5F5"},"fontSize":{"type":"integer","format":"int32","description":"Data cell font size in pt","example":10},"headerFontSize":{"type":"integer","format":"int32","description":"Header font size in pt","example":11},"boldHeader":{"type":"boolean","default":"true","description":"Bold header text"}}},"WatermarkConfig":{"type":"object","description":"Watermark configuration. Can be a simple string (just the text) or an object with text, fontSize, opacity, and color properties.","example":{"text":"DRAFT","fontSize":120,"opacity":0.15},"properties":{"text":{"type":"string","description":"Watermark text","example":"DRAFT"},"fontSize":{"type":"number","format":"float","description":"Font size in points. If not set, the text is auto-scaled to fill ~75% of the page diagonal.","example":100},"opacity":{"type":"number","format":"float","description":"Opacity from 0.0 (invisible) to 1.0 (fully opaque). Default: 0.15","example":0.15},"color":{"type":"string","description":"Color as hex string (e.g. '#999999'). Default: '#999999'","example":"#999999"}}},"JobInfo":{"type":"object","description":"Status information for an asynchronous document generation job","properties":{"jobId":{"type":"string","description":"Unique job identifier","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"status":{"type":"string","description":"Current job status","enum":["PENDING","PROCESSING","COMPLETED","FAILED"]},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the job was created"},"completedAt":{"type":"string","format":"date-time","description":"Timestamp when the job completed or failed"},"outputFormat":{"type":"string","description":"Requested output format","example":"PDF"},"errorMessage":{"type":"string","description":"Error message if the job failed"},"fileSizeBytes":{"type":"integer","format":"int64","description":"Size of the generated file in bytes","example":45321}}},"ComposeRequest":{"type":"object","description":"Request to compose a multi-part document from multiple templates/content blocks","properties":{"documents":{"type":"array","description":"List of document parts to combine","items":{"$ref":"#/components/schemas/DocumentPart"},"minItems":1},"outputFormat":{"type":"string","default":"PDF","description":"Output format","enum":["PDF","DOCX","ODT"]},"pageSettings":{"$ref":"#/components/schemas/PageSettings","description":"Global page settings applied to the composed document"},"watermark":{"$ref":"#/components/schemas/WatermarkConfig","description":"Watermark for the composed document. Can be a simple string or an object with text, fontSize, opacity, color.","example":"CONFIDENTIAL"},"password":{"type":"string","description":"Password to protect the composed document"},"contentAreas":{"type":"array","description":"Positioned content areas on the composed document (PDF output only)","items":{"$ref":"#/components/schemas/ContentArea"}},"stationery":{"$ref":"#/components/schemas/StationeryConfig","description":"Stationery (letterhead) PDF overlay applied to the composed document (PDF output only)"},"invoice":{"$ref":"#/components/schemas/InvoiceData","description":"ZUGFeRD invoice data to embed (PDF output only)"}},"required":["documents"]},"DocumentPart":{"type":"object","description":"A single document part within a compose request","properties":{"templateName":{"type":"string","description":"Template file name (pre-uploaded)","example":"cover-page.odt"},"templateBase64":{"type":"string","description":"Base64-encoded template file (alternative to templateName)"},"templateFilename":{"type":"string","description":"Original filename of the inline template","example":"deckblatt.odt"},"htmlContent":{"type":"string","description":"HTML content for this part"},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Field placeholders to replace"},"bookmarks":{"type":"object","additionalProperties":{"type":"string"},"description":"Bookmark positions for HTML injection"},"images":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ImageData"},"description":"Images to embed at bookmark positions"},"qrCodes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/QrCodeData"},"description":"QR codes to generate at bookmark positions"},"barcodes":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/BarcodeData"},"description":"Barcodes to generate at bookmark positions"},"tables":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/TableData"},"description":"Tables to generate at bookmark positions"},"markdownContent":{"type":"string","description":"Markdown content for this part (alternative to htmlContent)"},"markdownBookmarks":{"type":"object","additionalProperties":{"type":"string"},"description":"Markdown content at bookmark positions (key = bookmark name, value = Markdown)"},"markdownStyles":{"$ref":"#/components/schemas/MarkdownStyles","description":"Custom style mapping for Markdown elements"},"pageBreakBefore":{"type":"boolean","default":"true","description":"Insert a page break before this part"}}},"ValidateApiKeyRequest":{"type":"object","properties":{"apiKey":{"type":"string","description":"API key to validate","example":"dk_live_..."}}},"TenantSummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"plan":{"type":"string"},"rateLimitPerMinute":{"type":"integer","format":"int32"}}},"ValidateApiKeyResponse":{"type":"object","properties":{"valid":{"type":"boolean","description":"Whether the API key is valid","example":true},"message":{"type":"string","description":"Human-readable validation result","example":"API key is valid."},"tenant":{"$ref":"#/components/schemas/TenantSummary","description":"Associated tenant details when the API key is valid"}}},"UsageRecord":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time"},"tenantId":{"type":"string"},"tenantName":{"type":"string"},"endpoint":{"type":"string"},"method":{"type":"string"},"durationMs":{"type":"integer","format":"int64"},"responseSizeBytes":{"type":"integer","format":"int64"},"statusCode":{"type":"integer","format":"int32"}}}}}}